From a7c056c512484962dda3b0574dc9ff11444e5e9c Mon Sep 17 00:00:00 2001 From: imccyu <276526105+imccyu@users.noreply.github.com> Date: Mon, 10 Aug 2026 23:35:06 +0800 Subject: [PATCH 01/36] docs(release): propose three independent npm publish sequences packages/, vendor/, and native/ carry different version baselines and change at different times, so each releases on its own bump sequence, tag prefix, and workflow. Records the vendor change judgement (per-package tags as the last-published pointer), the registry-state publish rule that makes re-runs idempotent, and the workspace:^ prerequisite for publishing at any version other than the current 0.0.1. English counterpart and pairing record follow once the Chinese text is reviewed. --- .../2026-08-10-npm-release-sequences.zh.md | 186 ++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 .agents/notes/proposed/process/2026-08-10-npm-release-sequences.zh.md diff --git a/.agents/notes/proposed/process/2026-08-10-npm-release-sequences.zh.md b/.agents/notes/proposed/process/2026-08-10-npm-release-sequences.zh.md new file mode 100644 index 0000000000..836b5e863b --- /dev/null +++ b/.agents/notes/proposed/process/2026-08-10-npm-release-sequences.zh.md @@ -0,0 +1,186 @@ +# Agent Note: 三条独立序列的私有 NPM 发布 + +Status: proposed + +[English](2026-08-10-npm-release-sequences.md) | 中文 + +## 问题 + +这个仓库有三组互不相干的可发布包,但没有任何发布通道把它们送上 registry。 + +`packages/*/*` 与 `apps/*` 组成 `@deepseek-ai/dsh` 的运行时闭包;`vendor/*` 是九个 rescope 过的 Cordis 框架包,各自带着上游的版本号;`native/landlock-run/packages/*` 是 Linux 平台包,已有自己的 `landlock-run-release.yml`。三组的版本基线、变更节奏和构建要求都不同:dsh 随产品迭代,vendor 只在同步上游或改动本地修改时才动,native 需要 musl 工具链和逐架构构建。把它们塞进一条发布流水线,等于每次产品发版都要重发框架和原生二进制。 + +当前状态还有两处硬门。全部 217 个 workspace manifest 都是 `private: true`,直接 `npm publish` 发不出去。更隐蔽的是 933 条 dsh 兄弟包之间硬写的 `peerDependencies: "^0.0.1"`:`pnpm pack` 只替换 `workspace:` 协议,不动语义范围,而 `^0.0.1` 等于 `>=0.0.1 <0.0.2`——发 `0.0.2` 落不进去,发 `0.0.1-rc.1` 也落不进去(semver 规定不带预发布段的范围排除预发布版本)。这 933 条至今没出事,只因为版本一直停在 `0.0.1`。 + +本仓已有的 `scripts/publish-npm-baseline.ts` 是本机发布脚本:它把 pack 与 publish 放进同一个进程,需要人工在本机完成认证与重试,且把 vendor 排除在发布集之外。它不能作为 CI 发布的基础,但其中的 tarball payload 校验与已安装产物探针是验证过的零件。 + +## 提案 + +### 三条独立序列 + +`packages/`、`vendor/`、`native/` 各自一条 bump 序列、各自一次发布,不共享版本号、不共享触发、不互相等待。发 dsh 不重发 vendor,发 vendor 不重发 native。 + +| 序列 | 成员 | 版本基线 | tag | workflow | +|---|---|---|---|---| +| dsh | `packages/*/*` + `apps/*`(`@deepseek-ai/dsh` 与 `@deepseek-ai/dsh-frontend`) | 全族一个 `0.0.x` | `dsh-v<版本>` | `release.yml`(新增) | +| vendored framework | `vendor/*` 九个包 | 每包各自的上游版本线 | `vendor-<包名>-v<版本>`(每包一个) | `release-vendor.yml`(新增) | +| native | `native/landlock-run/packages/*` | 自己的 `0.0.x` | `landlock-run-v<版本>` | `landlock-run-release.yml`(现状不动) | + +三组一律发到 npmjs.com 的 `@deepseek-ai` scope 下的**私有包**(`npm publish --access restricted`)。native 三个包现在写的是 `access: public`,要改成 `restricted`。 + +### 版本由本地命令写进仓库,CI 只核对与上传 + +每条序列有一条 `bump and commit` 命令:算出目标版本 → 写进相关 manifest → `pnpm install --lockfile-only` → 立刻自检 → `git add` manifest 与 lockfile → commit。发布版本因此在仓库里查得到,不存在「发出去的是哪个版本说不清楚」。tag 由人工在合入 master 后打,CI 不写仓库、不需要写权限。 + +dsh 序列全族共用一个版本,接受 `major | minor | patch | x.y.z` 三种入参与显式版本号。先用 `0.0.1-rc.1` 这类预发布号把 pack、仓外安装探针、真实私有发布跑通一遍,验证通过后再发 `0.0.1`、`0.0.2` 这样的数字版本。dist-tag 沿用本仓 `landlock-run-release.yml` 已有的判定:版本带预发布段就 `--tag next`,否则进 `latest`。 + +### vendor:谁改了谁发版,tag 就是账本 + +vendor 九包加了 scope 之后与上游脱钩,但保留各自的版本线。发布版本 = 去掉预发布段后 patch+1,首发目标: + +| 包 | 上游版本 | 首发版本 | +|---|---|---| +| `@deepseek-ai/cordis` | 4.0.0-rc.7 | 4.0.1 | +| `@deepseek-ai/cordis-plugin-loader` | 1.0.0-rc.5 | 1.0.1 | +| `@deepseek-ai/cosmokit` | 1.8.1 | 1.8.2 | +| `@deepseek-ai/schemastery` | 3.18.0 | 3.18.1 | +| `@deepseek-ai/cordis-plugin-hmr` | 1.0.15 | 1.0.16 | +| `@deepseek-ai/cordis-plugin-include` | 1.0.4 | 1.0.5 | +| `@deepseek-ai/cordis-plugin-timer` | 1.1.2 | 1.1.3 | +| `@deepseek-ai/cordis-plugin-group` | 1.0.0 | 1.0.1 | +| `@deepseek-ai/cordis-plugin-logger-console` | 1.0.0 | 1.0.1 | + +只发改动过的包。变更判据不引入新的状态文件:**每包一个 tag,tag 就是「上次发布到哪个 commit」的记录**。bump 对每个包取最新的 `vendor-<包名>-v*` tag,`git diff <该 tag>..HEAD -- vendor/<目录>` 有差异就 patch+1,没差异就跳过;查不到 tag 就按上表首发。差异只看会进 tarball 的路径(复用 `scripts/publication-payload.ts` 的 `files` 规则),改动 vendor 内的注释不触发发版。 + +tag 只是 commit 指针,不是「已发布」的证明——打了 tag 而 publish 失败的情况必须能识别。所以 bump 还要向 registry 核对「tag 所指版本确实存在」,不一致时明确失败交人处理,不让脚本猜。私有包查询需要鉴权,本机未登录时跳过这条核对,CI 里强制执行。 + +vendor 九包**内部**的依赖范围不用改:`^1.8.1` 容纳 `1.8.2`、`^1.0.0-rc.5` 容纳 `1.0.1`,patch+1 永远落在范围内。 + +### publish 只在 GitHub 执行,用 registry 状态决定发什么 + +发布只从 GitHub Actions 执行,没有本机发布路径。这让「向 registry 核对」成为 CI 里的强制步骤,不需要为本机未鉴权的情况留旁路。 + +publish 不读 tag、不读任何清单,对发布集里每个包比较 manifest 版本与 registry 上的已发布状态,按三态处置: + +| 状态 | 处置 | +|---|---| +| registry 上没有该版本 | 发布 | +| 已有该版本,且 tarball 的 sha512 与 registry 记录的 `dist.integrity` 相同 | 跳过,属于同一批产物的重跑 | +| 已有该版本,但 integrity 不同 | 失败退出,报「内容已变但版本未 bump」 | + +第三态是这条规则的目的:它拦住「改了代码却没 bump 版本」。前两态给出的是幂等——同一个 artifact 重跑 publish 不会重复发布,也不需要人工挑拣包。 + +这条规则同时解决了一次发布事件产生多个 vendor tag、而 workflow 只能从一个 ref 触发的矛盾:workflow 不需要从 tag 推断本次该发哪些包。dsh 序列同构处理,它只有一个版本,差集要么全发要么全跳。 + +第三态依赖同输入构建可复现(同一 commit 两次 pack 得到相同字节)。这一点必须实测确认,不能假定:`pnpm run build` 的产物若嵌入绝对路径或时间,integrity 就会在内容未变时漂移,第三态会误报。落地前先在 CI 上对同一 commit 连跑两次 pack 比对 integrity;若不可复现,则把比较下沉到 tarball 内的逐文件内容哈希,并明确排除导致漂移的字段。 + + +### 一次性把 workspace 内部引用改成 `workspace:^` + +仓库里所有指向 workspace 成员的引用统一成 `workspace:^`,由 `pnpm pack` 在发布时替换成匹配目标版本的范围。 + +| 面 | 数量 | 效果 | +|---|---|---| +| dsh 兄弟包 `peerDependencies` | 933 | 发 `0.0.2` 或 `0.0.1-rc.1` 都自动得到匹配的范围 | +| 指向 vendor 的 dep / peer / devDep | 105 + 221 + 218 | vendor patch+1 后不需要改写 dsh 侧引用,范围也不会随 vendor 递增而过期 | + +`scripts/check-workspace-constraints.ts` 现在断言 vendor peer 与 dev 的范围相等,改后两边都是 `workspace:^`,断言仍成立但语义要随之更新。 + +这条是「发布期不做任何依赖改写」的前提:发布期只做一件事——pack 出字节。 + +### 发布族对象 + +领域里的实体是**发布族**:一组共享版本基线与 tag 前缀、可整体发布的包。新增一族等于新增一份族描述加一条 workflow lane,不改核心。 + +| 对象 | 职责 | +|---|---| +| `ReleaseFamily` | 一族的身份:成员发现规则、版本策略、tag 命名、publish 目标。新增发布族在此落地 | +| `ReleaseMember` | 一个可发布包:目录、manifest、族归属、发布顺序位次 | +| `VersionPolicy` | 版本从哪来。`SharedSemver`(dsh:全族一个版本)与 `PerPackageChanged`(vendor:按 tag 判变更、去预发布段后 patch+1) | +| `ReleaseSet` | 一族成员的拓扑序,按 `dependencies` 排、同层按包名排,保证确定性 | +| `PackedBundle` | tarball 集合 + `publish-order.txt` + 元数据清单,是 pack 与 publish 之间唯一的交接物 | +| `PublishTarget` | registry、access、dist-tag、凭据来源。dist-tag 由版本形态派生 | +| `VersionInvariant` | 族内版本自洽;publish 必须从对应 tag 跑;tag 版本等于包版本;待发版本不得已存在于 registry | +| `PayloadInvariant` | tarball 内容校验,复用 `scripts/publication-payload.ts` | +| `InstalledProbe` | 仓外临时 consumer 从 tarball 安装后,用普通 Node 驱动已安装入口:`dsh --version`、`dsh --dump-default-config`、起一次 TUI 到就绪后退出。实现从 `scripts/publish-npm-baseline.ts` 搬运复用 | + +### workflow 形状:一次性 pack 全部,再统一 publish + +照参照流程(node-addon-require-builtin 的 `release.yml` 与 `scripts/pack-release.mjs`)的形状:`pack` job 一趟遍历整个发布集,逐包 `pnpm --dir <目录> pack --pack-destination <同一个目录>`,写出 `publish-order.txt`,整个目录作为**一份** artifact 上传;`publish` job 下载那一份 artifact,按 `publish-order.txt` 逐个 `npm publish`。发布集是一个整体,不存在「一半的包发出去了、另一半还在构建」。 + +`pack` job 无凭据:install → verify → build → pack → 打包后安装验证 → upload-artifact。`publish` job 挂 `environment: npm-publish` 人工审批,只 `setup-node` 加 `download-artifact`,**不 checkout、不 build**,上传的就是 pack 出来的同一份字节。checkout 用 `fetch-depth: 0`,vendor 的变更判据需要历史与 tag。 + +`environment` 是整条流程唯一的刹车:pack 无凭据、可随意排练;只有 publish 会停在审批上。GitHub 侧需要 `NPM_TOKEN` secret(对该 scope 有发布权限的 automation token)与 `npm-publish` environment(required reviewers,允许的 tag 限制为 `dsh-v*`、`vendor-*`、`landlock-run-v*`)。 + +### PR 阶段跑到 pack 为止 + +参照流程只有 `workflow_dispatch`,PR 上什么都验证不了。本仓在 `pull_request` 上跑完整的 pack:install → verify → build → 逐包 pack → 上传 tarball artifact。它证明的是「这个发布集现在能完整打出来」,无凭据、不碰任何 registry,fork 发来的 PR 也能跑。产物本身的正确性由既有测试覆盖,不在 PR 这一层重复。 + +发布路径的测试走 master:`push: master` 跑同一套 pack 排练作为合入后回归,`workflow_dispatch` 带 `publish: true` 从 tag 走真实发布。 + + + +### 仓库改造项 + +| 项 | 内容 | +|---|---| +| 发布集 manifest | 去掉 `private: true`,补 `publishConfig`(`access: restricted`、`registry`) | +| 发布集边界 | 一份显式的族与成员清单,脚本据此发现成员并校验闭包内的包都在清单里,不猜 | +| 依赖协议 | workspace 内部引用统一 `workspace:^`,并更新 `check-workspace-constraints.ts` | +| 根 `AGENTS.md` | 现在写着 vendored 包是 rescope 过且 `private: true`,vendor 要发布,这条约定要改 | +| `vendor/README.md` | manifest 表补记上游版本,与我们发布的版本区分开 | +| native 三包 | `publishConfig.access` 从 `public` 改 `restricted` | + +### 与既有提案的关系 + +本 Note 取代 [以产物为先的 NPM 基线发布](2026-08-04-artifact-first-npm-baseline-publication.zh.md) 中的版本方案与发布集边界两部分:那篇的 `-<时间戳>-<短 SHA>` 预发布版本与 `dev-` dist-tag 不再采用,vendor 也不再排除在发布集之外。两篇一致的部分保留:pack 与 publish 分离、publish 只消费已验证的 tarball、payload 与安装后探针作为发布门。 + +## 考虑过的替代方案 + +**`-<时间戳>-<短 SHA>` 版本号。** 曾计划用它做持续 dev 发布。它与「版本必须落进代码库」冲突:版本内嵌 commit SHA,而把版本写回 manifest 会产生新的 commit,SHA 只能指向被发布的父 commit,链条要靠约定解释。改用数字版本递增后,`0.0.1-rc.1` 这类预发布号已经足够覆盖「先验证再正式发」的需求。 + +**用 `vendor/published.json` 账本记录每包的已发版本与 commit。** 这是 tag 方案之前的设计,需要新增一份状态文件并保证它与 registry 不漂移。per-package tag 提供同样的 commit 指针,且 tag 本来就要打,不引入第二处状态。 + +**事件级 tag(`vendor-r1`、`vendor-r2`)。** 为「一次发布事件多个包版本」准备的。改用 registry 差集决定发布集之后,workflow 不再需要从 tag 推断本次发布哪些包,per-package tag 就够用,而且每个 tag 携带的是它自己那个包的真实版本。 + +**vendor 九包统一到 `4.0.x` 一条线。** 省掉变更检测,但 cosmokit 会从 `1.8.1` 跳到 `4.0.1`,上游血缘全部丢失;且九包内部的上游依赖范围(`^1.8.1` 之类)会立刻失配,必须改写 vendored manifest。 + +**vendor 每次全部 patch+1,不做变更检测。** 最省事,代价是没有改动的包也拿到新版本号、内容与上一版逐字节相同。tag 方案让变更检测的成本降到「取一个 tag 加一次 diff」,不值得为省这点而让版本号虚涨。 + +**只按版本号判断是否已发布,不比对内容。** 参照流程根本不查 registry,publish 直接逐个上传,重复版本由 npm 报错拦下。只按版本号跳过则会漏掉「改了代码没 bump」这一类,而这是唯一会安静地把旧字节留在 registry 上的错误。代价是引入对 registry 的查询与对构建可复现性的依赖。 + +**只做打包后安装验证,不起本地 registry。** 参照流程就是这样:解包 tarball 组树、普通 Node 驱动。它绕过版本范围解析,理论上验证不了「200 多个互相依赖的包能不能从 registry 装起来」。曾提议在 CI 里起本地 registry 补这一层,被否:产物验证已由既有测试覆盖,发布路径的验证放在 master workflow 的排练里,PR 只需证明发布集能完整打出来。 + +**以 `scripts/publish-npm-baseline.ts` 为基础扩展。** 它是本机发布脚本,把 pack 与 publish 放在同一进程,与「无凭据 pack、受保护 publish」的分离相反。它验证过的零件(payload 校验、已安装产物探针)搬运复用,避免 `pnpm run duplication` 判重复。 + +**发布全部 217 个 workspace 包。** 发布集定为入口闭包。`support/`、`examples/` 这类包进 registry 只扩大攻击面与维护面,没有消费方。 + +**一个 workflow 用 `family` 输入选择序列。** 两套版本模型塞进一个文件会让 concurrency group、tag 前缀、排练触发条件全部分叉成条件表达式。一族一个文件更短也更好读。 + +**在发布期改写依赖范围。** 与一次性改成 `workspace:^` 相比,改写逻辑只在 CI 执行过,本机 `pnpm install` 看不见它是否正确,且每次发布都要重跑一遍。 + +**CI 里执行 bump 并把版本推回仓库。** 需要给 workflow 仓库写权限,且发布分支上的版本提交会与人的提交竞争。参照流程把 bump 与 commit 留在本地命令,CI 只核对与上传。 + +## 验收标准 + +1. 三条序列各自可独立发布:发 dsh 不改动 vendor 与 native 的任何 manifest,反之亦然。 +2. `pnpm release:dsh <版本>` 一条命令完成 bump 与 commit,产出的 commit 含全族 manifest 与 lockfile,且立刻自检通过。 +3. `pnpm release:vendor` 只对「自其 `vendor-<包名>-v*` tag 以来 tarball 内容有变化」的包 patch+1,无变化的包 manifest 不被改动。 +4. `pull_request` 上跑完整 pack 并产出 tarball artifact,无凭据、不访问真实 registry,fork 的 PR 也能跑。 +5. `push: master` 跑同一套 pack 排练;真实发布只能由 `workflow_dispatch` 带 `publish: true` 从对应 tag 触发。 +6. publish 重跑同一 artifact 不重复发布已存在的版本;当某个版本已存在而 tarball integrity 不同时,publish 失败并指明是哪个包。 +7. 仓外临时 consumer 安装 `@deepseek-ai/dsh@0.0.1-rc.1` 后,用普通 Node 能跑通 `--version`、`--dump-default-config` 与一次 TUI 启动。 +8. 所有 workspace 内部引用为 `workspace:^`,且 pack 出的 tarball 里没有任何 `workspace:` 残留、没有指向不存在版本的范围。 +9. 发布集内没有 `private: true`,每个成员都有 `publishConfig.access: restricted`。 + +## 风险 + +**tag 与 registry 漂移。** 打了 tag 但 publish 失败,会让下一次 bump 误判该包已发布。缓解手段是 bump 向 registry 核对 tag 所指版本,不一致就失败退出;但本机未登录私有 registry 时这条核对被跳过,此时误判只能由 CI 的同一条核对拦下。 + +**变更判据依赖 tag 可见。** shallow clone 或未拉取 tag 会让 vendor 的判据失效并退化成「全部首发」。`fetch-depth: 0` 是这条判据的前提,不是优化。 + +**`workspace:^` 改动面大。** 一次触及 1477 处依赖声明。它不改变本机解析行为(pnpm 本来就从 workspace 解析),但会改变发布出去的范围写法,且要同步更新 workspace 约束门。 + +**私有包的可见性代价。** `--access restricted` 之后,任何消费方(含 CI、沙箱 e2e、外部使用者)都必须持有 scope 凭据才能安装。native 三包从 public 转 restricted 会切断现有匿名安装路径。 + +**首发一次性放大。** vendor 首发九包、dsh 首发全闭包,任何 payload 缺陷都会在同一次发布里暴露。用 `0.0.1-rc.1` 先跑一遍完整链路是唯一的缓解手段,正式版本号留给验证通过之后。 From 8cd38945f192d484f4011d33971aa35616214469 Mon Sep 17 00:00:00 2001 From: imccyu <276526105+imccyu@users.noreply.github.com> Date: Mon, 10 Aug 2026 23:35:23 +0800 Subject: [PATCH 02/36] feat(release): add release family metadata, pack, verify, and publish A release family owns its member discovery, version baseline, tag naming, and packed-payload rule; the dsh family shares one version across packages/ and apps/, while every vendor/ package keeps its own version line. Publish order is topological over runtime dependencies so no package reaches the registry before one it depends on. pack packs the whole family into one directory and records the upload order; publish decides per package against the registry, skipping a version whose published tarball has the same integrity and failing when it differs, which is what makes re-running publish over one artifact safe. The vendored packages keep upstream's payload: their manifests export ./src/*, so the harness rule that rejects sources and declaration maps would publish an export map pointing at absent files. --- package.json | 3 + scripts/release/families.ts | 282 ++++++++++++++++++++++++++++++++++++ scripts/release/pack.ts | 86 +++++++++++ scripts/release/publish.ts | 130 +++++++++++++++++ scripts/release/verify.ts | 69 +++++++++ 5 files changed, 570 insertions(+) create mode 100644 scripts/release/families.ts create mode 100644 scripts/release/pack.ts create mode 100644 scripts/release/publish.ts create mode 100644 scripts/release/verify.ts diff --git a/package.json b/package.json index 77816c319d..32138d03e8 100644 --- a/package.json +++ b/package.json @@ -121,6 +121,9 @@ "doc-sync": "tsx scripts/run-gates.ts doc-sync", "hygiene": "pnpm run rescope-vendor:check && pnpm run knip && pnpm run publint && pnpm run constraints && pnpm run verify-package-invariants && pnpm run verify-built-package-invariants && pnpm run verify-cordis-config && pnpm run verify-node-next-types && pnpm run verify-runtime-closure && pnpm run verify-vendored-links", "publish:npm-baseline": "tsx scripts/publish-npm-baseline.ts", + "release:verify": "tsx scripts/release/verify.ts", + "release:pack": "tsx scripts/release/pack.ts", + "release:publish": "tsx scripts/release/publish.ts", "dsh": "node --import tsx/esm apps/cli/src/bin.ts", "demo:headless": "node --import tsx/esm apps/cli/src/bin.ts --profile headless", "demo:code-mode": "node scripts/demo-code-mode.mjs", diff --git a/scripts/release/families.ts b/scripts/release/families.ts new file mode 100644 index 0000000000..e989e54525 --- /dev/null +++ b/scripts/release/families.ts @@ -0,0 +1,282 @@ +/** + * The three independent publish sequences this repository releases from + * (`packages/` + `apps/`, `vendor/`, and `native/`) and the two this module + * owns: `dsh` and `vendor`. Each family carries its own version baseline, tag + * naming, and publish set, so releasing one never republishes another + * ([rationale](../../.agents/notes/proposed/process/2026-08-10-npm-release-sequences.md)). + * + * The family dimension lives here only. A new sequence adds a subclass and a + * `releaseFamilies()` entry; nothing else in the release scripts branches on it. + */ + +import { globSync, readFileSync } from 'node:fs' +import { resolve } from 'node:path' +import { hasTypeRTRemoteNavigation, validateTarballPayload } from '../publication-payload.ts' + +/** Dependency sections that constrain publish order: a consumer must publish after its dependency. */ +const ORDER_SECTIONS = ['dependencies', 'optionalDependencies'] as const + +/** The workspace root manifest, which is never a release member. */ +const WORKSPACE_ROOT_PACKAGE = '@deepseek-ai/dsh-root' + +/** One publishable package of a release family. */ +export interface ReleaseMember { + /** Repository-relative package directory, for example `packages/core/session`. */ + readonly directory: string + /** Package name from its manifest. */ + readonly name: string + /** Package version from its manifest. */ + readonly version: string + /** The parsed manifest, for payload policy and publication checks. */ + readonly manifest: Readonly> +} + +/** + * Read and parse a JSON file. + * @param path - absolute file path. + * @returns The parsed object. + */ +function readManifest(path: string): Record { + const parsed: unknown = JSON.parse(readFileSync(path, 'utf8')) + if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) { + throw new Error(`${path} is not a JSON object`) + } + return parsed as Record +} + +/** + * Read a required string field. + * @param manifest - parsed manifest. + * @param field - field name. + * @param context - manifest path for the error message. + * @returns The field value. + */ +function requireString(manifest: Record, field: string, context: string): string { + const value = manifest[field] + if (typeof value !== 'string' || value === '') throw new Error(`${context} must declare a string ${field}`) + return value +} + +/** A release sequence: its members, its version baseline, and its tag naming. */ +export abstract class ReleaseFamily { + /** Workflow-facing identifier, also the `--family` argument. */ + abstract readonly id: string + + /** Glob patterns, relative to the repository root, that select this family's manifests. */ + abstract readonly patterns: readonly string[] + + /** Git tag prefix this family publishes from. */ + abstract readonly tagPrefix: string + + /** + * Discover this family's members. + * @param root - repository root. + * @returns Members sorted by directory, with names validated and deduplicated. + */ + members(root: string): ReleaseMember[] { + const manifestPaths = globSync([...this.patterns], { cwd: root }).sort() + if (manifestPaths.length === 0) throw new Error(`release family ${this.id} matched no manifests`) + + const members: ReleaseMember[] = [] + const seen = new Set() + for (const manifestPath of manifestPaths) { + const normalized = manifestPath.replaceAll('\\', '/') + const manifest = readManifest(resolve(root, manifestPath)) + const name = requireString(manifest, 'name', normalized) + const version = requireString(manifest, 'version', normalized) + if (name === WORKSPACE_ROOT_PACKAGE) throw new Error(`${normalized} selected the workspace root`) + if (!name.startsWith('@deepseek-ai/')) throw new Error(`${normalized} must name an @deepseek-ai package`) + if (seen.has(name)) throw new Error(`${name} appears twice in release family ${this.id}`) + seen.add(name) + members.push({ + directory: normalized.slice(0, normalized.length - '/package.json'.length), + name, + version, + manifest, + }) + } + return members + } + + /** + * Order members so every package publishes after the family members it depends on. + * @param members - this family's members. + * @returns The same members in publish order; ties break by name for determinism. + */ + publishOrder(members: readonly ReleaseMember[]): ReleaseMember[] { + const byName = new Map(members.map(member => [member.name, member])) + const ordered: ReleaseMember[] = [] + const placed = new Set() + const visiting = new Set() + + const visit = (member: ReleaseMember, path: readonly string[]): void => { + if (placed.has(member.name)) return + if (visiting.has(member.name)) { + throw new Error(`dependency cycle in release family ${this.id}: ${[...path, member.name].join(' -> ')}`) + } + visiting.add(member.name) + for (const dependency of this.orderEdges(member, byName)) { + visit(dependency, [...path, member.name]) + } + visiting.delete(member.name) + placed.add(member.name) + ordered.push(member) + } + + for (const member of [...members].sort((left, right) => left.name.localeCompare(right.name))) { + visit(member, []) + } + return ordered + } + + /** + * The family members one member depends on at runtime. + * @param member - the dependent member. + * @param byName - every family member by package name. + * @returns Dependencies inside this family, sorted by name. + */ + private orderEdges(member: ReleaseMember, byName: ReadonlyMap): ReleaseMember[] { + const edges: ReleaseMember[] = [] + for (const section of ORDER_SECTIONS) { + const dependencies = member.manifest[section] + if (dependencies === null || typeof dependencies !== 'object' || Array.isArray(dependencies)) continue + for (const name of Object.keys(dependencies)) { + const dependency = byName.get(name) + if (dependency !== undefined && dependency.name !== member.name) edges.push(dependency) + } + } + return edges.sort((left, right) => left.name.localeCompare(right.name)) + } + + /** + * Assert this family's version baseline holds across its members. + * @param members - this family's members. + */ + abstract verifyVersions(members: readonly ReleaseMember[]): void + + /** + * The tag a member publishes from. + * @param member - the member being published. + * @returns The full tag name, without `refs/tags/`. + */ + abstract tagFor(member: ReleaseMember): string + + /** + * Check what a member's packed tarball carries. + * @param member - the packed member. + * @param files - every path inside its tarball. + */ + abstract validatePayload(member: ReleaseMember, files: readonly string[]): void +} + +/** `packages/*` and `apps/*`: one shared version across the whole family. */ +class DshFamily extends ReleaseFamily { + readonly id = 'dsh' + readonly patterns = ['packages/*/*/package.json', 'apps/*/package.json'] as const + readonly tagPrefix = 'dsh-v' + + /** + * Require one version across the family, the way a single tag can name it. + * @param members - this family's members. + */ + verifyVersions(members: readonly ReleaseMember[]): void { + const versions = new Set(members.map(member => member.version)) + if (versions.size !== 1) { + const detail = members.map(member => `${member.directory}: ${member.version}`).join('\n') + throw new Error(`dsh release members must share one version:\n${detail}`) + } + } + + /** + * The single family tag. + * @param member - any family member; all carry the same version. + * @returns `dsh-v`. + */ + tagFor(member: ReleaseMember): string { + return `${this.tagPrefix}${member.version}` + } + + /** + * Reject source and declaration-map members, the repository's publication policy. + * @param member - the packed member. + * @param files - every path inside its tarball. + */ + validatePayload(member: ReleaseMember, files: readonly string[]): void { + validateTarballPayload(files, member.name, { + typeRTRemoteNavigation: hasTypeRTRemoteNavigation(member.manifest), + }) + } +} + +/** `vendor/*`: every package keeps its own version line, so every package has its own tag. */ +class VendorFamily extends ReleaseFamily { + readonly id = 'vendor' + readonly patterns = ['vendor/*/package.json'] as const + readonly tagPrefix = 'vendor-' + + /** + * Accept independent versions; only reject a version this repository cannot publish. + * @param members - this family's members. + */ + verifyVersions(members: readonly ReleaseMember[]): void { + for (const member of members) { + if (!/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(member.version)) { + throw new Error(`${member.directory} has an unpublishable version: ${member.version}`) + } + } + } + + /** + * The member's own tag, because one vendor release can carry several versions. + * @param member - the member being published. + * @returns `vendor--v`. + */ + tagFor(member: ReleaseMember): string { + return `${this.tagPrefix}${member.name.replace('@deepseek-ai/', '')}-v${member.version}` + } + + /** + * Require the payload the vendored manifest declares, including upstream's + * `src` tree and declaration maps. + * + * The harness policy that rejects both does not apply here: these manifests + * export `./src/*` for source navigation, so dropping `src` would publish a + * package whose export map points at absent files. What must hold instead is + * that every path the manifest selects is present, which `files` already + * decides and `pnpm pack` already enforces. + * @param member - the packed member. + * @param files - every path inside its tarball. + */ + validatePayload(member: ReleaseMember, files: readonly string[]): void { + if (files.length === 0) throw new Error(`${member.name} packed an empty tarball`) + } +} + +/** Every release family this module owns, in workflow order. */ +export function releaseFamilies(): readonly ReleaseFamily[] { + return [new DshFamily(), new VendorFamily()] +} + +/** + * Resolve a family by its `--family` identifier. + * @param id - family identifier. + * @returns The family. + */ +export function releaseFamily(id: string): ReleaseFamily { + const family = releaseFamilies().find(candidate => candidate.id === id) + if (family === undefined) { + const known = releaseFamilies().map(candidate => candidate.id).join(', ') + throw new Error(`unknown release family ${id}; expected one of ${known}`) + } + return family +} + +/** + * The npm tarball filename `pnpm pack` writes for a member. + * @param member - the packed member. + * @returns The tarball filename. + */ +export function tarballName(member: ReleaseMember): string { + const unscoped = member.name.startsWith('@') ? member.name.slice(1).replace('/', '-') : member.name + return `${unscoped}-${member.version}.tgz` +} diff --git a/scripts/release/pack.ts b/scripts/release/pack.ts new file mode 100644 index 0000000000..1b128817b9 --- /dev/null +++ b/scripts/release/pack.ts @@ -0,0 +1,86 @@ +/** + * Pack one release family's whole publish set into a single directory, in + * publish order, and record that order for the publish step. + * + * The pack step is the release boundary: it runs without credentials, produces + * every tarball from one commit, and hands the publish step exactly those bytes + * ([rationale](../../.agents/notes/proposed/process/2026-08-10-npm-release-sequences.md)). + */ + +import { spawnSync } from 'node:child_process' +import { existsSync, mkdirSync, rmSync, writeFileSync } from 'node:fs' +import { join, resolve } from 'node:path' +import { parseArgs } from 'node:util' +import { releaseFamily, tarballName, type ReleaseFamily, type ReleaseMember } from './families.ts' + +/** Where pack output lands when `--out` is omitted. */ +const DEFAULT_OUTPUT = 'dist/npm' + +/** Name of the file the publish step reads to learn the upload order. */ +export const PUBLISH_ORDER_FILE = 'publish-order.txt' + +/** + * Run a command, inheriting stdio, and fail the process on a non-zero exit. + * @param command - executable name. + * @param args - command arguments. + */ +function run(command: string, args: readonly string[]): void { + const result = spawnSync(command, [...args], { stdio: 'inherit' }) + if (result.error !== undefined) throw result.error + if (result.status !== 0) throw new Error(`${command} ${args.join(' ')} exited with ${String(result.status)}`) +} + +/** + * List a tarball's members. + * @param tarball - absolute tarball path. + * @returns Every path inside the archive. + */ +function tarballFiles(tarball: string): string[] { + const result = spawnSync('tar', ['-tzf', tarball], { encoding: 'utf8' }) + if (result.error !== undefined) throw result.error + if (result.status !== 0) throw new Error(`tar -tzf ${tarball} exited with ${String(result.status)}:\n${result.stderr}`) + return result.stdout.split('\n').filter(line => line !== '') +} + +/** + * Pack one member and check what its tarball carries. + * @param family - the release family being packed. + * @param member - the member to pack. + * @param destination - absolute output directory. + * @returns The tarball filename. + */ +function packMember(family: ReleaseFamily, member: ReleaseMember, destination: string): string { + run('pnpm', ['--dir', member.directory, 'pack', '--pack-destination', destination]) + + const filename = tarballName(member) + const tarball = join(destination, filename) + if (!existsSync(tarball)) throw new Error(`${member.name} produced no tarball at ${tarball}`) + family.validatePayload(member, tarballFiles(tarball)) + return filename +} + +/** Pack the family named by `--family` into `--out`. */ +function main(): void { + const { values } = parseArgs({ + options: { family: { type: 'string' }, out: { type: 'string' } }, + allowPositionals: false, + }) + if (values.family === undefined) throw new Error('usage: pack.ts --family [--out dist/npm]') + + const family = releaseFamily(values.family) + const root = process.cwd() + const destination = resolve(root, values.out ?? DEFAULT_OUTPUT) + const members = family.publishOrder(family.members(root)) + family.verifyVersions(members) + + rmSync(destination, { recursive: true, force: true }) + mkdirSync(destination, { recursive: true }) + + const order: string[] = [] + for (const member of members) order.push(packMember(family, member, destination)) + writeFileSync(join(destination, PUBLISH_ORDER_FILE), `${order.join('\n')}\n`) + + console.log(`release pack: family ${family.id}, ${String(order.length)} tarball(s) in ${values.out ?? DEFAULT_OUTPUT}`) +} + +main() diff --git a/scripts/release/publish.ts b/scripts/release/publish.ts new file mode 100644 index 0000000000..68dae1701a --- /dev/null +++ b/scripts/release/publish.ts @@ -0,0 +1,130 @@ +/** + * Publish one packed release family from the tarballs the pack step produced. + * + * Publication is decided per package against the registry, never from a list of + * "what this release includes": a version the registry lacks is published, a + * version whose published tarball has the same integrity is skipped, and a + * version whose published tarball differs fails the run — that last case means + * the content changed without a version bump + * ([rationale](../../.agents/notes/proposed/process/2026-08-10-npm-release-sequences.md)). + * + * Skipping on identical integrity is what makes re-running the publish step over + * the same artifact safe. + */ + +import { spawnSync } from 'node:child_process' +import { createHash } from 'node:crypto' +import { readFileSync } from 'node:fs' +import { join, resolve } from 'node:path' +import { parseArgs } from 'node:util' +import { releaseFamily } from './families.ts' +import { PUBLISH_ORDER_FILE } from './pack.ts' + +/** npm access level for every package this repository publishes. */ +const ACCESS = 'restricted' + +/** What the registry knows about one version. */ +type RegistryState = + | { readonly kind: 'absent' } + | { readonly kind: 'present'; readonly integrity: string } + +/** + * Read a packed tarball's own manifest. + * @param tarball - absolute tarball path. + * @returns The packed `package.json` name and version. + */ +function packedIdentity(tarball: string): { name: string; version: string } { + const result = spawnSync('tar', ['-xOzf', tarball, 'package/package.json'], { encoding: 'utf8' }) + if (result.error !== undefined) throw result.error + if (result.status !== 0) throw new Error(`cannot read ${tarball}:\n${result.stderr}`) + const manifest: unknown = JSON.parse(result.stdout) + if (manifest === null || typeof manifest !== 'object') throw new Error(`${tarball} has no manifest`) + const { name, version } = manifest as Record + if (typeof name !== 'string' || typeof version !== 'string') throw new Error(`${tarball} manifest lacks name/version`) + return { name, version } +} + +/** + * The subresource integrity string npm records for a tarball. + * @param tarball - absolute tarball path. + * @returns A `sha512-` string. + */ +function integrityOf(tarball: string): string { + return `sha512-${createHash('sha512').update(readFileSync(tarball)).digest('base64')}` +} + +/** + * Ask the registry whether a version exists, and with what integrity. + * @param name - package name. + * @param version - package version. + * @returns The registry state for that version. + */ +function registryState(name: string, version: string): RegistryState { + const result = spawnSync('npm', ['view', `${name}@${version}`, 'dist.integrity', '--json'], { encoding: 'utf8' }) + if (result.error !== undefined) throw result.error + if (result.status !== 0) { + const output = `${result.stdout}${result.stderr}` + if (output.includes('E404') || output.includes('404 Not Found')) return { kind: 'absent' } + throw new Error(`npm view ${name}@${version} failed:\n${output}`) + } + const parsed: unknown = JSON.parse(result.stdout) + if (typeof parsed !== 'string' || parsed === '') { + throw new Error(`registry reported no dist.integrity for ${name}@${version}`) + } + return { kind: 'present', integrity: parsed } +} + +/** + * Publish one tarball. + * @param tarball - absolute tarball path. + * @param version - the version being published; a prerelease never takes `latest`. + */ +function publish(tarball: string, version: string): void { + const args = ['publish', tarball, '--access', ACCESS] + if (version.includes('-')) args.push('--tag', 'next') + const result = spawnSync('npm', args, { stdio: 'inherit' }) + if (result.error !== undefined) throw result.error + if (result.status !== 0) throw new Error(`npm publish ${tarball} exited with ${String(result.status)}`) +} + +/** Publish the family named by `--family` from the directory named by `--from`. */ +function main(): void { + const { values } = parseArgs({ + options: { family: { type: 'string' }, from: { type: 'string' } }, + allowPositionals: false, + }) + if (values.family === undefined || values.from === undefined) { + throw new Error('usage: publish.ts --family --from ') + } + + const family = releaseFamily(values.family) + const directory = resolve(process.cwd(), values.from) + const order = readFileSync(join(directory, PUBLISH_ORDER_FILE), 'utf8').split('\n').filter(line => line !== '') + + let published = 0 + let skipped = 0 + for (const filename of order) { + const tarball = join(directory, filename) + const { name, version } = packedIdentity(tarball) + const state = registryState(name, version) + if (state.kind === 'present') { + const local = integrityOf(tarball) + if (state.integrity !== local) { + throw new Error( + `${name}@${version} is already published with different content` + + `\n registry: ${state.integrity}\n packed: ${local}` + + '\nBump the version, or investigate why the build is not reproducible.', + ) + } + console.log(`release publish: ${name}@${version} already published, skipping`) + skipped += 1 + continue + } + publish(tarball, version) + published += 1 + } + + console.log(`release publish: family ${family.id}, ${String(published)} published, ${String(skipped)} already present`) +} + +main() diff --git a/scripts/release/verify.ts b/scripts/release/verify.ts new file mode 100644 index 0000000000..98988de18d --- /dev/null +++ b/scripts/release/verify.ts @@ -0,0 +1,69 @@ +/** + * Verify a release family's version baseline, and — when publishing — that the + * run comes from the family's tag and its members are publishable. + * + * Publication happens only from GitHub Actions, so the tag and publishability + * checks are gates on the workflow, not advisory local warnings + * ([rationale](../../.agents/notes/proposed/process/2026-08-10-npm-release-sequences.md)). + */ + +import { parseArgs } from 'node:util' +import { releaseFamily, type ReleaseFamily, type ReleaseMember } from './families.ts' + +/** + * Assert every member may be published: npm refuses a `private` package. + * @param members - the family's members. + */ +function verifyPublishable(members: readonly ReleaseMember[]): void { + const priv = members.filter(member => member.manifest.private === true) + if (priv.length > 0) { + throw new Error(`publishing requires removing "private": true from:\n${priv.map(member => member.directory).join('\n')}`) + } +} + +/** + * Assert the workflow runs from a tag this family publishes from, and that the + * tag names a version the family actually carries. + * @param family - the release family. + * @param members - the family's members. + * @param ref - the `GITHUB_REF` value. + */ +function verifyTag(family: ReleaseFamily, members: readonly ReleaseMember[], ref: string): void { + const prefix = 'refs/tags/' + if (!ref.startsWith(prefix)) { + throw new Error(`publishing release family ${family.id} requires running from a ${family.tagPrefix}* tag, got ${ref || '(no ref)'}`) + } + const tag = ref.slice(prefix.length) + if (!tag.startsWith(family.tagPrefix)) { + throw new Error(`tag ${tag} does not belong to release family ${family.id} (expected ${family.tagPrefix}*)`) + } + const expected = members.map(member => family.tagFor(member)) + if (!expected.includes(tag)) { + throw new Error(`tag ${tag} names no version this family carries; its members would tag as:\n${[...new Set(expected)].join('\n')}`) + } +} + +/** Run the verification for the family named by `--family`. */ +function main(): void { + const { values } = parseArgs({ + options: { family: { type: 'string' } }, + allowPositionals: false, + }) + if (values.family === undefined) throw new Error('usage: verify.ts --family ') + + const family = releaseFamily(values.family) + const members = family.members(process.cwd()) + family.verifyVersions(members) + + const publishing = process.env.RELEASE_PUBLISH === 'true' + if (publishing) { + verifyPublishable(members) + verifyTag(family, members, process.env.GITHUB_REF ?? '') + } + + const versions = [...new Set(members.map(member => member.version))] + const summary = versions.length === 1 ? versions[0] : `${String(versions.length)} versions` + console.log(`release verify: family ${family.id}, ${String(members.length)} member(s), ${summary}${publishing ? ', publish gates passed' : ''}`) +} + +main() From 4e91230dd698bc2f5890661ebf10c7516c9c148d Mon Sep 17 00:00:00 2001 From: imccyu <276526105+imccyu@users.noreply.github.com> Date: Mon, 10 Aug 2026 23:35:36 +0800 Subject: [PATCH 03/36] ci(release): pack on pull requests and publish from family tags Each sequence gets its own workflow so the two version models never meet in one file. Pack runs without credentials on every pull request and master push, so a pull request proves the whole publish set still packs; publication is a manual dispatch guarded by the npm-publish environment, runs only from that family's tag, and never builds - it uploads the bytes pack produced. --- .github/workflows/release-vendor.yml | 125 ++++++++++++++++++++++++++ .github/workflows/release.yml | 127 +++++++++++++++++++++++++++ 2 files changed, 252 insertions(+) create mode 100644 .github/workflows/release-vendor.yml create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release-vendor.yml b/.github/workflows/release-vendor.yml new file mode 100644 index 0000000000..b83547b560 --- /dev/null +++ b/.github/workflows/release-vendor.yml @@ -0,0 +1,125 @@ +# Pack and publish the vendored framework sequence: the nine rescoped Cordis +# packages under vendor/, each on its own version line. This sequence releases +# independently of dsh and of the native packages. +# +# Pack runs without credentials on every pull request and master push. +# Publication is a manual dispatch from a vendor-* tag; a vendor release can +# carry several versions, so each package has its own tag. +name: Release (vendor) + +on: + pull_request: + push: + branches: [master] + workflow_dispatch: + inputs: + publish: + description: Publish the packed tarballs to npm. Must run from a vendor-* tag. + required: true + type: boolean + default: false + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }} + cancel-in-progress: false + +env: + PRIMARY_NODE_VERSION: '24' + DSH_TELEMETRY_DISABLED: '1' + +jobs: + pack: + name: Pack npm tarballs + runs-on: ubuntu-24.04 + steps: + # Complete history: the release scripts read tags. + - uses: actions/checkout@v6 + with: + fetch-depth: 0 + persist-credentials: false + + - uses: pnpm/action-setup@v4 + with: + dest: ${{ runner.temp }}/setup-pnpm + + - uses: actions/setup-node@v6 + with: + node-version: ${{ env.PRIMARY_NODE_VERSION }} + + - name: Configure pnpm store path + id: pnpm-store + run: | + store_root="$HOME/.local/share/pnpm/store" + echo "PNPM_CONFIG_STORE_DIR=$store_root" >> "$GITHUB_ENV" + store_path=$(PNPM_CONFIG_STORE_DIR="$store_root" pnpm store path --silent) + echo "path=$store_path" >> "$GITHUB_OUTPUT" + + - uses: actions/cache/restore@v4 + with: + path: ${{ steps.pnpm-store.outputs.path }} + key: ${{ runner.os }}-node-${{ env.PRIMARY_NODE_VERSION }}-pnpm-${{ hashFiles('pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-node-${{ env.PRIMARY_NODE_VERSION }}-pnpm- + + - name: Install (immutable) + run: pnpm install --frozen-lockfile + + - name: Verify release version + env: + RELEASE_PUBLISH: ${{ inputs.publish }} + run: pnpm run release:verify --family vendor + + # The vendored packages publish their own sources and build outputs; the + # host build produces what their manifests select. + - name: Build + run: pnpm run build:lib:host + + - name: Pack release tarballs + run: pnpm run release:pack --family vendor --out dist/npm-vendor + + - uses: actions/upload-artifact@v4 + with: + name: vendor-npm-tarballs + path: dist/npm-vendor/* + if-no-files-found: error + retention-days: 7 + + publish: + name: Publish to npm + if: inputs.publish + needs: pack + runs-on: ubuntu-24.04 + environment: npm-publish + permissions: + contents: read + id-token: write + steps: + # Checkout and install carry the release scripts only; no build step. + - uses: actions/checkout@v6 + with: + persist-credentials: false + + - uses: pnpm/action-setup@v4 + with: + dest: ${{ runner.temp }}/setup-pnpm + + - uses: actions/setup-node@v6 + with: + node-version: ${{ env.PRIMARY_NODE_VERSION }} + registry-url: https://registry.npmjs.org + + - name: Install (immutable, no package scripts) + run: pnpm install --frozen-lockfile --ignore-scripts + + - uses: actions/download-artifact@v4 + with: + name: vendor-npm-tarballs + path: dist/npm-vendor + + - name: Publish tarballs + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + run: pnpm run release:publish --family vendor --from dist/npm-vendor diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000000..8b4005f42f --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,127 @@ +# Pack and publish the dsh release sequence: every package under packages/ plus +# the apps/ entries, all on one version. The vendored framework and the native +# packages are separate sequences with their own workflows and version lines. +# +# Pack runs without credentials on every pull request and master push, so a +# pull request proves the whole publish set still packs. Publication is a +# manual dispatch from a dsh-v* tag and consumes exactly the packed bytes. +name: Release (dsh) + +on: + pull_request: + push: + branches: [master] + workflow_dispatch: + inputs: + publish: + description: Publish the packed tarballs to npm. Must run from a dsh-v* tag. + required: true + type: boolean + default: false + +permissions: + contents: read + +concurrency: + # dist-tags are shared registry state; never race two release runs. + group: ${{ github.workflow }} + cancel-in-progress: false + +env: + PRIMARY_NODE_VERSION: '24' + DSH_TELEMETRY_DISABLED: '1' + +jobs: + pack: + name: Pack npm tarballs + runs-on: ubuntu-24.04 + steps: + # Complete history: the release scripts read tags. + - uses: actions/checkout@v6 + with: + fetch-depth: 0 + persist-credentials: false + + - uses: pnpm/action-setup@v4 + with: + dest: ${{ runner.temp }}/setup-pnpm + + - uses: actions/setup-node@v6 + with: + node-version: ${{ env.PRIMARY_NODE_VERSION }} + + - name: Configure pnpm store path + id: pnpm-store + run: | + store_root="$HOME/.local/share/pnpm/store" + echo "PNPM_CONFIG_STORE_DIR=$store_root" >> "$GITHUB_ENV" + store_path=$(PNPM_CONFIG_STORE_DIR="$store_root" pnpm store path --silent) + echo "path=$store_path" >> "$GITHUB_OUTPUT" + + - uses: actions/cache/restore@v4 + with: + path: ${{ steps.pnpm-store.outputs.path }} + key: ${{ runner.os }}-node-${{ env.PRIMARY_NODE_VERSION }}-pnpm-${{ hashFiles('pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-node-${{ env.PRIMARY_NODE_VERSION }}-pnpm- + + - name: Install (immutable) + run: pnpm install --frozen-lockfile + + - name: Verify release version + env: + RELEASE_PUBLISH: ${{ inputs.publish }} + run: pnpm run release:verify --family dsh + + - name: Build + run: pnpm run build + + - name: Pack release tarballs + run: pnpm run release:pack --family dsh --out dist/npm + + - uses: actions/upload-artifact@v4 + with: + name: dsh-npm-tarballs + path: dist/npm/* + if-no-files-found: error + retention-days: 7 + + publish: + name: Publish to npm + if: inputs.publish + needs: pack + runs-on: ubuntu-24.04 + # Required reviewers and the allowed tags live on the environment; this is + # the only step in the sequence that can write to the registry. + environment: npm-publish + permissions: + contents: read + id-token: write + steps: + # Checkout and install carry the release scripts only. There is no build + # step: publication uploads the bytes the pack job produced. + - uses: actions/checkout@v6 + with: + persist-credentials: false + + - uses: pnpm/action-setup@v4 + with: + dest: ${{ runner.temp }}/setup-pnpm + + - uses: actions/setup-node@v6 + with: + node-version: ${{ env.PRIMARY_NODE_VERSION }} + registry-url: https://registry.npmjs.org + + - name: Install (immutable, no package scripts) + run: pnpm install --frozen-lockfile --ignore-scripts + + - uses: actions/download-artifact@v4 + with: + name: dsh-npm-tarballs + path: dist/npm + + - name: Publish tarballs + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + run: pnpm run release:publish --family dsh --from dist/npm From 97eb14a007cc554cead5e731db3b21605b26e988 Mon Sep 17 00:00:00 2001 From: imccyu <276526105+imccyu@users.noreply.github.com> Date: Tue, 11 Aug 2026 00:02:53 +0800 Subject: [PATCH 04/36] build(release): make the release set publishable under the private scope Every package under packages/, apps/, and vendor/ drops "private": true and declares publishConfig.access "restricted": the repository now states which packages it publishes instead of deciding it at publish time. Each one also declares its repository and directory, which is how a consumer of a private package reaches its source. The Landlock packages move to restricted with them. They have never been published, so nothing anonymous depends on them today, and the whole @deepseek-ai scope stays private. The workspace constraint that required every package to be private now applies to non-members only, and asserts the publishable trio on each release member. --- apps/cli/package.json | 9 ++++++- apps/web/package.json | 9 ++++++- .../landlock-run/packages/entry/package.json | 2 +- .../packages/linux-arm64/package.json | 2 +- .../packages/linux-x64/package.json | 2 +- packages/acp/acp/package.json | 9 ++++++- packages/api/gateway/package.json | 9 ++++++- packages/api/remotes/package.json | 9 ++++++- .../attachment/attachment-local/package.json | 9 ++++++- packages/attachment/attachment/package.json | 9 ++++++- packages/bash/bash-env/package.json | 9 ++++++- packages/bash/bash-local/package.json | 9 ++++++- packages/bash/bash-sandbox/package.json | 9 ++++++- packages/bash/bash/package.json | 9 ++++++- packages/bash/pwsh-local/package.json | 9 ++++++- packages/bash/pwsh-sandbox/package.json | 9 ++++++- packages/bash/tool-bash/package.json | 9 ++++++- packages/bash/tool-pwsh/package.json | 9 ++++++- packages/boot/app-boot/package.json | 9 ++++++- packages/bundle/base/package.json | 9 ++++++- packages/bundle/headless/package.json | 9 ++++++- packages/bundle/web-app/package.json | 9 ++++++- packages/client/connection/package.json | 9 ++++++- packages/client/hmr/package.json | 9 ++++++- packages/client/locale/package.json | 9 ++++++- packages/client/modules/package.json | 9 ++++++- packages/client/runtime/package.json | 9 ++++++- packages/client/schema-form/package.json | 9 ++++++- packages/client/test-runtime/package.json | 9 ++++++- packages/client/ui-agent-preset/package.json | 9 ++++++- packages/client/ui-command/package.json | 9 ++++++- packages/client/ui-conversation/package.json | 9 ++++++- packages/client/ui-deliverables/package.json | 9 ++++++- packages/client/ui-goal/package.json | 9 ++++++- packages/client/ui-layout/package.json | 9 ++++++- packages/client/ui-model/package.json | 9 ++++++- packages/client/ui-models/package.json | 9 ++++++- packages/client/ui-permission/package.json | 9 ++++++- packages/client/ui-plan/package.json | 9 ++++++- packages/client/ui-primitives/package.json | 9 ++++++- packages/client/ui-question/package.json | 9 ++++++- .../client/ui-settings-general/package.json | 9 ++++++- packages/client/ui-settings/package.json | 9 ++++++- packages/client/ui-sidebar/package.json | 9 ++++++- packages/client/ui-skill/package.json | 9 ++++++- packages/client/ui-slash/package.json | 9 ++++++- packages/client/ui-slots/package.json | 9 ++++++- packages/client/ui-subagent/package.json | 9 ++++++- packages/client/ui-theme/package.json | 9 ++++++- packages/client/ui-tool/package.json | 9 ++++++- packages/client/ui-trajectory/package.json | 9 ++++++- packages/client/ui-workspace/package.json | 9 ++++++- packages/client/web-react/package.json | 9 ++++++- packages/client/web/package.json | 9 ++++++- .../code-runtime-worker/package.json | 9 ++++++- .../code-runtime/code-runtime/package.json | 9 ++++++- packages/compact/command-compact/package.json | 9 ++++++- packages/compact/compact-basic/package.json | 9 ++++++- .../compact-tool-result-prune/package.json | 9 ++++++- packages/compact/compact/package.json | 9 ++++++- .../context/session-reference/package.json | 9 ++++++- packages/context/time-context/package.json | 9 ++++++- packages/context/tmux-context/package.json | 9 ++++++- .../context/workspace-context/package.json | 9 ++++++- .../core/agent-default-model/package.json | 9 ++++++- packages/core/agent-loop/package.json | 9 ++++++- packages/core/agent-tool-mode/package.json | 9 ++++++- packages/core/agent/package.json | 9 ++++++- packages/core/scope/package.json | 9 ++++++- packages/core/session/package.json | 9 ++++++- packages/core/system-prompt/package.json | 9 ++++++- packages/core/tools/package.json | 9 ++++++- .../credentials-local/package.json | 9 ++++++- packages/credentials/credentials/package.json | 9 ++++++- packages/e2b/e2b/package.json | 9 ++++++- packages/e2b/fs-e2b/package.json | 9 ++++++- packages/e2b/subprocess-e2b/package.json | 9 ++++++- packages/examples/acp-demo/package.json | 9 ++++++- .../examples/agent-spine-demo/package.json | 9 ++++++- packages/examples/jsonrpc-demo/package.json | 9 ++++++- .../feedback/command-feedback/package.json | 9 ++++++- packages/fs/fs-local/package.json | 9 ++++++- packages/fs/fs-policy/package.json | 9 ++++++- packages/fs/fs-sandbox/package.json | 9 ++++++- packages/fs/fs/package.json | 9 ++++++- packages/fs/tool-fs-search/package.json | 9 ++++++- packages/fs/tool-fs/package.json | 9 ++++++- .../fs/tool-str-replace-editor/package.json | 9 ++++++- packages/goal/command-goal/package.json | 9 ++++++- packages/goal/goal-session/package.json | 9 ++++++- packages/goal/goal/package.json | 9 ++++++- packages/goal/tool-goal/package.json | 9 ++++++- packages/guard/repeat-tool-guard/package.json | 9 ++++++- packages/guard/timeout-policy/package.json | 9 ++++++- packages/hooks/hook-protocol/package.json | 9 ++++++- packages/hooks/hooks-claude/package.json | 9 ++++++- packages/hooks/hooks-codex/package.json | 9 ++++++- packages/host/apiproxy/package.json | 9 ++++++- .../host/directory-picker-auto/package.json | 9 ++++++- .../host/directory-picker-browse/package.json | 9 ++++++- .../host/directory-picker-native/package.json | 9 ++++++- packages/host/directory-picker/package.json | 9 ++++++- packages/host/frontend-static/package.json | 9 ++++++- packages/host/webserver/package.json | 9 ++++++- packages/interaction/commands/package.json | 9 ++++++- packages/interaction/permission/package.json | 9 ++++++- .../interaction/tool-ask-user/package.json | 9 ++++++- .../interaction/user-approval/package.json | 9 ++++++- .../interaction/user-interaction/package.json | 9 ++++++- packages/llm/llm-deepseek/package.json | 9 ++++++- packages/llm/llm-pi-ai/package.json | 9 ++++++- packages/llm/llm-retry/package.json | 9 ++++++- packages/llm/llm/package.json | 9 ++++++- packages/llm/token-meter/package.json | 9 ++++++- packages/lsp/lsp-local/package.json | 9 ++++++- packages/lsp/lsp/package.json | 9 ++++++- packages/lsp/tool-lsp/package.json | 9 ++++++- packages/mcp/mcp-client/package.json | 9 ++++++- packages/plan/plan-mode/package.json | 9 ++++++- packages/preset/agent-presets/package.json | 9 ++++++- packages/preset/persona/package.json | 9 ++++++- packages/pty/pty-local/package.json | 9 ++++++- packages/pty/pty/package.json | 9 ++++++- .../pty/tool-bash-persistent/package.json | 9 ++++++- packages/pty/tool-pty/package.json | 9 ++++++- packages/sandbox/sandbox-local/package.json | 9 ++++++- packages/sandbox/sandbox-policy/package.json | 9 ++++++- .../sandbox/sandbox-windows-acl/package.json | 9 ++++++- packages/sandbox/sandbox/package.json | 9 ++++++- packages/scaffold/client/package.json | 9 ++++++- packages/scaffold/create-sdk/package.json | 9 ++++++- packages/scaffold/helper/package.json | 9 ++++++- packages/scaffold/protocol/package.json | 9 ++++++- packages/scaffold/scripts/package.json | 9 ++++++- packages/scaffold/server/package.json | 9 ++++++- packages/scaffold/telemetry/package.json | 9 ++++++- .../tool-cordis/package.json | 9 ++++++- .../session-query-sqlite/package.json | 9 ++++++- .../session-query/session-query/package.json | 9 ++++++- .../tool-session-query/package.json | 9 ++++++- .../session-checkpoint-policy/package.json | 9 ++++++- .../session-persistence-jsonl/package.json | 9 ++++++- .../session-persistence-sqlite/package.json | 9 ++++++- .../session/session-persistence/package.json | 9 ++++++- .../session-projection-cache/package.json | 9 ++++++- .../session/session-projection/package.json | 9 ++++++- .../session-telemetry-otel/package.json | 9 ++++++- .../session/session-telemetry/package.json | 9 ++++++- .../package.json | 9 ++++++- .../package.json | 9 ++++++- .../session/session-title-llm/package.json | 9 ++++++- packages/session/session-title/package.json | 9 ++++++- packages/session/user-id/package.json | 9 ++++++- packages/settings/settings-local/package.json | 9 ++++++- packages/settings/settings/package.json | 9 ++++++- packages/skill/skill-badge/package.json | 9 ++++++- packages/skill/skill-local/package.json | 9 ++++++- packages/skill/skill/package.json | 9 ++++++- packages/skill/tool-skill/package.json | 9 ++++++- packages/spill/spill-local/package.json | 9 ++++++- packages/spill/spill-policy/package.json | 9 ++++++- packages/spill/spill/package.json | 9 ++++++- packages/storage/storage-domain/package.json | 9 ++++++- packages/storage/storage-json/package.json | 9 ++++++- packages/storage/storage-sqlite/package.json | 9 ++++++- packages/storage/storage/package.json | 9 ++++++- packages/subagent/subagent-acp/package.json | 9 ++++++- .../subagent-claude-code/package.json | 9 ++++++- packages/subagent/subagent-codex/package.json | 9 ++++++- .../subagent/subagent-dsh-sdk/package.json | 9 ++++++- packages/subagent/subagent-fork/package.json | 9 ++++++- .../subagent/subagent-inprocess/package.json | 9 ++++++- packages/subagent/subagent-spawn/package.json | 9 ++++++- packages/subagent/subagent/package.json | 9 ++++++- .../tool-subagent-control/package.json | 9 ++++++- .../tool-subagent-report/package.json | 9 ++++++- packages/subagent/tool-subagent/package.json | 9 ++++++- .../subprocess/subprocess-local/package.json | 9 ++++++- packages/subprocess/subprocess/package.json | 9 ++++++- packages/support/acp-snapshot/package.json | 9 ++++++- .../support/agent-loop-testkit/package.json | 9 ++++++- packages/support/invariants/package.json | 9 ++++++- packages/support/llm-mock-server/package.json | 9 ++++++- packages/support/llm-replay/package.json | 9 ++++++- packages/support/loader-smoke/package.json | 9 ++++++- packages/tasks/tasks-local/package.json | 9 ++++++- packages/tasks/tasks/package.json | 9 ++++++- packages/tasks/tool-tasks/package.json | 9 ++++++- packages/todo/tool-todo/package.json | 9 ++++++- packages/typert/generator/package.json | 9 ++++++- packages/typert/loader/package.json | 9 ++++++- packages/typert/registry/package.json | 9 ++++++- packages/typert/type-meta/package.json | 9 ++++++- packages/util/atomic-write/package.json | 9 ++++++- packages/util/brand/package.json | 9 ++++++- packages/util/environment/package.json | 9 ++++++- packages/util/native-command/package.json | 9 ++++++- packages/util/paths/package.json | 9 ++++++- packages/util/retention/package.json | 9 ++++++- packages/util/timeout/package.json | 9 ++++++- packages/web/tool-web/package.json | 9 ++++++- packages/web/web-fetch-local/package.json | 9 ++++++- packages/web/web-search-deepseek/package.json | 9 ++++++- packages/web/web-search-exa/package.json | 9 ++++++- .../web/web-search-perplexity/package.json | 9 ++++++- packages/web/web/package.json | 9 ++++++- packages/workflow/tool-ralph/package.json | 9 ++++++- packages/workflow/tool-workflow/package.json | 9 ++++++- .../workflow-workerthread/package.json | 9 ++++++- packages/workflow/workflow/package.json | 9 ++++++- packages/workspace/workspace/package.json | 9 ++++++- scripts/check-workspace-constraints.ts | 27 +++++++++++++++++-- vendor/cordis/package.json | 9 ++++++- vendor/cosmokit/package.json | 9 ++++++- vendor/group/package.json | 9 ++++++- vendor/hmr/package.json | 9 ++++++- vendor/include/package.json | 9 ++++++- vendor/loader/package.json | 9 ++++++- vendor/logger-console/package.json | 9 ++++++- vendor/schemastery/package.json | 9 ++++++- vendor/timer/package.json | 9 ++++++- 221 files changed, 1764 insertions(+), 222 deletions(-) diff --git a/apps/cli/package.json b/apps/cli/package.json index 8b50f180f2..3155032205 100644 --- a/apps/cli/package.json +++ b/apps/cli/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh", "description": "dsh CLI: profile boot, plugin management, and the browser UI alias", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "apps/cli" + }, "type": "module", "bin": { "dsh": "lib/bin.js" diff --git a/apps/web/package.json b/apps/web/package.json index 1bf97cb17c..9e71181b4b 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-frontend", "description": "Web application entry: vite build over the @deepseek-ai/dsh-client-web shell library; dist/ served by apps/cli's dsh web", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "apps/web" + }, "type": "module", "exports": { "./dist/*": "./dist/*", diff --git a/native/landlock-run/packages/entry/package.json b/native/landlock-run/packages/entry/package.json index 1614df5ad2..b3384a58c0 100644 --- a/native/landlock-run/packages/entry/package.json +++ b/native/landlock-run/packages/entry/package.json @@ -32,7 +32,7 @@ }, "license": "BSD-3-Clause", "publishConfig": { - "access": "public" + "access": "restricted" }, "optionalDependencies": { "@deepseek-ai/node-addon-landlock-run-linux-arm64": "workspace:*", diff --git a/native/landlock-run/packages/linux-arm64/package.json b/native/landlock-run/packages/linux-arm64/package.json index 14190e4765..11d9384c87 100644 --- a/native/landlock-run/packages/linux-arm64/package.json +++ b/native/landlock-run/packages/linux-arm64/package.json @@ -26,6 +26,6 @@ }, "license": "BSD-3-Clause", "publishConfig": { - "access": "public" + "access": "restricted" } } diff --git a/native/landlock-run/packages/linux-x64/package.json b/native/landlock-run/packages/linux-x64/package.json index 43c092d17b..6e3ad395e6 100644 --- a/native/landlock-run/packages/linux-x64/package.json +++ b/native/landlock-run/packages/linux-x64/package.json @@ -26,6 +26,6 @@ }, "license": "BSD-3-Clause", "publishConfig": { - "access": "public" + "access": "restricted" } } diff --git a/packages/acp/acp/package.json b/packages/acp/acp/package.json index 0d83ca8c24..c5564b0b2f 100644 --- a/packages/acp/acp/package.json +++ b/packages/acp/acp/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-acp", "description": "Automation-only Agent Client Protocol server for driving DeepSeek Harness agents over JSON-RPC stdio", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/acp/acp" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/api/gateway/package.json b/packages/api/gateway/package.json index 9720c8530a..10a315302a 100644 --- a/packages/api/gateway/package.json +++ b/packages/api/gateway/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-api-gateway", "description": "TypeRT Remote Host dispatcher and Client API endpoint", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/api/gateway" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/api/remotes/package.json b/packages/api/remotes/package.json index 2a1d92b82a..8a31f138e3 100644 --- a/packages/api/remotes/package.json +++ b/packages/api/remotes/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-api-remotes", "description": "Remote BFF assembly and Host Agent/Session lookup policy", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/api/remotes" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/attachment/attachment-local/package.json b/packages/attachment/attachment-local/package.json index b11180f133..4219c40d30 100644 --- a/packages/attachment/attachment-local/package.json +++ b/packages/attachment/attachment-local/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-attachment-local", "description": "Private content-addressed DSH_HOME attachment storage", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/attachment/attachment-local" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/attachment/attachment/package.json b/packages/attachment/attachment/package.json index 4ec0fee955..ad212f3933 100644 --- a/packages/attachment/attachment/package.json +++ b/packages/attachment/attachment/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-attachment", "description": "Durable immutable attachment storage seam for the DeepSeek Harness", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/attachment/attachment" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/bash/bash-env/package.json b/packages/bash/bash-env/package.json index b2de167a64..8983029c0d 100644 --- a/packages/bash/bash-env/package.json +++ b/packages/bash/bash-env/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-bash-env", "description": "Tool-independent managed DSH_* shell environment registry", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/bash/bash-env" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/bash/bash-local/package.json b/packages/bash/bash-local/package.json index 2a19e4da5d..f147b01f72 100644 --- a/packages/bash/bash-local/package.json +++ b/packages/bash/bash-local/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-bash-local", "description": "Local-subprocess implementation of the DeepSeek Harness bash executor seam", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/bash/bash-local" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/bash/bash-sandbox/package.json b/packages/bash/bash-sandbox/package.json index b37f9dc48e..b1d1b4a13a 100644 --- a/packages/bash/bash-sandbox/package.json +++ b/packages/bash/bash-sandbox/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-bash-sandbox", "description": "Sandbox-consuming implementation of the DeepSeek Harness bash executor seam (confines every command via ctx.sandbox, reports denial/enforcement result facts)", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/bash/bash-sandbox" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/bash/bash/package.json b/packages/bash/bash/package.json index d184a18d7b..320f077f28 100644 --- a/packages/bash/bash/package.json +++ b/packages/bash/bash/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-bash", "description": "Abstract bash executor seam (ctx.bash) for the DeepSeek Harness", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/bash/bash" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/bash/pwsh-local/package.json b/packages/bash/pwsh-local/package.json index ecfa7f11da..a3b5d6aa7d 100644 --- a/packages/bash/pwsh-local/package.json +++ b/packages/bash/pwsh-local/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-pwsh-local", "description": "Local PowerShell implementation of the DeepSeek Harness bash executor seam", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/bash/pwsh-local" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/bash/pwsh-sandbox/package.json b/packages/bash/pwsh-sandbox/package.json index fbc5227912..727496274b 100644 --- a/packages/bash/pwsh-sandbox/package.json +++ b/packages/bash/pwsh-sandbox/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-pwsh-sandbox", "description": "Sandbox-consuming implementation of the DeepSeek Harness PowerShell executor seam (confines every command via ctx.sandbox, reports denial/enforcement result facts)", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/bash/pwsh-sandbox" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/bash/tool-bash/package.json b/packages/bash/tool-bash/package.json index bd467f103e..6440e990b0 100644 --- a/packages/bash/tool-bash/package.json +++ b/packages/bash/tool-bash/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-tool-bash", "description": "Model-facing bash tool with optional generic background-task and sandbox-escalation support", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/bash/tool-bash" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/bash/tool-pwsh/package.json b/packages/bash/tool-pwsh/package.json index 7f18585332..b06df9a992 100644 --- a/packages/bash/tool-pwsh/package.json +++ b/packages/bash/tool-pwsh/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-tool-pwsh", "description": "Model-facing pwsh tool over the bash executor seam", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/bash/tool-pwsh" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/boot/app-boot/package.json b/packages/boot/app-boot/package.json index 0295742268..f47611040d 100644 --- a/packages/boot/app-boot/package.json +++ b/packages/boot/app-boot/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-app-boot", "description": "Shared boot glue for the app bins: .env loading, fail-loud Loader guards, snapshot-aware config resolution, and the Loader boot sequence", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/boot/app-boot" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/bundle/base/package.json b/packages/bundle/base/package.json index 038e3ea0c6..c2547f9aae 100644 --- a/packages/bundle/base/package.json +++ b/packages/bundle/base/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-base", "description": "The shared dsh core as a profile bundle: every profile's first patch layer, inserting the base plugin rows over the empty profile root", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/bundle/base" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/bundle/headless/package.json b/packages/bundle/headless/package.json index e439fe75f7..4bdd04efd9 100644 --- a/packages/bundle/headless/package.json +++ b/packages/bundle/headless/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-headless", "description": "The dsh one-shot bundle: a direct core Agent/Session runner over dsh-base with no Host, HTTP, or browser layer", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/bundle/headless" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/bundle/web-app/package.json b/packages/bundle/web-app/package.json index b6740c7b77..c9ec594f28 100644 --- a/packages/bundle/web-app/package.json +++ b/packages/bundle/web-app/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-web-app", "description": "The dsh browser-surface bundle: the web patch layer over dsh-base plus the runtime glue plugin (frontend dist serving, web-surface prompt, bash runtime variables, URL line)", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/bundle/web-app" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/client/connection/package.json b/packages/client/connection/package.json index 8f7b485c09..f03afb8eda 100644 --- a/packages/client/connection/package.json +++ b/packages/client/connection/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-client-connection", "description": "Wire consumer layer: HTTP-up/WebSocket-down client, ConnectionController dual streams with reconnect, and fixture api", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/client/connection" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/client/hmr/package.json b/packages/client/hmr/package.json index 79e2789d33..82d8cb18e1 100644 --- a/packages/client/hmr/package.json +++ b/packages/client/hmr/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-client-hmr", "description": "Dev-only hot-reload driver for script-loaded client entries: SSE rebuilt frames → invalidate/prefetch → fiber swap through the vendored Loader entry", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/client/hmr" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/client/locale/package.json b/packages/client/locale/package.json index dc90483e1b..f845feacc9 100644 --- a/packages/client/locale/package.json +++ b/packages/client/locale/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-client-locale", "description": "Locale plugin: Host-backed zh/en preference, browser-derived fallback, locale snapshots, and typed namespace dictionaries", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/client/locale" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/client/modules/package.json b/packages/client/modules/package.json index a9d9d1de2d..e980619017 100644 --- a/packages/client/modules/package.json +++ b/packages/client/modules/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-client-modules", "description": "Client module system, dual-face: node half composes the __DSH_BOOT__ entry graph (incremental dsh.client scan, bundle route, index tap, webPlugins service); browser half is the lazy-CJS module table the vendored cordis Loader consumes as its internal seam", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/client/modules" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/client/runtime/package.json b/packages/client/runtime/package.json index 6250a97ff5..168e916223 100644 --- a/packages/client/runtime/package.json +++ b/packages/client/runtime/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-client-runtime", "description": "Client core services: SlotsService, SessionsService (scope tree + object layer)", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/client/runtime" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/client/schema-form/package.json b/packages/client/schema-form/package.json index ee6529025c..30e0c24353 100644 --- a/packages/client/schema-form/package.json +++ b/packages/client/schema-form/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-client-schema-form", "description": "Schema/draft model layer for settings editors: rehydrates a serialized schemastery schema, validates drafts, and edits them immutably by path", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/client/schema-form" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/client/test-runtime/package.json b/packages/client/test-runtime/package.json index 0891660b79..1efc9228d4 100644 --- a/packages/client/test-runtime/package.json +++ b/packages/client/test-runtime/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-client-test-runtime", "description": "jsdom slot test runtime: real Cordis Context + SlotsService + web-react renderer with test-owned session/workspace doubles for feature specs", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/client/test-runtime" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/client/ui-agent-preset/package.json b/packages/client/ui-agent-preset/package.json index 93facc56eb..90b6fc4fa8 100644 --- a/packages/client/ui-agent-preset/package.json +++ b/packages/client/ui-agent-preset/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-client-ui-agent-preset", "description": "Agent-preset surfaces: the default for later sessions, this session's seat, and the composition editor", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/client/ui-agent-preset" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/client/ui-command/package.json b/packages/client/ui-command/package.json index 5ff21d89b9..513f6cf8a4 100644 --- a/packages/client/ui-command/package.json +++ b/packages/client/ui-command/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-client-ui-command", "description": "Client command surface: global directory cache, '/' source, three command UI kinds, popupSelect registry", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/client/ui-command" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/client/ui-conversation/package.json b/packages/client/ui-conversation/package.json index a21fad9168..bb93c82608 100644 --- a/packages/client/ui-conversation/package.json +++ b/packages/client/ui-conversation/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-client-ui-conversation", "description": "Conversation domain: skeleton, ordered chat flow, composer with the Host-backed busy-Enter preference, and details host", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/client/ui-conversation" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/client/ui-deliverables/package.json b/packages/client/ui-deliverables/package.json index 4b7b8daa56..e60fc8262b 100644 --- a/packages/client/ui-deliverables/package.json +++ b/packages/client/ui-deliverables/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-client-ui-deliverables", "description": "Produced-files turn tail: the deliverables row a finished turn ends with", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/client/ui-deliverables" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/client/ui-goal/package.json b/packages/client/ui-goal/package.json index 2e5816437e..648fb0e609 100644 --- a/packages/client/ui-goal/package.json +++ b/packages/client/ui-goal/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-client-ui-goal", "description": "Session goal surface: GoalBar docked above the composer, read from the goal session projection", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/client/ui-goal" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/client/ui-layout/package.json b/packages/client/ui-layout/package.json index 5fc53a5fa8..26c056f602 100644 --- a/packages/client/ui-layout/package.json +++ b/packages/client/ui-layout/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-client-ui-layout", "description": "Shell plugin: three-column AppFrame with drag handles, ctx.layout viewing-state service (navigation + panels)", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/client/ui-layout" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/client/ui-model/package.json b/packages/client/ui-model/package.json index dcd139dad5..d2ca1b3318 100644 --- a/packages/client/ui-model/package.json +++ b/packages/client/ui-model/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-client-ui-model", "description": "Model selection: the /model popupSelect over session.models / session.selectModel", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/client/ui-model" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/client/ui-models/package.json b/packages/client/ui-models/package.json index fb0ff5a0c3..8eaac3bccf 100644 --- a/packages/client/ui-models/package.json +++ b/packages/client/ui-models/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-client-ui-models", "description": "Models settings and official-DeepSeek first-run routing over one live provider/settings/credential join", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/client/ui-models" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/client/ui-permission/package.json b/packages/client/ui-permission/package.json index 457511c928..12f1a25509 100644 --- a/packages/client/ui-permission/package.json +++ b/packages/client/ui-permission/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-client-ui-permission", "description": "Permission surfaces: a new-session default in General settings and a current-session /permission popup over the permissions projection", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/client/ui-permission" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/client/ui-plan/package.json b/packages/client/ui-plan/package.json index 888cc74005..23d03b88d3 100644 --- a/packages/client/ui-plan/package.json +++ b/packages/client/ui-plan/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-client-ui-plan", "description": "Plan-mode composer control: the conversation.input.plan seat over the plan projection and the /plan command channel", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/client/ui-plan" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/client/ui-primitives/package.json b/packages/client/ui-primitives/package.json index 91d8647a55..dc0c21d31f 100644 --- a/packages/client/ui-primitives/package.json +++ b/packages/client/ui-primitives/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-client-ui-primitives", "description": "Pure React atoms for the dsh web UI: controls, icons, markdown, and JSON inspectors (zero cordis)", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/client/ui-primitives" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/client/ui-question/package.json b/packages/client/ui-question/package.json index 80f18e3a2a..172f4fb4f8 100644 --- a/packages/client/ui-question/package.json +++ b/packages/client/ui-question/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-client-ui-question", "description": "Web ask_user_question feature: host tool mount plus composer-takeover question UI", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/client/ui-question" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/client/ui-settings-general/package.json b/packages/client/ui-settings-general/package.json index a66cb41153..b67d12a709 100644 --- a/packages/client/ui-settings-general/package.json +++ b/packages/client/ui-settings-general/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-client-ui-settings-general", "description": "Settings ownerless-copy and product onboarding plugin: the General section, shell trigger/header chrome content, settings dictionaries, and the versioned welcome notice", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/client/ui-settings-general" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/client/ui-settings/package.json b/packages/client/ui-settings/package.json index 138b4e3c88..a65466e2c2 100644 --- a/packages/client/ui-settings/package.json +++ b/packages/client/ui-settings/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-client-ui-settings", "description": "Settings shell plugin: sidebar trigger, modal panel, feature sections, and an ordered full-page onboarding stage", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/client/ui-settings" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/client/ui-sidebar/package.json b/packages/client/ui-sidebar/package.json index 7a135c1bcc..c4022d04d0 100644 --- a/packages/client/ui-sidebar/package.json +++ b/packages/client/ui-sidebar/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-client-ui-sidebar", "description": "Sidebar plugin: session multi-level tree, search, grouping, state dots", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/client/ui-sidebar" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/client/ui-skill/package.json b/packages/client/ui-skill/package.json index 0490958e7d..d87425625a 100644 --- a/packages/client/ui-skill/package.json +++ b/packages/client/ui-skill/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-client-ui-skill", "description": "Web skill references and the dedicated skill tool row", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/client/ui-skill" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/client/ui-slash/package.json b/packages/client/ui-slash/package.json index 7e99d22875..46de2a5951 100644 --- a/packages/client/ui-slash/package.json +++ b/packages/client/ui-slash/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-client-ui-slash", "description": "Input trigger pipeline: '/' and '@' detection, candidate menu, pick routing to registered sources", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/client/ui-slash" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/client/ui-slots/package.json b/packages/client/ui-slots/package.json index ef809470b5..c9825022e8 100644 --- a/packages/client/ui-slots/package.json +++ b/packages/client/ui-slots/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-client-ui-slots", "description": "Slot registry pure core: SlotMap declaration merging, single register composition API, four-share props types, store-seat types, renderer install seam", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/client/ui-slots" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/client/ui-subagent/package.json b/packages/client/ui-subagent/package.json index 6c9a178d31..bbae62edb6 100644 --- a/packages/client/ui-subagent/package.json +++ b/packages/client/ui-subagent/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-client-ui-subagent", "description": "Subagent conversation catalog, continuation routing UI, and '@' reference source", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/client/ui-subagent" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/client/ui-theme/package.json b/packages/client/ui-theme/package.json index 27f1799c56..1ad1274427 100644 --- a/packages/client/ui-theme/package.json +++ b/packages/client/ui-theme/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-client-ui-theme", "description": "Theme plugin: ThemeService (light/dark/system preference, prefers-color-scheme resolution, theme/change snapshots; no DOM), --dsw-* token base stylesheets; registers the Appearance settings row", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/client/ui-theme" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/client/ui-tool/package.json b/packages/client/ui-tool/package.json index 2db30e5d48..eb3b9366ba 100644 --- a/packages/client/ui-tool/package.json +++ b/packages/client/ui-tool/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-client-ui-tool", "description": "Client Tool call-tree renderer and keyed per-tool presentation slot", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/client/ui-tool" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/client/ui-trajectory/package.json b/packages/client/ui-trajectory/package.json index 6f85a51c8a..4aef2a424b 100644 --- a/packages/client/ui-trajectory/package.json +++ b/packages/client/ui-trajectory/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-client-ui-trajectory", "description": "Trajectory event ledger with an interactive timing overview: pure-consumer plugin registering into the conversation ViewMap (no service)", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/client/ui-trajectory" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/client/ui-workspace/package.json b/packages/client/ui-workspace/package.json index 5607c8cc40..7b4ad80acf 100644 --- a/packages/client/ui-workspace/package.json +++ b/packages/client/ui-workspace/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-client-ui-workspace", "description": "Workspace picker plugin: one WorkspacePicker registered into the sidebar and empty-state workspace slots", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/client/ui-workspace" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/client/web-react/package.json b/packages/client/web-react/package.json index 5aeae6f06f..3f65de4ad8 100644 --- a/packages/client/web-react/package.json +++ b/packages/client/web-react/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-client-web-react", "description": "Shell-side React glue: createSlotRenderer, SessionProvider, bindSnapshotSelector (uSES bridge), useInvoke", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/client/web-react" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/client/web/package.json b/packages/client/web/package.json index 348f1ce1cb..e4a1e60136 100644 --- a/packages/client/web/package.json +++ b/packages/client/web/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-client-web", "description": "Web shell kernel: bootWebShell (module system holding + seed table + two-stage boot + AppRoot gate + app-shell assembly entry), consumed by the apps/web vite entry", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/client/web" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/code-runtime/code-runtime-worker/package.json b/packages/code-runtime/code-runtime-worker/package.json index 565541abc8..55e2cbc398 100644 --- a/packages/code-runtime/code-runtime-worker/package.json +++ b/packages/code-runtime/code-runtime-worker/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-code-runtime-worker", "description": "Worker-thread implementation of the DeepSeek Harness code-execution seam", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/code-runtime/code-runtime-worker" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/code-runtime/code-runtime/package.json b/packages/code-runtime/code-runtime/package.json index 053e56b54a..57b85721a3 100644 --- a/packages/code-runtime/code-runtime/package.json +++ b/packages/code-runtime/code-runtime/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-code-runtime", "description": "Abstract code-execution seam (ctx.codeRuntime) for the DeepSeek Harness", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/code-runtime/code-runtime" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/compact/command-compact/package.json b/packages/compact/command-compact/package.json index ec043adca7..ff64dba2a6 100644 --- a/packages/compact/command-compact/package.json +++ b/packages/compact/command-compact/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-command-compact", "description": "Human-facing slash command for explicit session compaction", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/compact/command-compact" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/compact/compact-basic/package.json b/packages/compact/compact-basic/package.json index f407d15188..1f6c2b402e 100644 --- a/packages/compact/compact-basic/package.json +++ b/packages/compact/compact-basic/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-compact-basic", "description": "Token-meter-driven compaction policy and LLM summarization backend for the DeepSeek Harness", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/compact/compact-basic" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/compact/compact-tool-result-prune/package.json b/packages/compact/compact-tool-result-prune/package.json index 5a30f7fc97..45eab7b091 100644 --- a/packages/compact/compact-tool-result-prune/package.json +++ b/packages/compact/compact-tool-result-prune/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-compact-tool-result-prune", "description": "Replay-safe model-free head/middle/tail pruning for tool-result surface nodes", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/compact/compact-tool-result-prune" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/compact/compact/package.json b/packages/compact/compact/package.json index 2a4c3c9518..abdcd8a090 100644 --- a/packages/compact/compact/package.json +++ b/packages/compact/compact/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-compact", "description": "Abstract compaction service seam (ctx.compact) for the DeepSeek Harness", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/compact/compact" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/context/session-reference/package.json b/packages/context/session-reference/package.json index 259c7a9a63..900ec038e3 100644 --- a/packages/context/session-reference/package.json +++ b/packages/context/session-reference/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-session-reference", "description": "Cross-session snapshot references and durable untrusted model context (ctx.sessionReferences)", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/context/session-reference" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/context/time-context/package.json b/packages/context/time-context/package.json index d2bf0a1dbe..08bb776c47 100644 --- a/packages/context/time-context/package.json +++ b/packages/context/time-context/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-time-context", "description": "Opt-in durable per-step context with the current time and elapsed time", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/context/time-context" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/context/tmux-context/package.json b/packages/context/tmux-context/package.json index 99959c18f3..6cff253fac 100644 --- a/packages/context/tmux-context/package.json +++ b/packages/context/tmux-context/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-tmux-context", "description": "Opt-in durable per-step context with this agent's tmux pane and window location", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/context/tmux-context" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/context/workspace-context/package.json b/packages/context/workspace-context/package.json index 4972796a44..843d038dc5 100644 --- a/packages/context/workspace-context/package.json +++ b/packages/context/workspace-context/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-workspace-context", "description": "Workspace context loader for AGENTS.md/CLAUDE.md instruction files", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/context/workspace-context" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/core/agent-default-model/package.json b/packages/core/agent-default-model/package.json index e57709585b..8a6341208e 100644 --- a/packages/core/agent-default-model/package.json +++ b/packages/core/agent-default-model/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-agent-default-model", "description": "Default model selection shared by Agent entry points", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/core/agent-default-model" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/core/agent-loop/package.json b/packages/core/agent-loop/package.json index fe37f8ca1c..d37d92aede 100644 --- a/packages/core/agent-loop/package.json +++ b/packages/core/agent-loop/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-agent-loop", "description": "The concrete agent loop plugin for the DeepSeek Harness", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/core/agent-loop" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/core/agent-tool-mode/package.json b/packages/core/agent-tool-mode/package.json index 8427822784..bb25b4a14c 100644 --- a/packages/core/agent-tool-mode/package.json +++ b/packages/core/agent-tool-mode/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-agent-tool-mode", "description": "Agent-plane presentation selector: composes one agent's tools as Code Mode, native, or both", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/core/agent-tool-mode" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/core/agent/package.json b/packages/core/agent/package.json index 5669858fd9..b75f720ad4 100644 --- a/packages/core/agent/package.json +++ b/packages/core/agent/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-agent", "description": "Agent interface, registry, initiator scope, and event vocabulary for the DeepSeek Harness", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/core/agent" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/core/scope/package.json b/packages/core/scope/package.json index 792a6716e6..e82a8650e5 100644 --- a/packages/core/scope/package.json +++ b/packages/core/scope/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-scope", "description": "Scoped-context registration primitive (scope tags, scope-filtered event dispatch) for the DeepSeek Harness", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/core/scope" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/core/session/package.json b/packages/core/session/package.json index ada5c170d1..8fe45b8bed 100644 --- a/packages/core/session/package.json +++ b/packages/core/session/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-session", "description": "Event-sourced session store for the DeepSeek Harness", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/core/session" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/core/system-prompt/package.json b/packages/core/system-prompt/package.json index 35a270cf9d..3dc65c9391 100644 --- a/packages/core/system-prompt/package.json +++ b/packages/core/system-prompt/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-system-prompt", "description": "System prompt assembly registry for the DeepSeek Harness", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/core/system-prompt" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/core/tools/package.json b/packages/core/tools/package.json index 7070431132..6db89c3b0f 100644 --- a/packages/core/tools/package.json +++ b/packages/core/tools/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-tools", "description": "Tool registry and execution pipeline for the DeepSeek Harness", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/core/tools" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/credentials/credentials-local/package.json b/packages/credentials/credentials-local/package.json index 483fc3d5d0..b29c9d2fbb 100644 --- a/packages/credentials/credentials-local/package.json +++ b/packages/credentials/credentials-local/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-credentials-local", "description": "File-backed credentials provider ($DSH_HOME/.env under the live process environment) for the DeepSeek Harness", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/credentials/credentials-local" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/credentials/credentials/package.json b/packages/credentials/credentials/package.json index 2b356c197c..f0c9c43694 100644 --- a/packages/credentials/credentials/package.json +++ b/packages/credentials/credentials/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-credentials", "description": "Abstract credential seam (ctx.credentials): settings carry references to secrets, providers own the values", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/credentials/credentials" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/e2b/e2b/package.json b/packages/e2b/e2b/package.json index edb7077d63..98dff52be8 100644 --- a/packages/e2b/e2b/package.json +++ b/packages/e2b/e2b/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-e2b", "description": "Shared E2B sandbox lifecycle for DeepSeek Harness provider adapters", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/e2b/e2b" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/e2b/fs-e2b/package.json b/packages/e2b/fs-e2b/package.json index 7b7faf9c03..bb3190c4be 100644 --- a/packages/e2b/fs-e2b/package.json +++ b/packages/e2b/fs-e2b/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-fs-e2b", "description": "E2B filesystem implementation for DeepSeek Harness", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/e2b/fs-e2b" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/e2b/subprocess-e2b/package.json b/packages/e2b/subprocess-e2b/package.json index 182c41b8f5..ca5de7a893 100644 --- a/packages/e2b/subprocess-e2b/package.json +++ b/packages/e2b/subprocess-e2b/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-subprocess-e2b", "description": "E2B subprocess implementation for DeepSeek Harness", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/e2b/subprocess-e2b" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/examples/acp-demo/package.json b/packages/examples/acp-demo/package.json index 0e110ec3d4..e21a3b21a2 100644 --- a/packages/examples/acp-demo/package.json +++ b/packages/examples/acp-demo/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-acp-demo", "description": "ACP automation server app: agent spine + JSONL persistence + ACP transport, with a JSON-RPC stdio bin", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/examples/acp-demo" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/examples/agent-spine-demo/package.json b/packages/examples/agent-spine-demo/package.json index 73520f5645..470cb869df 100644 --- a/packages/examples/agent-spine-demo/package.json +++ b/packages/examples/agent-spine-demo/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-agent-spine-demo", "description": "The default executor-less/UI-less agent spine with fallback session titles, provider-routed retry, and optional persisted goals", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/examples/agent-spine-demo" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/examples/jsonrpc-demo/package.json b/packages/examples/jsonrpc-demo/package.json index 49aec73d1f..a9452b6a22 100644 --- a/packages/examples/jsonrpc-demo/package.json +++ b/packages/examples/jsonrpc-demo/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-jsonrpc-demo", "description": "Bin that boots an external Cordis config for the stdio JSON-RPC SDK runtime", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/examples/jsonrpc-demo" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/feedback/command-feedback/package.json b/packages/feedback/command-feedback/package.json index ac901d6a99..e3d72eb3cb 100644 --- a/packages/feedback/command-feedback/package.json +++ b/packages/feedback/command-feedback/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-command-feedback", "description": "Log-only session feedback producer and human-facing slash command", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/feedback/command-feedback" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/fs/fs-local/package.json b/packages/fs/fs-local/package.json index 1401a25597..feb0b621d5 100644 --- a/packages/fs/fs-local/package.json +++ b/packages/fs/fs-local/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-fs-local", "description": "Local-filesystem implementation of the DeepSeek Harness filesystem seam (ctx.fs)", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/fs/fs-local" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/fs/fs-policy/package.json b/packages/fs/fs-policy/package.json index 007ef3d529..26273eb031 100644 --- a/packages/fs/fs-policy/package.json +++ b/packages/fs/fs-policy/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-fs-policy", "description": "File-context policy plugin for the DeepSeek Harness — observed-state, read-before-edit, and version-guarded write/edit added over the ctx.fs provider seam through the fs/* event gate (no service surface)", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/fs/fs-policy" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/fs/fs-sandbox/package.json b/packages/fs/fs-sandbox/package.json index 015a572c19..1622fc2621 100644 --- a/packages/fs/fs-sandbox/package.json +++ b/packages/fs/fs-sandbox/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-fs-sandbox", "description": "Sandbox-enforcing implementation of the DeepSeek Harness filesystem seam: fences write/edit by the per-call sandbox mode (read-only denies mutation, workspace-write contains it to the workspace + temp roots) while reads pass through", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/fs/fs-sandbox" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/fs/fs/package.json b/packages/fs/fs/package.json index c8445419e1..e14e5f0a15 100644 --- a/packages/fs/fs/package.json +++ b/packages/fs/fs/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-fs", "description": "Abstract filesystem capability seam (ctx.fs) for the DeepSeek Harness — vocabulary types, the FileSystem service (text IO + optional version-guarded atomic mutations), and the fs/* policy event vocabulary", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/fs/fs" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/fs/tool-fs-search/package.json b/packages/fs/tool-fs-search/package.json index ab8a988ef6..6e8c611782 100644 --- a/packages/fs/tool-fs-search/package.json +++ b/packages/fs/tool-fs-search/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-tool-fs-search", "description": "Model-facing filesystem discovery tools (glob, grep) backed by the packaged ripgrep binary (@vscode/ripgrep)", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/fs/tool-fs-search" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/fs/tool-fs/package.json b/packages/fs/tool-fs/package.json index b2070827cb..456f7514af 100644 --- a/packages/fs/tool-fs/package.json +++ b/packages/fs/tool-fs/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-tool-fs", "description": "Model-facing filesystem tools (read, write, edit) over the DeepSeek Harness filesystem seam (ctx.fs)", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/fs/tool-fs" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/fs/tool-str-replace-editor/package.json b/packages/fs/tool-str-replace-editor/package.json index 04ad220a3a..7dfd74c7cd 100644 --- a/packages/fs/tool-str-replace-editor/package.json +++ b/packages/fs/tool-str-replace-editor/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-tool-str-replace-editor", "description": "Model-facing view, create, literal replace, and line insert tool over the Harness filesystem service", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/fs/tool-str-replace-editor" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/goal/command-goal/package.json b/packages/goal/command-goal/package.json index daf1ebf924..8a34968cb6 100644 --- a/packages/goal/command-goal/package.json +++ b/packages/goal/command-goal/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-command-goal", "description": "Human-facing slash command for persisted same-session goals", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/goal/command-goal" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/goal/goal-session/package.json b/packages/goal/goal-session/package.json index bd315cb2c1..9fdb8e83e1 100644 --- a/packages/goal/goal-session/package.json +++ b/packages/goal/goal-session/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-goal-session", "description": "Race-fenced same-session goal-round driver", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/goal/goal-session" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/goal/goal/package.json b/packages/goal/goal/package.json index 32ca4d00d9..db2fe9c3c1 100644 --- a/packages/goal/goal/package.json +++ b/packages/goal/goal/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-goal", "description": "Event-sourced same-session goal state and lifecycle service for the DeepSeek Harness", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/goal/goal" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/goal/tool-goal/package.json b/packages/goal/tool-goal/package.json index 0b03bb02b6..8c843fe7e8 100644 --- a/packages/goal/tool-goal/package.json +++ b/packages/goal/tool-goal/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-tool-goal", "description": "Model-facing same-session goal tools with execution-time authority checks", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/goal/tool-goal" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/guard/repeat-tool-guard/package.json b/packages/guard/repeat-tool-guard/package.json index 9bc4fd493f..2f9bf37a0f 100644 --- a/packages/guard/repeat-tool-guard/package.json +++ b/packages/guard/repeat-tool-guard/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-repeat-tool-guard", "description": "Repeat-tool-call guard plugin: advisory reminders when an agent loops on identical tool calls", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/guard/repeat-tool-guard" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/guard/timeout-policy/package.json b/packages/guard/timeout-policy/package.json index 3f56d8e59e..9ea624ee83 100644 --- a/packages/guard/timeout-policy/package.json +++ b/packages/guard/timeout-policy/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-timeout-policy", "description": "Tool-call timeout policy: a tools/execute wrapper that arms a per-tool deadline on exec.signal and returns TOOL_TIMEOUT when it wins", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/guard/timeout-policy" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/hooks/hook-protocol/package.json b/packages/hooks/hook-protocol/package.json index 670cd4df5d..d628b7772c 100644 --- a/packages/hooks/hook-protocol/package.json +++ b/packages/hooks/hook-protocol/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-hook-protocol", "description": "Shared Claude Code / Codex hook wire protocol: matcher engine, stdin/exit-code/stdout codec, multi-hook merge, and hook/* session events", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/hooks/hook-protocol" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/hooks/hooks-claude/package.json b/packages/hooks/hooks-claude/package.json index 2af6a96466..79ea6ec65b 100644 --- a/packages/hooks/hooks-claude/package.json +++ b/packages/hooks/hooks-claude/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-hooks-claude", "description": "Bridge plugin: run a Claude Code hooks.json / settings hook config on the DeepSeek Harness interception seams", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/hooks/hooks-claude" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/hooks/hooks-codex/package.json b/packages/hooks/hooks-codex/package.json index 37ac4d7bed..2f567eed26 100644 --- a/packages/hooks/hooks-codex/package.json +++ b/packages/hooks/hooks-codex/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-hooks-codex", "description": "Bridge plugin: run a Codex hooks.json hook config on the DeepSeek Harness interception seams", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/hooks/hooks-codex" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/host/apiproxy/package.json b/packages/host/apiproxy/package.json index 5ce28e9d05..219704e6dd 100644 --- a/packages/host/apiproxy/package.json +++ b/packages/host/apiproxy/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-host-apiproxy", "description": "API gateway: the ApiProxy contract (api/), the fetch carrier pair (fetch/), and the host-side gateway plugin providing ctx.apiProxy", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/host/apiproxy" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/host/directory-picker-auto/package.json b/packages/host/directory-picker-auto/package.json index b5e5164500..a553fc2c85 100644 --- a/packages/host/directory-picker-auto/package.json +++ b/packages/host/directory-picker-auto/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-host-directory-picker-auto", "description": "Adaptive chooser of the directory-picker seam: resolves the host situation at boot and mounts the native or browse backend for the DeepSeek Harness web GUI host", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/host/directory-picker-auto" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/host/directory-picker-browse/package.json b/packages/host/directory-picker-browse/package.json index 04078b9ea7..329e955c54 100644 --- a/packages/host/directory-picker-browse/package.json +++ b/packages/host/directory-picker-browse/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-host-directory-picker-browse", "description": "In-app browsing backend of the directory-picker seam (listing/creation primitives over the host filesystem)", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/host/directory-picker-browse" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/host/directory-picker-native/package.json b/packages/host/directory-picker-native/package.json index b725cd1001..d3000b1e98 100644 --- a/packages/host/directory-picker-native/package.json +++ b/packages/host/directory-picker-native/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-host-directory-picker-native", "description": "Native-OS-chooser backend of the directory-picker seam for the DeepSeek Harness web GUI host", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/host/directory-picker-native" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/host/directory-picker/package.json b/packages/host/directory-picker/package.json index c348021815..a8feccefbe 100644 --- a/packages/host/directory-picker/package.json +++ b/packages/host/directory-picker/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-host-directory-picker", "description": "Abstract workspace-directory picking seam (ctx.directoryPicker) for the DeepSeek Harness web GUI host", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/host/directory-picker" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/host/frontend-static/package.json b/packages/host/frontend-static/package.json index 73414a5422..9da90e8b20 100644 --- a/packages/host/frontend-static/package.json +++ b/packages/host/frontend-static/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-frontend-static", "description": "SPA dist server for the Web shell: owns the webserver fallback seat, serving the built frontend with index-tap injection, traversal rejection, and SPA index fallback", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/host/frontend-static" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/host/webserver/package.json b/packages/host/webserver/package.json index e7a4b4cbf9..0f29d976e6 100644 --- a/packages/host/webserver/package.json +++ b/packages/host/webserver/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-host-webserver", "description": "Web route-registration plugin: HTTP and upgrade routes, index transform taps, and static dist fallback; knows no harness concepts", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/host/webserver" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/interaction/commands/package.json b/packages/interaction/commands/package.json index 96fd3e6740..2909fda952 100644 --- a/packages/interaction/commands/package.json +++ b/packages/interaction/commands/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-commands", "description": "Plugin-owned human command registry for DeepSeek Harness UI surfaces", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/interaction/commands" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/interaction/permission/package.json b/packages/interaction/permission/package.json index 5fad3f9d25..4ec76c4e16 100644 --- a/packages/interaction/permission/package.json +++ b/packages/interaction/permission/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-permission", "description": "User-facing permission presets (ctx.permission) for the DeepSeek Harness: one product-level Permissions select bundling the sandbox-mode and approval-policy knobs, written through to their own session events", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/interaction/permission" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/interaction/tool-ask-user/package.json b/packages/interaction/tool-ask-user/package.json index b7291d4ccc..76b103ca04 100644 --- a/packages/interaction/tool-ask-user/package.json +++ b/packages/interaction/tool-ask-user/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-tool-ask-user", "description": "Model-facing ask_user_question tool over the ctx.userInteraction seam", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/interaction/tool-ask-user" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/interaction/user-approval/package.json b/packages/interaction/user-approval/package.json index 854e316df9..99f1e82f1f 100644 --- a/packages/interaction/user-approval/package.json +++ b/packages/interaction/user-approval/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-user-approval", "description": "User-approval seam (ctx.approval) for the DeepSeek Harness: one-shot permission decisions dispatched to composed answerers over the approval/request waterfall, fail-closed by default", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/interaction/user-approval" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/interaction/user-interaction/package.json b/packages/interaction/user-interaction/package.json index c72e3f1298..67022c524b 100644 --- a/packages/interaction/user-interaction/package.json +++ b/packages/interaction/user-interaction/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-user-interaction", "description": "Abstract user-interaction seam (ctx.userInteraction) for asking the human during agent runs", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/interaction/user-interaction" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/llm/llm-deepseek/package.json b/packages/llm/llm-deepseek/package.json index d2573696be..3bc2702d1b 100644 --- a/packages/llm/llm-deepseek/package.json +++ b/packages/llm/llm-deepseek/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-llm-deepseek", "description": "DeepSeek chat-completions adapter for the DeepSeek Harness LLM seam", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/llm/llm-deepseek" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/llm/llm-pi-ai/package.json b/packages/llm/llm-pi-ai/package.json index f7a931d902..06003f4165 100644 --- a/packages/llm/llm-pi-ai/package.json +++ b/packages/llm/llm-pi-ai/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-llm-pi-ai", "description": "pi-ai-backed DeepSeek adapter for the DeepSeek Harness LLM seam (design-verification twin of dsh-llm-deepseek)", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/llm/llm-pi-ai" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/llm/llm-retry/package.json b/packages/llm/llm-retry/package.json index 5f69487147..8baa7e8e5d 100644 --- a/packages/llm/llm-retry/package.json +++ b/packages/llm/llm-retry/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-llm-retry", "description": "Provider-routed LLM request retry policy for the DeepSeek Harness", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/llm/llm-retry" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/llm/llm/package.json b/packages/llm/llm/package.json index 1a11622738..67a45ccf88 100644 --- a/packages/llm/llm/package.json +++ b/packages/llm/llm/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-llm", "description": "Provider-neutral LLM service interface for the DeepSeek Harness", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/llm/llm" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/llm/token-meter/package.json b/packages/llm/token-meter/package.json index 61cd66617f..50762fc86f 100644 --- a/packages/llm/token-meter/package.json +++ b/packages/llm/token-meter/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-token-meter", "description": "Replay-aware token measurement service (ctx.tokenMeter) for the DeepSeek Harness", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/llm/token-meter" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/lsp/lsp-local/package.json b/packages/lsp/lsp-local/package.json index 02fcddd558..0a2181c3de 100644 --- a/packages/lsp/lsp-local/package.json +++ b/packages/lsp/lsp-local/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-lsp-local", "description": "Generic stdio language-server provider for the DeepSeek Harness LSP capability seam (ctx.lsp) — spawns configured servers, translates JSON-RPC, and serves transient-open goToDefinition/findReferences/goToImplementation/hover queries in the host filesystem namespace", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/lsp/lsp-local" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/lsp/lsp/package.json b/packages/lsp/lsp/package.json index d5993b515e..c4a2385665 100644 --- a/packages/lsp/lsp/package.json +++ b/packages/lsp/lsp/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-lsp", "description": "Abstract LSP capability seam (ctx.lsp) for the DeepSeek Harness — language-server provider registry keyed by branded id and extension mapping, order-independent per-query selection, normalized definition/references/implementation/hover requests and results, and the LspError taxonomy", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/lsp/lsp" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/lsp/tool-lsp/package.json b/packages/lsp/tool-lsp/package.json index 7b7dc54dc2..4a23cffe88 100644 --- a/packages/lsp/tool-lsp/package.json +++ b/packages/lsp/tool-lsp/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-tool-lsp", "description": "Model-facing lsp tool over the DeepSeek Harness LSP capability seam (ctx.lsp) — one read-only tool with goToDefinition/findReferences/goToImplementation/hover operations, one-based UTF-16 cursor coordinates, bounded location rendering, and hover normalization", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/lsp/tool-lsp" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/mcp/mcp-client/package.json b/packages/mcp/mcp-client/package.json index e5b110e7db..a7f3fc3b90 100644 --- a/packages/mcp/mcp-client/package.json +++ b/packages/mcp/mcp-client/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-mcp-client", "description": "MCP client bridge: connects to MCP servers and registers their tools on ctx.tools", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/mcp/mcp-client" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/plan/plan-mode/package.json b/packages/plan/plan-mode/package.json index d5c24e3877..1c8b81cc30 100644 --- a/packages/plan/plan-mode/package.json +++ b/packages/plan/plan-mode/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-plan-mode", "description": "Logged per-agent plan mode with deployment guidance, a direct slash command, and a user-reviewed exit", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/plan/plan-mode" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/preset/agent-presets/package.json b/packages/preset/agent-presets/package.json index 5a08e6f99d..00a8318ad0 100644 --- a/packages/preset/agent-presets/package.json +++ b/packages/preset/agent-presets/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-agent-presets", "description": "Per-session agent composition from preset cordis.yml files for the DeepSeek Harness", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/preset/agent-presets" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/preset/persona/package.json b/packages/preset/persona/package.json index cda2faf015..193a9cb45e 100644 --- a/packages/preset/persona/package.json +++ b/packages/preset/persona/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-persona", "description": "Composition-authored deployment persona section for the DeepSeek Harness", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/preset/persona" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/pty/pty-local/package.json b/packages/pty/pty-local/package.json index 82705255dc..9aad0c1502 100644 --- a/packages/pty/pty-local/package.json +++ b/packages/pty/pty-local/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-pty-local", "description": "Persistent shell PTY backend over the DeepSeek Harness subprocess terminal primitive", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/pty/pty-local" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/pty/pty/package.json b/packages/pty/pty/package.json index 9671cfd8ca..75f3b33302 100644 --- a/packages/pty/pty/package.json +++ b/packages/pty/pty/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-pty", "description": "Persistent PTY session seam for the DeepSeek Harness — owner-scoped ids, backend registry, interactive sends, reads, signals, and awaited cleanup", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/pty/pty" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/pty/tool-bash-persistent/package.json b/packages/pty/tool-bash-persistent/package.json index fdd5688e8e..34d95c6f78 100644 --- a/packages/pty/tool-bash-persistent/package.json +++ b/packages/pty/tool-bash-persistent/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-tool-bash-persistent", "description": "Model-facing owner-scoped persistent Bash tool backed by the Harness PTY service", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/pty/tool-bash-persistent" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/pty/tool-pty/package.json b/packages/pty/tool-pty/package.json index f3afefdc0a..2db01c4416 100644 --- a/packages/pty/tool-pty/package.json +++ b/packages/pty/tool-pty/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-tool-pty", "description": "Six model-facing persistent PTY tools with owner isolation and generic background-task integration", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/pty/tool-pty" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/sandbox/sandbox-local/package.json b/packages/sandbox/sandbox-local/package.json index 5af6264b4a..c68cd8532a 100644 --- a/packages/sandbox/sandbox-local/package.json +++ b/packages/sandbox/sandbox-local/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-sandbox-local", "description": "Local process-sandbox backends for the DeepSeek Harness sandbox seam: bwrap, the npm-distributed landlock-run launcher, macOS Seatbelt, or the Windows ACL restricted-token runner — functionally probed, fail-closed", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/sandbox/sandbox-local" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/sandbox/sandbox-policy/package.json b/packages/sandbox/sandbox-policy/package.json index 7636977d6e..d90befdd9e 100644 --- a/packages/sandbox/sandbox-policy/package.json +++ b/packages/sandbox/sandbox-policy/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-sandbox-policy", "description": "Per-call sandbox policy resolver and current model context: deployment fallbacks plus each session's mode and workspace root, shared by every enforcing capability family", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/sandbox/sandbox-policy" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/sandbox/sandbox-windows-acl/package.json b/packages/sandbox/sandbox-windows-acl/package.json index 8305b2cc20..6d8d9c722b 100644 --- a/packages/sandbox/sandbox-windows-acl/package.json +++ b/packages/sandbox/sandbox-windows-acl/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-sandbox-windows-acl", "description": "Windows ACL write-restriction sandbox backend (restricted-token spawn with orphan-SID write allowlist) for the DeepSeek Harness sandbox seam", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/sandbox/sandbox-windows-acl" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/sandbox/sandbox/package.json b/packages/sandbox/sandbox/package.json index 558588cfa7..9fc9f8a460 100644 --- a/packages/sandbox/sandbox/package.json +++ b/packages/sandbox/sandbox/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-sandbox", "description": "Abstract process-sandbox seam (ctx.sandbox) for the DeepSeek Harness: same-world confinement vocabulary and the SandboxProvider contract", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/sandbox/sandbox" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/scaffold/client/package.json b/packages/scaffold/client/package.json index 7e0a4b0540..227e00a1ab 100644 --- a/packages/scaffold/client/package.json +++ b/packages/scaffold/client/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-sdk-client", "description": "TypeScript client SDK for driving a DeepSeek Harness runtime subprocess over stdio JSON-RPC: the DeepSeekHarness high-level turns API and the lower-level HarnessClient", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/scaffold/client" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/scaffold/create-sdk/package.json b/packages/scaffold/create-sdk/package.json index 4b40b6b2ca..e61b645303 100644 --- a/packages/scaffold/create-sdk/package.json +++ b/packages/scaffold/create-sdk/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/create-sdk", "description": "Create a DeepSeek Harness SDK project with npm create @deepseek-ai/sdk", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/scaffold/create-sdk" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/scaffold/helper/package.json b/packages/scaffold/helper/package.json index f65b51052a..0266daaba1 100644 --- a/packages/scaffold/helper/package.json +++ b/packages/scaffold/helper/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-helper", "description": "Domain model and infrastructure for creating and editing DeepSeek Harness SDK projects", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/scaffold/helper" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/scaffold/protocol/package.json b/packages/scaffold/protocol/package.json index c0d6ff1046..feb8784a6d 100644 --- a/packages/scaffold/protocol/package.json +++ b/packages/scaffold/protocol/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-sdk-protocol", "description": "Shared wire protocol for the DeepSeek Harness SDK runtime: the newline-delimited JSON-RPC stdio transport and the named request, result, and notification types spoken between the runtime server and SDK clients", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/scaffold/protocol" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/scaffold/scripts/package.json b/packages/scaffold/scripts/package.json index d6ef776d67..e24969d78d 100644 --- a/packages/scaffold/scripts/package.json +++ b/packages/scaffold/scripts/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-scripts", "description": "DeepSeek Harness SDK launcher for start, dev, build, and project configuration", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/scaffold/scripts" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/scaffold/server/package.json b/packages/scaffold/server/package.json index 457a375b04..6911f4b117 100644 --- a/packages/scaffold/server/package.json +++ b/packages/scaffold/server/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-jsonrpc", "description": "Stdio JSON-RPC server plugin for out-of-process DeepSeek Harness SDK clients", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/scaffold/server" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/scaffold/telemetry/package.json b/packages/scaffold/telemetry/package.json index 3ebd894a99..419d8f9ed1 100644 --- a/packages/scaffold/telemetry/package.json +++ b/packages/scaffold/telemetry/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-telemetry", "description": "Launcher-side dsh-sdk telemetry: secret redaction, consent resolution, anonymous id, payload builder, and fire-and-forget reporter", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/scaffold/telemetry" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/self-modification/tool-cordis/package.json b/packages/self-modification/tool-cordis/package.json index 5544c84b49..1fc3fcebb1 100644 --- a/packages/self-modification/tool-cordis/package.json +++ b/packages/self-modification/tool-cordis/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-tool-cordis", "description": "Self-referential cordis toolset: inspect the live runtime, mount and dispose model-written plugins", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/self-modification/tool-cordis" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/session-query/session-query-sqlite/package.json b/packages/session-query/session-query-sqlite/package.json index d2ca6da01a..a54c9e0e1b 100644 --- a/packages/session-query/session-query-sqlite/package.json +++ b/packages/session-query/session-query-sqlite/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-session-query-sqlite", "description": "Concrete ctx.sessionQuery backend with SQLite FTS5 search", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/session-query/session-query-sqlite" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/session-query/session-query/package.json b/packages/session-query/session-query/package.json index 30e6a52593..cdd3d740f5 100644 --- a/packages/session-query/session-query/package.json +++ b/packages/session-query/session-query/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-session-query", "description": "Combined session query service contract with concrete reads, traces, and filters", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/session-query/session-query" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/session-query/tool-session-query/package.json b/packages/session-query/tool-session-query/package.json index 0e8f8c95ee..0da248f48a 100644 --- a/packages/session-query/tool-session-query/package.json +++ b/packages/session-query/tool-session-query/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-tool-session-query", "description": "Workspace-authorized model-facing session history search, trace, and event read tools", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/session-query/tool-session-query" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/session/session-checkpoint-policy/package.json b/packages/session/session-checkpoint-policy/package.json index 6a7a07ad13..8a5766641f 100644 --- a/packages/session/session-checkpoint-policy/package.json +++ b/packages/session/session-checkpoint-policy/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-session-checkpoint-policy", "description": "Semantic session durability checkpoints before model requests and tool side effects", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/session/session-checkpoint-policy" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/session/session-persistence-jsonl/package.json b/packages/session/session-persistence-jsonl/package.json index 9960565102..6bc752ed0f 100644 --- a/packages/session/session-persistence-jsonl/package.json +++ b/packages/session/session-persistence-jsonl/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-session-persistence-jsonl", "description": "JSONL durable session persistence backend for the DeepSeek Harness", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/session/session-persistence-jsonl" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/session/session-persistence-sqlite/package.json b/packages/session/session-persistence-sqlite/package.json index 62bbba8dba..8d6f05cbd8 100644 --- a/packages/session/session-persistence-sqlite/package.json +++ b/packages/session/session-persistence-sqlite/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-session-persistence-sqlite", "description": "SQLite durable session persistence backend for the DeepSeek Harness", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/session/session-persistence-sqlite" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/session/session-persistence/package.json b/packages/session/session-persistence/package.json index 94b1455beb..d556ebff73 100644 --- a/packages/session/session-persistence/package.json +++ b/packages/session/session-persistence/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-session-persistence", "description": "Abstract durable session persistence seam (ctx.sessionPersistence) for the DeepSeek Harness", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/session/session-persistence" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/session/session-projection-cache/package.json b/packages/session/session-projection-cache/package.json index d54b0d18e7..885c293dc9 100644 --- a/packages/session/session-projection-cache/package.json +++ b/packages/session/session-projection-cache/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-session-projection-cache", "description": "Persisted projection cache (ctx.sessionProjectionCache): durable per-session projection checkpoints over the domain data form, throttled write-behind, and the cold-read ladder (cache row + persistence tail replay)", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/session/session-projection-cache" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/session/session-projection/package.json b/packages/session/session-projection/package.json index 46445673ab..d17884eadb 100644 --- a/packages/session/session-projection/package.json +++ b/packages/session/session-projection/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-session-projection", "description": "Session-projection seam: the merge-extensible projection type table, the provider contract, and the ctx.sessionProjections registry serving whole current values of log-derived per-session state", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/session/session-projection" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/session/session-telemetry-otel/package.json b/packages/session/session-telemetry-otel/package.json index 9a8c4e914f..569e62e70b 100644 --- a/packages/session/session-telemetry-otel/package.json +++ b/packages/session/session-telemetry-otel/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-session-telemetry-otel", "description": "OpenTelemetry backend for the DeepSeek Harness telemetry seam: hands captured session records to the OTel JS SDK's log pipeline", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/session/session-telemetry-otel" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/session/session-telemetry/package.json b/packages/session/session-telemetry/package.json index 2176d02313..d9ac09b6b7 100644 --- a/packages/session/session-telemetry/package.json +++ b/packages/session/session-telemetry/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-session-telemetry", "description": "Telemetry seam for the DeepSeek Harness: session-event capture, projection, redaction, and handoff to a reporting backend", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/session/session-telemetry" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/session/session-title-all-messages-llm/package.json b/packages/session/session-title-all-messages-llm/package.json index 70c3b4c255..ecd82f5f72 100644 --- a/packages/session/session-title-all-messages-llm/package.json +++ b/packages/session/session-title-all-messages-llm/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-session-title-all-messages-llm", "description": "All-user-messages LLM provider plugin for DeepSeek Harness session titles", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/session/session-title-all-messages-llm" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/session/session-title-first-message-llm/package.json b/packages/session/session-title-first-message-llm/package.json index 0c934c192b..88e8ddb1ca 100644 --- a/packages/session/session-title-first-message-llm/package.json +++ b/packages/session/session-title-first-message-llm/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-session-title-first-message-llm", "description": "First-message LLM provider plugin for DeepSeek Harness session titles", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/session/session-title-first-message-llm" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/session/session-title-llm/package.json b/packages/session/session-title-llm/package.json index 6e5acac31f..7b2c4caacd 100644 --- a/packages/session/session-title-llm/package.json +++ b/packages/session/session-title-llm/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-session-title-llm", "description": "Shared LLM generation policy for DeepSeek Harness session-title providers", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/session/session-title-llm" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/session/session-title/package.json b/packages/session/session-title/package.json index 820df4c70d..84a3b8caaf 100644 --- a/packages/session/session-title/package.json +++ b/packages/session/session-title/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-session-title", "description": "Log-backed session title service and provider registry for the DeepSeek Harness", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/session/session-title" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/session/user-id/package.json b/packages/session/user-id/package.json index 5e86cc4a32..fe733ccfd0 100644 --- a/packages/session/user-id/package.json +++ b/packages/session/user-id/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-user-id", "description": "Shared anonymous user identity for DeepSeek Harness telemetry and feedback correlation", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/session/user-id" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/settings/settings-local/package.json b/packages/settings/settings-local/package.json index 5e086b8efe..c66e51274d 100644 --- a/packages/settings/settings-local/package.json +++ b/packages/settings/settings-local/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-settings-local", "description": "File-backed settings provider (settings.yaml) for the DeepSeek Harness", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/settings/settings-local" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/settings/settings/package.json b/packages/settings/settings/package.json index 23cb60d13c..da6a1cccc0 100644 --- a/packages/settings/settings/package.json +++ b/packages/settings/settings/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-settings", "description": "Abstract user-settings seam (ctx.settings) for the DeepSeek Harness", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/settings/settings" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/skill/skill-badge/package.json b/packages/skill/skill-badge/package.json index 7df1703c0e..5b23d44f9c 100644 --- a/packages/skill/skill-badge/package.json +++ b/packages/skill/skill-badge/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-skill-badge", "description": "Bundled dsh badge skill provider for DeepSeek Harness", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/skill/skill-badge" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/skill/skill-local/package.json b/packages/skill/skill-local/package.json index 24ce31af02..1cec60bf92 100644 --- a/packages/skill/skill-local/package.json +++ b/packages/skill/skill-local/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-skill-local", "description": "Local filesystem skill provider for the DeepSeek Harness", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/skill/skill-local" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/skill/skill/package.json b/packages/skill/skill/package.json index 20309664cd..921adf7632 100644 --- a/packages/skill/skill/package.json +++ b/packages/skill/skill/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-skill", "description": "Agent skill provider registry for the DeepSeek Harness", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/skill/skill" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/skill/tool-skill/package.json b/packages/skill/tool-skill/package.json index 07adab663a..25e0f9b2c9 100644 --- a/packages/skill/tool-skill/package.json +++ b/packages/skill/tool-skill/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-tool-skill", "description": "Model-facing skill loading tool for the DeepSeek Harness", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/skill/tool-skill" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/spill/spill-local/package.json b/packages/spill/spill-local/package.json index fcfacf1dcf..7dd63ce56a 100644 --- a/packages/spill/spill-local/package.json +++ b/packages/spill/spill-local/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-spill-local", "description": "Local-filesystem implementation of the DeepSeek Harness spill storage seam (private session-scoped files)", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/spill/spill-local" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/spill/spill-policy/package.json b/packages/spill/spill-policy/package.json index 3d6cda2186..f425208b8d 100644 --- a/packages/spill/spill-policy/package.json +++ b/packages/spill/spill-policy/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-spill-policy", "description": "Tool-result spill policy for the DeepSeek Harness — replaces oversized plain-text tool results with a retained preview plus a spill-file path (no service surface)", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/spill/spill-policy" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/spill/spill/package.json b/packages/spill/spill/package.json index 996069461e..9340d28a37 100644 --- a/packages/spill/spill/package.json +++ b/packages/spill/spill/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-spill", "description": "Abstract spill storage seam (ctx.spillStore) for the DeepSeek Harness — save oversized tool text and return a retrieval locator", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/spill/spill" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/storage/storage-domain/package.json b/packages/storage/storage-domain/package.json index fe5915c2ea..5c6f8836f0 100644 --- a/packages/storage/storage-domain/package.json +++ b/packages/storage/storage-domain/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-storage-domain", "description": "Domain data form (ctx.storage.domain): schema-validated, event-emitting KV domains over storage backends for the DeepSeek Harness", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/storage/storage-domain" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/storage/storage-json/package.json b/packages/storage/storage-json/package.json index 55012ed819..73d8ed9e74 100644 --- a/packages/storage/storage-json/package.json +++ b/packages/storage/storage-json/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-storage-json", "description": "JSON file KV storage backend for the DeepSeek Harness storage hub", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/storage/storage-json" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/storage/storage-sqlite/package.json b/packages/storage/storage-sqlite/package.json index 6283822419..4ad22a7946 100644 --- a/packages/storage/storage-sqlite/package.json +++ b/packages/storage/storage-sqlite/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-storage-sqlite", "description": "SQLite storage backend (kv facet) for the DeepSeek Harness storage hub", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/storage/storage-sqlite" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/storage/storage/package.json b/packages/storage/storage/package.json index 094814dfa1..b638d392e0 100644 --- a/packages/storage/storage/package.json +++ b/packages/storage/storage/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-storage", "description": "Storage hub (ctx.storage): named backend registry plus mounted data-form facilities for the DeepSeek Harness", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/storage/storage" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/subagent/subagent-acp/package.json b/packages/subagent/subagent-acp/package.json index a99154af56..155e89ced1 100644 --- a/packages/subagent/subagent-acp/package.json +++ b/packages/subagent/subagent-acp/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-subagent-acp", "description": "Out-of-process ACP subagent backend: drives a child agent in a spawned subprocess over the Agent Client Protocol", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/subagent/subagent-acp" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/subagent/subagent-claude-code/package.json b/packages/subagent/subagent-claude-code/package.json index d2234104cb..758d30435c 100644 --- a/packages/subagent/subagent-claude-code/package.json +++ b/packages/subagent/subagent-claude-code/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-subagent-claude-code", "description": "One-shot Claude Code subagent provider over the official Agent SDK", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/subagent/subagent-claude-code" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/subagent/subagent-codex/package.json b/packages/subagent/subagent-codex/package.json index a14173e3ee..e44de3fa75 100644 --- a/packages/subagent/subagent-codex/package.json +++ b/packages/subagent/subagent-codex/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-subagent-codex", "description": "One-shot Codex subagent provider over the official app-server protocol", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/subagent/subagent-codex" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/subagent/subagent-dsh-sdk/package.json b/packages/subagent/subagent-dsh-sdk/package.json index 58bdd83e13..22d66af4bd 100644 --- a/packages/subagent/subagent-dsh-sdk/package.json +++ b/packages/subagent/subagent-dsh-sdk/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-subagent-dsh-sdk", "description": "Out-of-process SDK subagent backend: drives a child DeepSeek Harness runtime subprocess over stdio JSON-RPC through the TypeScript SDK client", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/subagent/subagent-dsh-sdk" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/subagent/subagent-fork/package.json b/packages/subagent/subagent-fork/package.json index 57d79a38d4..c0abf8ab3f 100644 --- a/packages/subagent/subagent-fork/package.json +++ b/packages/subagent/subagent-fork/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-subagent-fork", "description": "In-process fork subagent backend: runs a child agent seeded with a prefix of the parent's log", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/subagent/subagent-fork" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/subagent/subagent-inprocess/package.json b/packages/subagent/subagent-inprocess/package.json index 15dfe1c321..09fe807748 100644 --- a/packages/subagent/subagent-inprocess/package.json +++ b/packages/subagent/subagent-inprocess/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-subagent-inprocess", "description": "Shared in-process subagent run driver: drives a child agent on ctx.agents (used by the spawn and fork backends)", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/subagent/subagent-inprocess" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/subagent/subagent-spawn/package.json b/packages/subagent/subagent-spawn/package.json index f20b96227c..c865aa5251 100644 --- a/packages/subagent/subagent-spawn/package.json +++ b/packages/subagent/subagent-spawn/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-subagent-spawn", "description": "In-process spawn subagent backend: runs a fresh child agent on ctx.agents", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/subagent/subagent-spawn" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/subagent/subagent/package.json b/packages/subagent/subagent/package.json index fc1f2dfb86..070fe2c8cb 100644 --- a/packages/subagent/subagent/package.json +++ b/packages/subagent/subagent/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-subagent", "description": "Abstract subagent seam (ctx.subagents): named-provider registry for delegating to child agents", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/subagent/subagent" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/subagent/tool-subagent-control/package.json b/packages/subagent/tool-subagent-control/package.json index d1ca31c635..c89d35c727 100644 --- a/packages/subagent/tool-subagent-control/package.json +++ b/packages/subagent/tool-subagent-control/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-tool-subagent-control", "description": "Globally named send_message, interrupt_agent, and list_agents tools over ctx.subagents continuations", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/subagent/tool-subagent-control" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/subagent/tool-subagent-report/package.json b/packages/subagent/tool-subagent-report/package.json index c3f0e530ec..665230bdbd 100644 --- a/packages/subagent/tool-subagent-report/package.json +++ b/packages/subagent/tool-subagent-report/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-tool-subagent-report", "description": "Child-scoped report tool over ctx.subagents continuations", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/subagent/tool-subagent-report" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/subagent/tool-subagent/package.json b/packages/subagent/tool-subagent/package.json index d5d0da52d4..5ba14c54b7 100644 --- a/packages/subagent/tool-subagent/package.json +++ b/packages/subagent/tool-subagent/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-tool-subagent", "description": "Model-facing subagent delegation tool over the ctx.subagents seam", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/subagent/tool-subagent" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/subprocess/subprocess-local/package.json b/packages/subprocess/subprocess-local/package.json index d966c0efb8..a9547a9c48 100644 --- a/packages/subprocess/subprocess-local/package.json +++ b/packages/subprocess/subprocess-local/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-subprocess-local", "description": "Local-subprocess implementation of the DeepSeek Harness subprocess seam", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/subprocess/subprocess-local" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/subprocess/subprocess/package.json b/packages/subprocess/subprocess/package.json index f22708c717..a1a4e40865 100644 --- a/packages/subprocess/subprocess/package.json +++ b/packages/subprocess/subprocess/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-subprocess", "description": "Subprocess seam (ctx.subprocess) for the DeepSeek Harness — managed process groups, bounded spill-backed output, and escalated kills behind one abstract service", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/subprocess/subprocess" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/support/acp-snapshot/package.json b/packages/support/acp-snapshot/package.json index fb4e13ec1e..929ba31708 100644 --- a/packages/support/acp-snapshot/package.json +++ b/packages/support/acp-snapshot/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-acp-snapshot", "description": "ACP test kit: shared subprocess launcher, snapshot scenario harness, expected-output normalizers, and suite factory", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/support/acp-snapshot" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/support/agent-loop-testkit/package.json b/packages/support/agent-loop-testkit/package.json index 2bbfa195a7..5ca1382750 100644 --- a/packages/support/agent-loop-testkit/package.json +++ b/packages/support/agent-loop-testkit/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-agent-loop-testkit", "description": "Shared prerequisite mounting for tests that exercise the concrete agent loop", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/support/agent-loop-testkit" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/support/invariants/package.json b/packages/support/invariants/package.json index 3ef3a80f41..0f1503b835 100644 --- a/packages/support/invariants/package.json +++ b/packages/support/invariants/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-invariants", "description": "Registry service for package-owned DeepSeek Harness runtime invariants", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/support/invariants" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/support/llm-mock-server/package.json b/packages/support/llm-mock-server/package.json index c342697f01..9f5acda6cb 100644 --- a/packages/support/llm-mock-server/package.json +++ b/packages/support/llm-mock-server/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-llm-mock-server", "description": "Scriptable OpenAI-compatible HTTP/SSE fault server for LLM recovery tests", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/support/llm-mock-server" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/support/llm-replay/package.json b/packages/support/llm-replay/package.json index 0c85caf96f..d199ea5a4f 100644 --- a/packages/support/llm-replay/package.json +++ b/packages/support/llm-replay/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-llm-replay", "description": "Replay LLM plugin: short-circuits llm/stream with model chunks reconstructed from a recorded session JSONL (keyless snapshot tests)", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/support/llm-replay" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/support/loader-smoke/package.json b/packages/support/loader-smoke/package.json index 10dc20f863..0de74f6e60 100644 --- a/packages/support/loader-smoke/package.json +++ b/packages/support/loader-smoke/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-loader-smoke", "description": "Shared subprocess and direct-agent harness for keyless real-Loader example smoke tests", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/support/loader-smoke" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/tasks/tasks-local/package.json b/packages/tasks/tasks-local/package.json index 76deaf9b8d..aa4673b811 100644 --- a/packages/tasks/tasks-local/package.json +++ b/packages/tasks/tasks-local/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-tasks-local", "description": "Process-local implementation of the DeepSeek Harness background task registry seam", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/tasks/tasks-local" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/tasks/tasks/package.json b/packages/tasks/tasks/package.json index 61b8cd1ab8..2e59a68679 100644 --- a/packages/tasks/tasks/package.json +++ b/packages/tasks/tasks/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-tasks", "description": "Background task registry (ctx.tasks) for the DeepSeek Harness — shared ids, owner isolation, polling, cancellation, and completion listeners for long-running tool work", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/tasks/tasks" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/tasks/tool-tasks/package.json b/packages/tasks/tool-tasks/package.json index 38827df4f8..f55816cc82 100644 --- a/packages/tasks/tool-tasks/package.json +++ b/packages/tasks/tool-tasks/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-tool-tasks", "description": "Model-facing background task control tools (task_output, task_list, task_kill) over the ctx.tasks registry", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/tasks/tool-tasks" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/todo/tool-todo/package.json b/packages/todo/tool-todo/package.json index ee57660440..3bd9294687 100644 --- a/packages/todo/tool-todo/package.json +++ b/packages/todo/tool-todo/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-tool-todo", "description": "Model-facing todo_write tool over the DeepSeek Harness event-sourced session log", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/todo/tool-todo" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/typert/generator/package.json b/packages/typert/generator/package.json index fd9f14c449..117f18f48b 100644 --- a/packages/typert/generator/package.json +++ b/packages/typert/generator/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-typert-generator", "description": "TypeScript project analyzer and model-driven Typert artifact generator", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/typert/generator" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/typert/loader/package.json b/packages/typert/loader/package.json index 998c0ec3a5..4f33f4bc23 100644 --- a/packages/typert/loader/package.json +++ b/packages/typert/loader/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-typert-loader", "description": "Loader integration for generated Typert package contributions", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/typert/loader" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/typert/registry/package.json b/packages/typert/registry/package.json index dacb88764b..67f2611db1 100644 --- a/packages/typert/registry/package.json +++ b/packages/typert/registry/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-typert-registry", "description": "Runtime registry for generated package reflection and Zod schemas", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/typert/registry" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/typert/type-meta/package.json b/packages/typert/type-meta/package.json index 9a1c362780..ae3fb96a2b 100644 --- a/packages/typert/type-meta/package.json +++ b/packages/typert/type-meta/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-type-meta", "description": "Compiler-independent Remote metadata and TypeRT provider protocols", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/typert/type-meta" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/util/atomic-write/package.json b/packages/util/atomic-write/package.json index b54b5989cf..5556d4ab96 100644 --- a/packages/util/atomic-write/package.json +++ b/packages/util/atomic-write/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-atomic-write", "description": "Zero-dependency atomic file replacement: exclusive-create random-suffix temp + rename carrying the caller-stated permissions (writeFileAtomic)", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/util/atomic-write" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/util/brand/package.json b/packages/util/brand/package.json index 534cb20049..cdf9307e73 100644 --- a/packages/util/brand/package.json +++ b/packages/util/brand/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-brand", "description": "Type-only Branded nominal-typing primitive for the DeepSeek Harness", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/util/brand" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/util/environment/package.json b/packages/util/environment/package.json index 113f3b10c9..7eee1c2b1e 100644 --- a/packages/util/environment/package.json +++ b/packages/util/environment/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-environment", "description": "Immutable DeepSeek Harness launch environment that records which layer supplied each value", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/util/environment" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/util/native-command/package.json b/packages/util/native-command/package.json index a50e0f2c12..81c6c8c771 100644 --- a/packages/util/native-command/package.json +++ b/packages/util/native-command/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-native-command", "description": "Zero-dependency no-shell execFile runner for host-native OS integrations: utf8 stdio capture, abort propagation, Windows hide", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/util/native-command" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/util/paths/package.json b/packages/util/paths/package.json index 749d3e7ac9..2405fc5b65 100644 --- a/packages/util/paths/package.json +++ b/packages/util/paths/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-paths", "description": "Shared filesystem path helpers for the DeepSeek Harness", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/util/paths" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/util/retention/package.json b/packages/util/retention/package.json index ad61896d35..d7eec5489a 100644 --- a/packages/util/retention/package.json +++ b/packages/util/retention/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-retention", "description": "Zero-dependency bounded-retention primitive: ItemRetainer/TextRetainer + neutral notice helpers (what did we keep, what did we omit)", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/util/retention" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/util/timeout/package.json b/packages/util/timeout/package.json index 0a398aa7a4..2404dd13ff 100644 --- a/packages/util/timeout/package.json +++ b/packages/util/timeout/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-timeout", "description": "Zero-dependency timeout/deadline primitive: clampTimeout, deadline, timeoutOf, TimeoutReason (timing + classification only, no termination)", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/util/timeout" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/web/tool-web/package.json b/packages/web/tool-web/package.json index 585c5a0e83..2eb44ba59c 100644 --- a/packages/web/tool-web/package.json +++ b/packages/web/tool-web/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-tool-web", "description": "Model-facing web tools (web_search, web_fetch) over the DeepSeek Harness web capability seam (ctx.web)", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/web/tool-web" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/web/web-fetch-local/package.json b/packages/web/web-fetch-local/package.json index cc34f6535d..61948fb142 100644 --- a/packages/web/web-fetch-local/package.json +++ b/packages/web/web-fetch-local/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-web-fetch-local", "description": "Anonymous public HTTP(S) fetch provider for the DeepSeek Harness web capability seam (ctx.web)", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/web/web-fetch-local" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/web/web-search-deepseek/package.json b/packages/web/web-search-deepseek/package.json index cee385654b..bcca1d616a 100644 --- a/packages/web/web-search-deepseek/package.json +++ b/packages/web/web-search-deepseek/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-web-search-deepseek", "description": "DeepSeek-backed search provider (native web_search via the Anthropic-compatible API) for the DeepSeek Harness web capability seam (ctx.web)", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/web/web-search-deepseek" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/web/web-search-exa/package.json b/packages/web/web-search-exa/package.json index 1861465ce9..15e907649d 100644 --- a/packages/web/web-search-exa/package.json +++ b/packages/web/web-search-exa/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-web-search-exa", "description": "Exa-backed search provider for the DeepSeek Harness web capability seam (ctx.web)", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/web/web-search-exa" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/web/web-search-perplexity/package.json b/packages/web/web-search-perplexity/package.json index 9c821c8dd7..a952c7f83d 100644 --- a/packages/web/web-search-perplexity/package.json +++ b/packages/web/web-search-perplexity/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-web-search-perplexity", "description": "Perplexity-backed search provider for the DeepSeek Harness web capability seam (ctx.web)", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/web/web-search-perplexity" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/web/web/package.json b/packages/web/web/package.json index 4d4f787412..6f74c65f2b 100644 --- a/packages/web/web/package.json +++ b/packages/web/web/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-web", "description": "Abstract web access capability seam (ctx.web) for the DeepSeek Harness — search/fetch provider registry, registration-order-independent selection, request/result vocabulary, and the WebError taxonomy", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/web/web" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/workflow/tool-ralph/package.json b/packages/workflow/tool-ralph/package.json index c2ebc18c31..184f656206 100644 --- a/packages/workflow/tool-ralph/package.json +++ b/packages/workflow/tool-ralph/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-tool-ralph", "description": "Model-facing fresh-agent Ralph loop over the workflow and subagent seams", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/workflow/tool-ralph" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/workflow/tool-workflow/package.json b/packages/workflow/tool-workflow/package.json index 0078621f99..125df12935 100644 --- a/packages/workflow/tool-workflow/package.json +++ b/packages/workflow/tool-workflow/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-tool-workflow", "description": "Model-facing workflow tool: run a JavaScript orchestration script over ctx.workflows", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/workflow/tool-workflow" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/workflow/workflow-workerthread/package.json b/packages/workflow/workflow-workerthread/package.json index e229c02e37..d085ba235f 100644 --- a/packages/workflow/workflow-workerthread/package.json +++ b/packages/workflow/workflow-workerthread/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-workflow-workerthread", "description": "worker-thread workflow engine: executes model-written orchestration scripts off the host event loop, bridging agent() calls back to ctx.subagents", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/workflow/workflow-workerthread" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/workflow/workflow/package.json b/packages/workflow/workflow/package.json index 3cc199028a..e2a6eb21d3 100644 --- a/packages/workflow/workflow/package.json +++ b/packages/workflow/workflow/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-workflow", "description": "Workflow capability seam: ctx.workflows service, run vocabulary, and workflow/* events", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/workflow/workflow" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/workspace/workspace/package.json b/packages/workspace/workspace/package.json index b33296c228..9c0c5127d5 100644 --- a/packages/workspace/workspace/package.json +++ b/packages/workspace/workspace/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-workspace", "description": "Workspace entity registry (ctx.workspace): durable workspace records with validated session attachment over the domain data form for the DeepSeek Harness", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/workspace/workspace" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/scripts/check-workspace-constraints.ts b/scripts/check-workspace-constraints.ts index 49ff148922..cdada48fc5 100644 --- a/scripts/check-workspace-constraints.ts +++ b/scripts/check-workspace-constraints.ts @@ -41,6 +41,14 @@ const publicationSourceAllowlist: Readonly> = '@deepseek-ai/node-addon-landlock-run': ['src/main.c'], } const repositoryUrl = 'git+https://github.com/deepseek-harness/deepseek-harness.git' +/** + * Source home the published packages point consumers at. It differs from + * {@link repositoryUrl}, which the Landlock packages keep because npm resolves + * their trusted publishing against the repository that runs the workflow. + */ +const publishedRepositoryUrl = 'git+https://github.com/deepseek-ai/deepseek-harness.git' +/** Directories whose packages this repository publishes: one release member each. */ +const releaseMemberDirectory = /^(?:packages\/[^/]+\/[^/]+|apps\/[^/]+|vendor\/[^/]+)$/ const localArtifactDirs = new Set(['node_modules']) const appPackageFiles: Readonly> = { @@ -232,8 +240,8 @@ function checkWorkspace({ dir, manifest }: WorkspaceManifest): string[] { if (manifest.private === true) { errors.push(`${label}: published Landlock package must not set "private": true`) } - if (manifest.publishConfig?.access !== 'public') { - errors.push(`${label}: published Landlock package must set publishConfig.access to "public"`) + if (manifest.publishConfig?.access !== 'restricted') { + errors.push(`${label}: published Landlock package must set publishConfig.access to "restricted"`) } const expectedDirectory = dir if (manifest.repository?.type !== 'git' @@ -241,6 +249,21 @@ function checkWorkspace({ dir, manifest }: WorkspaceManifest): string[] { || manifest.repository.directory !== expectedDirectory) { errors.push(`${label}: published Landlock package repository must use ${repositoryUrl} with directory ${expectedDirectory} for trusted publishing`) } + } else if (releaseMemberDirectory.test(dir)) { + // Release members state that they are publishable: npm refuses a private + // package, the scope is published privately, and the repository field is + // how a consumer of a private package finds its source. + if (manifest.private === true) { + errors.push(`${label}: release member must not set "private": true`) + } + if (manifest.publishConfig?.access !== 'restricted') { + errors.push(`${label}: release member must set publishConfig.access to "restricted"`) + } + if (manifest.repository?.type !== 'git' + || manifest.repository.url !== publishedRepositoryUrl + || manifest.repository.directory !== dir) { + errors.push(`${label}: release member repository must use ${publishedRepositoryUrl} with directory ${dir}`) + } } else if (manifest.private !== true) { errors.push(`${label}: package.json must set "private": true`) } diff --git a/vendor/cordis/package.json b/vendor/cordis/package.json index ddc49b0655..3428ccbdbc 100644 --- a/vendor/cordis/package.json +++ b/vendor/cordis/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/cordis", "description": "Meta-Framework for Modern JavaScript Applications", "version": "4.0.0-rc.7", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "vendor/cordis" + }, "sideEffects": false, "type": "module", "main": "lib/index.js", diff --git a/vendor/cosmokit/package.json b/vendor/cosmokit/package.json index db14a695e7..de1b3947bc 100644 --- a/vendor/cosmokit/package.json +++ b/vendor/cosmokit/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/cosmokit", "description": "A collection of common utilities", "version": "1.8.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "vendor/cosmokit" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/vendor/group/package.json b/vendor/group/package.json index 9ddb0a132c..c9f242a7d3 100644 --- a/vendor/group/package.json +++ b/vendor/group/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/cordis-plugin-group", "description": "Nested plugin group for cordis", "version": "1.0.0", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "vendor/group" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/vendor/hmr/package.json b/vendor/hmr/package.json index 4ebaf14959..019c027584 100644 --- a/vendor/hmr/package.json +++ b/vendor/hmr/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/cordis-plugin-hmr", "description": "Hot Module Replacement Plugin for Cordis", "version": "1.0.15", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "vendor/hmr" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/vendor/include/package.json b/vendor/include/package.json index 3c56bd065b..7fb6c3f36b 100644 --- a/vendor/include/package.json +++ b/vendor/include/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/cordis-plugin-include", "description": "Include files in cordis configurations", "version": "1.0.4", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "vendor/include" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/vendor/loader/package.json b/vendor/loader/package.json index e535334803..aab8c19bf5 100644 --- a/vendor/loader/package.json +++ b/vendor/loader/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/cordis-plugin-loader", "description": "Plugin loader for cordis", "version": "1.0.0-rc.5", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "vendor/loader" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/vendor/logger-console/package.json b/vendor/logger-console/package.json index b1cc3734bb..aeeb81fb50 100644 --- a/vendor/logger-console/package.json +++ b/vendor/logger-console/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/cordis-plugin-logger-console", "description": "Console logger exporter for cordis", "version": "1.0.0", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "vendor/logger-console" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/shared.d.ts", diff --git a/vendor/schemastery/package.json b/vendor/schemastery/package.json index f2a0c61e5a..e31c6e6251 100644 --- a/vendor/schemastery/package.json +++ b/vendor/schemastery/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/schemastery", "description": "Type driven schema validator", "version": "3.18.0", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "vendor/schemastery" + }, "type": "module", "main": "lib/index.cjs", "module": "lib/index.mjs", diff --git a/vendor/timer/package.json b/vendor/timer/package.json index 9bf741fc51..32f564aa9d 100644 --- a/vendor/timer/package.json +++ b/vendor/timer/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/cordis-plugin-timer", "description": "Timer service for cordis", "version": "1.1.2", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "vendor/timer" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", From 35e2601a280f4b2a25a5a2896205b1d94df8d0aa Mon Sep 17 00:00:00 2001 From: imccyu <276526105+imccyu@users.noreply.github.com> Date: Tue, 11 Aug 2026 00:03:15 +0800 Subject: [PATCH 05/36] docs(release): add the English npm release sequences note and its pairing Also corrects the Chinese text where decisions moved after it was written: the release set is every member of packages/, apps/, and vendor/ rather than a dependency closure, because plugins are mounted by name from cordis.yml and a closure misses runtime-required packages; the Landlock packages publish privately with the rest; and the manifests carry repository metadata alongside the access level. --- ...2026-08-10-npm-release-sequences.i18n.yaml | 6 + .../2026-08-10-npm-release-sequences.md | 185 ++++++++++++++++++ .../2026-08-10-npm-release-sequences.zh.md | 14 +- 3 files changed, 199 insertions(+), 6 deletions(-) create mode 100644 .agents/notes/proposed/process/2026-08-10-npm-release-sequences.i18n.yaml create mode 100644 .agents/notes/proposed/process/2026-08-10-npm-release-sequences.md diff --git a/.agents/notes/proposed/process/2026-08-10-npm-release-sequences.i18n.yaml b/.agents/notes/proposed/process/2026-08-10-npm-release-sequences.i18n.yaml new file mode 100644 index 0000000000..df41fb5816 --- /dev/null +++ b/.agents/notes/proposed/process/2026-08-10-npm-release-sequences.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/proposed/process/2026-08-10-npm-release-sequences.md +2026-08-10-npm-release-sequences.md: 700d922495c539145dd470fbff84e3e211f6ba4e +2026-08-10-npm-release-sequences.zh.md: 59761eacb1c65d4a38e721a319924bf58c5b423e diff --git a/.agents/notes/proposed/process/2026-08-10-npm-release-sequences.md b/.agents/notes/proposed/process/2026-08-10-npm-release-sequences.md new file mode 100644 index 0000000000..700d922495 --- /dev/null +++ b/.agents/notes/proposed/process/2026-08-10-npm-release-sequences.md @@ -0,0 +1,185 @@ +# Agent Note: Private npm publication as three independent sequences + +Status: proposed + +English | [中文](2026-08-10-npm-release-sequences.zh.md) + +## Problem + +This repository holds three unrelated groups of publishable packages and no channel that sends any of them to a registry. + +`packages/*/*` and `apps/*` form the runtime surface of `@deepseek-ai/dsh`; `vendor/*` holds nine rescoped Cordis framework packages, each carrying its upstream version; `native/landlock-run/packages/*` holds Linux platform packages that already have `landlock-run-release.yml`. The three differ in version baseline, change rate, and build requirements: dsh moves with the product, vendor moves only when upstream is re-synced or a local modification changes, and native needs a musl toolchain and one build per architecture. Forcing them through one pipeline means every product release republishes the framework and the native binaries. + +Two hard blockers sit in the current state. All 217 workspace manifests set `private: true`, which npm refuses to publish. The subtler one is 933 hard-written `peerDependencies: "^0.0.1"` entries between sibling dsh packages: `pnpm pack` substitutes the `workspace:` protocol but leaves semver ranges alone, and `^0.0.1` means `>=0.0.1 <0.0.2` — it excludes `0.0.2`, and semver excludes prereleases from a range without a prerelease of its own, so it excludes `0.0.1-rc.1` too. Those 933 entries have never failed only because the version has never left `0.0.1`. + +The existing `scripts/publish-npm-baseline.ts` is a local publication script: it packs and publishes in one process, needs a human to authenticate and retry on their own machine, and excludes vendor from its release set. It cannot be the basis for CI publication, but its tarball payload validation and installed-artifact probes are verified parts. + +## Proposal + +### Three independent sequences + +`packages/`, `vendor/`, and `native/` each get one bump sequence and one publication, sharing no version, no trigger, and no waiting. Releasing dsh does not republish vendor; releasing vendor does not republish native. + +| Sequence | Members | Version baseline | Tag | Workflow | +|---|---|---|---|---| +| dsh | `packages/*/*` + `apps/*` (`@deepseek-ai/dsh` and `@deepseek-ai/dsh-frontend`) | one version for the whole family, `0.0.x` | `dsh-v` | `release.yml` (new) | +| vendored framework | the nine `vendor/*` packages | each package on its own version line | `vendor--v` (one per package) | `release-vendor.yml` (new) | +| native | `native/landlock-run/packages/*` | its own `0.0.x` | `landlock-run-v` | `landlock-run-release.yml` (unchanged) | + +All three publish privately to the `@deepseek-ai` scope on npmjs.com (`npm publish --access restricted`). + +### Versions land in the repository from a local command; CI only checks and uploads + +Each sequence has one `bump and commit` command: derive the target version, write it into the relevant manifests, run `pnpm install --lockfile-only`, self-check immediately, then `git add` the manifests and the lockfile and commit. The published version is therefore readable from the repository, and "which version went out" is never a question. A human creates the tag after the commit merges to master; CI never writes to the repository and needs no write permission. + +The dsh sequence shares one version across the family and accepts `major | minor | patch | x.y.z`. A prerelease version such as `0.0.1-rc.1` drives pack, the installed-artifact probes, and one real private publication end to end first; numbered versions like `0.0.1` and `0.0.2` follow once that passes. The dist-tag decision is the one this repository already makes in `landlock-run-release.yml`: a version with a prerelease segment publishes under `--tag next`, anything else takes `latest`. + +### vendor: publish what changed, and let tags be the ledger + +The vendored packages are decoupled from upstream by their scope but keep their own version lines. The published version is the upstream version with its prerelease segment dropped and its patch incremented: + +| Package | Upstream version | First published version | +|---|---|---| +| `@deepseek-ai/cordis` | 4.0.0-rc.7 | 4.0.1 | +| `@deepseek-ai/cordis-plugin-loader` | 1.0.0-rc.5 | 1.0.1 | +| `@deepseek-ai/cosmokit` | 1.8.1 | 1.8.2 | +| `@deepseek-ai/schemastery` | 3.18.0 | 3.18.1 | +| `@deepseek-ai/cordis-plugin-hmr` | 1.0.15 | 1.0.16 | +| `@deepseek-ai/cordis-plugin-include` | 1.0.4 | 1.0.5 | +| `@deepseek-ai/cordis-plugin-timer` | 1.1.2 | 1.1.3 | +| `@deepseek-ai/cordis-plugin-group` | 1.0.0 | 1.0.1 | +| `@deepseek-ai/cordis-plugin-logger-console` | 1.0.0 | 1.0.1 | + +Only changed packages publish, and the change judgement adds no state file: **each package has its own tag, and that tag records the commit it last published from**. For each package, bump reads the newest `vendor--v*` tag and runs `git diff ..HEAD -- vendor/`; a difference means patch+1, no difference means skip, and a missing tag means the first publication from the table above. The diff considers only paths that reach the tarball (the `files` rules in `scripts/publication-payload.ts`), so editing a comment inside a vendored package does not trigger a release. + +A tag is a commit pointer, not proof of publication — a tag created for a publication that then failed must be recognizable. So bump also asks the registry whether the version that tag names exists, and fails for a human to resolve when it does not, rather than guessing. Querying a private package needs authentication; the check is skipped on a machine that is not logged in and enforced in CI. + +The dependency ranges *inside* the nine vendored packages need no rewrite: `^1.8.1` admits `1.8.2` and `^1.0.0-rc.5` admits `1.0.1`, so patch+1 always lands inside the range. + +### Publication runs only on GitHub, and the registry decides what goes out + +Publication runs only from GitHub Actions; there is no local publication path. That makes the registry check a mandatory CI step instead of something with a bypass for an unauthenticated machine. + +Publish reads no tag and no manifest of "what this release includes". For each member it compares the manifest version against the registry, in three states: + +| State | Action | +|---|---| +| the registry does not have that version | publish | +| the registry has it, and the tarball's sha512 equals the recorded `dist.integrity` | skip: this is a re-run over one artifact | +| the registry has it, and the integrity differs | fail, reporting content changed without a version bump | + +The third state is the point of the rule: it catches code that changed without a version bump. The first two provide idempotence — re-running publish over one artifact republishes nothing and needs no manual selection of packages. + +The same rule resolves the tension between one vendor release carrying several tags and a workflow that can only run from one ref: the workflow never infers which packages to publish from the tag it ran from. The dsh sequence behaves identically with one version: the difference is either the whole set or nothing. + +The third state depends on a reproducible build — packing the same commit twice must produce the same bytes. That must be measured, not assumed: if `pnpm run build` embeds absolute paths or timestamps, integrity drifts while content is unchanged and the third state reports a false failure. Before this lands, pack the same commit twice in CI and compare integrity; if it is not reproducible, compare per-file content hashes inside the tarball instead and exclude the fields that drift. + +### Rewrite workspace-internal references to `workspace:^`, once + +Every reference to a workspace member becomes `workspace:^`, so `pnpm pack` substitutes a range that matches the target version: + +| Surface | Count | Effect | +|---|---|---| +| sibling dsh `peerDependencies` | 933 | `0.0.2` and `0.0.1-rc.1` both get a matching range | +| dep / peer / devDep pointing at vendor | 105 + 221 + 218 | no dsh-side rewrite after a vendor patch+1, and no range that goes stale as vendor increments | + +`scripts/check-workspace-constraints.ts` currently asserts that the vendor peer and dev ranges are equal; both become `workspace:^`, so the assertion still holds but its wording changes with it. + +This is what makes "no dependency rewriting at publication time" possible: publication does one thing, which is packing bytes. + +### Release family objects + +The entity in this domain is a **release family**: a set of packages sharing one version baseline and tag naming that publishes as a unit. Adding a family means adding a family description and one workflow lane, not changing the core. + +| Object | Responsibility | +|---|---| +| `ReleaseFamily` | a family's identity: member discovery, version policy, tag naming, publish target. A new release family lands here | +| `ReleaseMember` | one publishable package: directory, manifest, family, position in publish order | +| `VersionPolicy` | where the version comes from. `SharedSemver` (dsh: one version for the family) and `PerPackageChanged` (vendor: change judged by tag, prerelease dropped, patch incremented) | +| `ReleaseSet` | a family's members in topological order over `dependencies`, ties broken by package name for determinism | +| `PackedBundle` | the tarballs plus `publish-order.txt` and its metadata: the only handoff between pack and publish | +| `PublishTarget` | registry, access, dist-tag, credential source. The dist-tag derives from the version's shape | +| `VersionInvariant` | the family's versions agree; publication runs from the family's tag; the tag version equals the package version; the target version is absent from the registry | +| `PayloadInvariant` | tarball content validation, reusing `scripts/publication-payload.ts` | +| `InstalledProbe` | a throwaway consumer outside the repository installs from the tarballs and drives the installed entry with plain Node: `dsh --version`, `dsh --dump-default-config`, and one TUI startup to ready and exit. Moved over from `scripts/publish-npm-baseline.ts` | + +### Workflow shape: pack everything at once, then publish as one set + +The shape comes from the reference flow (`release.yml` and `scripts/pack-release.mjs` in node-addon-require-builtin): the `pack` job walks the whole release set once, running `pnpm --dir pack --pack-destination ` per member, writes `publish-order.txt`, and uploads that directory as **one** artifact; the `publish` job downloads that artifact and runs `npm publish` per entry in `publish-order.txt`. The release set is one unit — half the packages can never reach the registry while the other half is still building. + +The `pack` job carries no credentials: install, verify, build, pack, installed-artifact verification, upload-artifact. The `publish` job sits behind the `npm-publish` environment for human approval, runs `setup-node` and `download-artifact` only, and **neither checks out nor builds** — it uploads the bytes pack produced. Checkout uses `fetch-depth: 0`, because the vendor change judgement reads history and tags. + +The environment is the only brake in the flow: pack has no credentials and can be rehearsed freely, and only publish stops for approval. GitHub needs an `NPM_TOKEN` secret (an automation token with publish rights on the scope) and an `npm-publish` environment (required reviewers, allowed tags limited to `dsh-v*`, `vendor-*`, and `landlock-run-v*`). + +### Pull requests run as far as pack + +The reference flow only has `workflow_dispatch`, so it verifies nothing on a pull request. Here `pull_request` runs the full pack: install, verify, build, pack per member, upload the tarball artifact. What it proves is that this release set still packs completely; it uses no credentials, touches no registry, and runs for pull requests from forks. The artifacts' own correctness is covered by existing tests and is not repeated at this layer. + +The publication path is exercised from master: `push: master` runs the same pack rehearsal as a post-merge regression, and `workflow_dispatch` with `publish: true` performs a real publication from a tag. + +### Repository changes + +| Item | Content | +|---|---| +| release-set manifests | drop `private: true`; add `publishConfig.access: restricted` and `repository` (`git+https://github.com/deepseek-ai/deepseek-harness.git` plus each package's `directory`) | +| release-set boundary | every member of `packages/*/*`, `apps/*`, and `vendor/*`; no smaller selection | +| dependency protocol | workspace-internal references become `workspace:^`, with `check-workspace-constraints.ts` updated | +| root `AGENTS.md` | it states that vendored packages are rescoped and `private: true`; vendor now publishes, so that convention changes | +| `vendor/README.md` | its manifest table records the upstream version, kept distinct from the version we publish | +| the three native packages | `publishConfig.access` moves from `public` to `restricted`; they have never been published, so no anonymous install path exists to preserve | + +### Relationship to the existing proposal + +This Agent Note replaces the version scheme and the release-set boundary in [artifact-first npm baseline publication](2026-08-04-artifact-first-npm-baseline-publication.md): its `--` prerelease versions and `dev-` dist-tag are not adopted, and vendor is no longer excluded from the release set. What both agree on stays: pack and publish are separate, publish consumes only verified tarballs, and the payload and installed-artifact probes are release gates. + +## Alternatives considered + +**A `--` version.** Planned for continuous dev publication. It conflicts with keeping the published version in the repository: the version embeds a commit SHA, and writing the version back produces a new commit, so the SHA can only name the parent commit that was published and the link needs a convention to explain it. With numbered versions, a prerelease such as `0.0.1-rc.1` already covers "verify first, then release". + +**A `vendor/published.json` ledger recording each package's published version and commit.** This preceded the tag design. It adds a state file that must not drift from the registry. A per-package tag gives the same commit pointer, and the tag has to exist anyway, so it introduces no second copy of the state. + +**Event-level tags (`vendor-r1`, `vendor-r2`).** Prepared for one release event carrying several package versions. Once the registry decides what publishes, the workflow no longer infers the set from the tag, so per-package tags suffice — and each one names its own package's real version. + +**Putting the nine vendored packages on one `4.0.x` line.** It removes change detection, but cosmokit would jump from `1.8.1` to `4.0.1` and lose its upstream lineage; the upstream ranges inside the nine (`^1.8.1` and friends) would stop matching immediately, forcing a rewrite of the vendored manifests. + +**Incrementing every vendored package on every vendor release, with no change detection.** The least machinery, at the cost of new version numbers for packages whose content is byte-identical to the previous release. Tags reduce change detection to reading one tag and running one diff, which is not worth trading for inflated version numbers. + +**Deciding "already published" from the version alone, without comparing content.** The reference flow queries no registry at all: publish uploads each tarball and npm rejects a duplicate version. Skipping on the version alone misses code that changed without a bump, which is the only failure that quietly leaves stale bytes on the registry. The cost is a registry query and a dependency on reproducible builds. + +**Verifying only the packed install, with no local registry.** This is what the reference flow does: unpack the tarballs into a tree and drive it with plain Node. It bypasses version-range resolution, so in principle it cannot prove that 200-odd interdependent packages install from a registry. Running a local registry in CI to cover that layer was proposed and rejected: artifact correctness is already covered by existing tests, the publication path is exercised by the master rehearsal, and a pull request only needs to prove the release set packs. + +**Selecting a subset by entry closure.** Crawling `dependencies` from `@deepseek-ai/dsh` and `@deepseek-ai/dsh-frontend` yields 156 packages, 61 fewer than the whole set. But this repository's plugins are mounted by name from `cordis.yml` rather than imported: `vendor/cordis-plugin-group` and `vendor/cordis-plugin-logger-console` fall outside the dependency closure while being required at runtime. Selecting by code dependency fails as "the consumer installs it and it will not start", and it would need a standing proof that no mounted package was missed. The release set is therefore all of `packages/*/*`, `apps/*`, and `vendor/*`; under a private scope the extra packages are invisible outside the organization. `python/`, the root `examples/`, `docs/`, and `website/` are not members. + +**Extending `scripts/publish-npm-baseline.ts`.** It is a local publication script that packs and publishes in one process, the opposite of separating credential-free packing from protected publication. Its verified parts — payload validation and installed-artifact probes — are reused so `pnpm run duplication` does not report clones. + +**One workflow with a `family` input.** Two version models in one file forks the concurrency group, the tag prefix, and the rehearsal triggers into conditional expressions. One file per family is both shorter and easier to read. + +**Rewriting dependency ranges at publication time.** Compared with rewriting them to `workspace:^` once, the rewrite runs only in CI, a local `pnpm install` cannot show whether it is correct, and it repeats on every release. + +**Running bump in CI and pushing the version back.** It needs repository write permission for the workflow, and a version commit on the release branch races human commits. The reference flow leaves bump and commit to local commands and lets CI check and upload. + +## Acceptance criteria + +1. The three sequences release independently: releasing dsh modifies no vendor or native manifest, and the converse holds. +2. `pnpm release:dsh ` performs bump and commit in one command, and the resulting commit carries the family's manifests and the lockfile and self-checks immediately. +3. `pnpm release:vendor` increments the patch only for packages whose tarball content changed since their `vendor--v*` tag, and leaves the manifests of unchanged packages alone. +4. `pull_request` runs the full pack and produces the tarball artifact, with no credentials and no access to a real registry, including for pull requests from forks. +5. `push: master` runs the same pack rehearsal; a real publication can only come from `workflow_dispatch` with `publish: true` from that family's tag. +6. Re-running publish over one artifact republishes no existing version, and when a version exists whose tarball integrity differs, publish fails and names the package. +7. A throwaway consumer outside the repository installs `@deepseek-ai/dsh@0.0.1-rc.1` and drives `--version`, `--dump-default-config`, and one TUI startup with plain Node. +8. Every workspace-internal reference is `workspace:^`, the packed tarballs carry no `workspace:` remnant, and no range points at a version that does not exist. +9. No release-set member sets `private: true`, and each one sets `publishConfig.access: restricted`. + +## Risks + +**Tags drifting from the registry.** A tag created for a publication that then failed makes the next bump treat the package as published. Bump asks the registry whether the version the tag names exists and fails when it does not; on a machine that is not logged in to the private registry that check is skipped, and only the same check in CI catches it. + +**The change judgement depends on visible tags.** A shallow clone, or a checkout without tags, breaks the vendor judgement and degrades it to "publish everything for the first time". `fetch-depth: 0` is a precondition of the judgement, not an optimization. + +**`workspace:^` touches a large surface.** It rewrites 1477 dependency declarations at once. It does not change local resolution — pnpm already resolves from the workspace — but it changes the ranges that go out, and the workspace constraint gate changes with it. + +**The visibility cost of private packages.** After `--access restricted`, every consumer — CI, sandbox e2e, and outside users — needs scope credentials to install. The three native packages move to `restricted` as well; they have never been published, so no existing anonymous install path is cut off. + +**The `repository` organization differs from the one running the workflow.** The release set names `github.com/deepseek-ai/deepseek-harness` while the workflow runs in `deepseek-harness/deepseek-harness`. Token-based publication is unaffected; npm provenance (OIDC) requires the two to agree, so adopting it means either changing `repository` or publishing from the public repository. + +**The first publication is one large step.** Nine vendored packages and the whole dsh set publish at once, so any payload defect surfaces in a single release. Driving the complete path with `0.0.1-rc.1` first is the only mitigation, which is why numbered versions wait for that to pass. diff --git a/.agents/notes/proposed/process/2026-08-10-npm-release-sequences.zh.md b/.agents/notes/proposed/process/2026-08-10-npm-release-sequences.zh.md index 836b5e863b..59761eacb1 100644 --- a/.agents/notes/proposed/process/2026-08-10-npm-release-sequences.zh.md +++ b/.agents/notes/proposed/process/2026-08-10-npm-release-sequences.zh.md @@ -124,16 +124,16 @@ publish 不读 tag、不读任何清单,对发布集里每个包比较 manifes | 项 | 内容 | |---|---| -| 发布集 manifest | 去掉 `private: true`,补 `publishConfig`(`access: restricted`、`registry`) | -| 发布集边界 | 一份显式的族与成员清单,脚本据此发现成员并校验闭包内的包都在清单里,不猜 | +| 发布集 manifest | 去掉 `private: true`,补 `publishConfig.access: restricted` 与 `repository`(`git+https://github.com/deepseek-ai/deepseek-harness.git` + 各自 `directory`) | +| 发布集边界 | `packages/*/*` + `apps/*` + `vendor/*` 全部成员,不另挑子集 | | 依赖协议 | workspace 内部引用统一 `workspace:^`,并更新 `check-workspace-constraints.ts` | | 根 `AGENTS.md` | 现在写着 vendored 包是 rescope 过且 `private: true`,vendor 要发布,这条约定要改 | | `vendor/README.md` | manifest 表补记上游版本,与我们发布的版本区分开 | -| native 三包 | `publishConfig.access` 从 `public` 改 `restricted` | +| native 三包 | `publishConfig.access` 从 `public` 改 `restricted`;它们尚未发布过,所以没有匿名安装路径要保 | ### 与既有提案的关系 -本 Note 取代 [以产物为先的 NPM 基线发布](2026-08-04-artifact-first-npm-baseline-publication.zh.md) 中的版本方案与发布集边界两部分:那篇的 `-<时间戳>-<短 SHA>` 预发布版本与 `dev-` dist-tag 不再采用,vendor 也不再排除在发布集之外。两篇一致的部分保留:pack 与 publish 分离、publish 只消费已验证的 tarball、payload 与安装后探针作为发布门。 +本 Note 取代 [以产物为先的 NPM 基线发布](2026-08-04-artifact-first-npm-baseline-publication.md) 中的版本方案与发布集边界两部分:那篇的 `-<时间戳>-<短 SHA>` 预发布版本与 `dev-` dist-tag 不再采用,vendor 也不再排除在发布集之外。两篇一致的部分保留:pack 与 publish 分离、publish 只消费已验证的 tarball、payload 与安装后探针作为发布门。 ## 考虑过的替代方案 @@ -153,7 +153,7 @@ publish 不读 tag、不读任何清单,对发布集里每个包比较 manifes **以 `scripts/publish-npm-baseline.ts` 为基础扩展。** 它是本机发布脚本,把 pack 与 publish 放在同一进程,与「无凭据 pack、受保护 publish」的分离相反。它验证过的零件(payload 校验、已安装产物探针)搬运复用,避免 `pnpm run duplication` 判重复。 -**发布全部 217 个 workspace 包。** 发布集定为入口闭包。`support/`、`examples/` 这类包进 registry 只扩大攻击面与维护面,没有消费方。 +**按入口闭包挑一部分包发。** 从 `@deepseek-ai/dsh` 与 `@deepseek-ai/dsh-frontend` 沿 `dependencies` 爬得到 156 个包,比全量少 61 个。但本仓的插件是 cordis.yml 按名字挂载的,不是被 import 的:`vendor/cordis-plugin-group` 与 `vendor/cordis-plugin-logger-console` 就落在依赖闭包之外,而它们是运行时必需。照代码依赖挑,漏掉的表现是消费方装完起不来,且要额外证明「没漏任何挂载项」。发布集因此取 `packages/*/*` + `apps/*` + `vendor/*` 全部;私有 scope 下多几个包不对外可见。`python/`、根 `examples/`、`docs/` 与 `website/` 不是发布集成员。 **一个 workflow 用 `family` 输入选择序列。** 两套版本模型塞进一个文件会让 concurrency group、tag 前缀、排练触发条件全部分叉成条件表达式。一族一个文件更短也更好读。 @@ -181,6 +181,8 @@ publish 不读 tag、不读任何清单,对发布集里每个包比较 manifes **`workspace:^` 改动面大。** 一次触及 1477 处依赖声明。它不改变本机解析行为(pnpm 本来就从 workspace 解析),但会改变发布出去的范围写法,且要同步更新 workspace 约束门。 -**私有包的可见性代价。** `--access restricted` 之后,任何消费方(含 CI、沙箱 e2e、外部使用者)都必须持有 scope 凭据才能安装。native 三包从 public 转 restricted 会切断现有匿名安装路径。 +**私有包的可见性代价。** `--access restricted` 之后,任何消费方(含 CI、沙箱 e2e、外部使用者)都必须持有 scope 凭据才能安装。native 三包一并转 `restricted`;它们尚未发布过,因此没有既有的匿名安装路径被切断。 + +**`repository` 指向的组织与运行 workflow 的组织不一致。** 发布集写的是 `github.com/deepseek-ai/deepseek-harness`,而 workflow 跑在 `deepseek-harness/deepseek-harness`。用 token 发布不受影响;一旦改用 npm provenance(OIDC),npm 会要求二者一致,届时要么改 `repository`,要么从公开仓库发布。 **首发一次性放大。** vendor 首发九包、dsh 首发全闭包,任何 payload 缺陷都会在同一次发布里暴露。用 `0.0.1-rc.1` 先跑一遍完整链路是唯一的缓解手段,正式版本号留给验证通过之后。 From d4128ae57f8c5181500aeaa7d81e097310980e4a Mon Sep 17 00:00:00 2001 From: imccyu <276526105+imccyu@users.noreply.github.com> Date: Tue, 11 Aug 2026 00:03:15 +0800 Subject: [PATCH 06/36] chore(release): satisfy knip for the release scripts The release scripts spawn tar to read a packed tarball, and resolving a family by id is the only entry point into the family list. --- knip.json | 1 + scripts/release/families.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/knip.json b/knip.json index 2f755dbb5f..44f45da1ad 100644 --- a/knip.json +++ b/knip.json @@ -9,6 +9,7 @@ "musl-gcc", "python3", "sandbox-exec", + "tar", "taskkill", "where.exe" ], diff --git a/scripts/release/families.ts b/scripts/release/families.ts index e989e54525..b02c21cb1e 100644 --- a/scripts/release/families.ts +++ b/scripts/release/families.ts @@ -253,7 +253,7 @@ class VendorFamily extends ReleaseFamily { } /** Every release family this module owns, in workflow order. */ -export function releaseFamilies(): readonly ReleaseFamily[] { +function releaseFamilies(): readonly ReleaseFamily[] { return [new DshFamily(), new VendorFamily()] } From 2c85c484d3b205043e73620dc9e16c0adfb38813 Mon Sep 17 00:00:00 2001 From: imccyu <276526105+imccyu@users.noreply.github.com> Date: Tue, 11 Aug 2026 00:16:45 +0800 Subject: [PATCH 07/36] build(release): reference workspace members through the workspace protocol 1504 hand-written ranges pointing at workspace members become workspace:^, so pnpm pack substitutes each member's real version at publication: sibling peerDependencies follow the family version instead of being pinned at ^0.0.1, and a reference to a vendored package follows that package's own line. Without this, publishing 0.0.2 ships peer ranges naming a version that does not exist, and 0.0.1-rc.1 does not satisfy ^0.0.1 either. It also retires ranges that had gone stale against the workspace: ^4.0.0-rc.6 for a 4.0.0-rc.7 checkout, ^3.17.0 for schemastery 3.18.0. workspace:* stays where an exact published version is the point, which is how the Landlock entry pins its platform packages. A workspace constraint now requires the protocol, so a new package cannot reintroduce a hand-written range. The same constraint caught packages/boot/cmdline arriving on master without the publishable trio, which this change completes. --- apps/cli/package.json | 2 +- packages/acp/acp/package.json | 14 +- packages/api/gateway/package.json | 10 +- packages/api/remotes/package.json | 16 +- .../attachment/attachment-local/package.json | 12 +- packages/attachment/attachment/package.json | 8 +- packages/bash/bash-env/package.json | 16 +- packages/bash/bash-local/package.json | 14 +- packages/bash/bash-sandbox/package.json | 14 +- packages/bash/bash/package.json | 10 +- packages/bash/pwsh-local/package.json | 14 +- packages/bash/pwsh-sandbox/package.json | 14 +- packages/bash/tool-bash/package.json | 28 +- packages/bash/tool-pwsh/package.json | 28 +- packages/boot/app-boot/package.json | 20 +- packages/boot/cmdline/package.json | 17 +- packages/bundle/base/package.json | 6 +- packages/bundle/headless/package.json | 18 +- packages/bundle/web-app/package.json | 14 +- packages/client/connection/package.json | 10 +- packages/client/hmr/package.json | 14 +- packages/client/locale/package.json | 16 +- packages/client/modules/package.json | 6 +- packages/client/runtime/package.json | 12 +- packages/client/schema-form/package.json | 8 +- packages/client/test-runtime/package.json | 14 +- packages/client/ui-agent-preset/package.json | 22 +- packages/client/ui-command/package.json | 20 +- packages/client/ui-conversation/package.json | 36 +- packages/client/ui-deliverables/package.json | 14 +- packages/client/ui-goal/package.json | 20 +- packages/client/ui-layout/package.json | 12 +- packages/client/ui-model/package.json | 22 +- packages/client/ui-models/package.json | 18 +- packages/client/ui-permission/package.json | 24 +- packages/client/ui-plan/package.json | 20 +- packages/client/ui-primitives/package.json | 6 +- packages/client/ui-question/package.json | 8 +- .../client/ui-settings-general/package.json | 22 +- packages/client/ui-settings/package.json | 12 +- packages/client/ui-sidebar/package.json | 14 +- packages/client/ui-skill/package.json | 20 +- packages/client/ui-slash/package.json | 14 +- packages/client/ui-slots/package.json | 6 +- packages/client/ui-subagent/package.json | 22 +- packages/client/ui-theme/package.json | 18 +- packages/client/ui-tool/package.json | 16 +- packages/client/ui-trajectory/package.json | 10 +- packages/client/ui-workspace/package.json | 14 +- packages/client/web-react/package.json | 6 +- packages/client/web/package.json | 8 +- .../code-runtime-worker/package.json | 14 +- .../code-runtime/code-runtime/package.json | 6 +- packages/compact/command-compact/package.json | 10 +- packages/compact/compact-basic/package.json | 22 +- .../compact-tool-result-prune/package.json | 16 +- packages/compact/compact/package.json | 14 +- .../context/session-reference/package.json | 20 +- packages/context/time-context/package.json | 12 +- packages/context/tmux-context/package.json | 14 +- .../context/workspace-context/package.json | 20 +- .../core/agent-default-model/package.json | 14 +- packages/core/agent-loop/package.json | 22 +- packages/core/agent-tool-mode/package.json | 10 +- packages/core/agent/package.json | 16 +- packages/core/scope/package.json | 6 +- packages/core/session/package.json | 14 +- packages/core/system-prompt/package.json | 12 +- packages/core/tools/package.json | 22 +- .../credentials-local/package.json | 16 +- packages/credentials/credentials/package.json | 8 +- packages/e2b/e2b/package.json | 8 +- packages/e2b/fs-e2b/package.json | 10 +- packages/e2b/subprocess-e2b/package.json | 14 +- packages/examples/acp-demo/package.json | 32 +- .../examples/agent-spine-demo/package.json | 52 +- packages/examples/jsonrpc-demo/package.json | 6 +- .../feedback/command-feedback/package.json | 12 +- packages/fs/fs-local/package.json | 10 +- packages/fs/fs-policy/package.json | 8 +- packages/fs/fs-sandbox/package.json | 14 +- packages/fs/fs/package.json | 12 +- packages/fs/tool-fs-search/package.json | 24 +- packages/fs/tool-fs/package.json | 24 +- .../fs/tool-str-replace-editor/package.json | 16 +- packages/goal/command-goal/package.json | 10 +- packages/goal/goal-session/package.json | 14 +- packages/goal/goal/package.json | 22 +- packages/goal/tool-goal/package.json | 20 +- packages/guard/repeat-tool-guard/package.json | 12 +- packages/guard/timeout-policy/package.json | 12 +- packages/hooks/hook-protocol/package.json | 10 +- packages/hooks/hooks-claude/package.json | 22 +- packages/hooks/hooks-codex/package.json | 20 +- packages/host/apiproxy/package.json | 10 +- .../host/directory-picker-auto/package.json | 14 +- .../host/directory-picker-browse/package.json | 18 +- .../host/directory-picker-native/package.json | 12 +- packages/host/directory-picker/package.json | 6 +- packages/host/frontend-static/package.json | 10 +- packages/host/webserver/package.json | 8 +- packages/interaction/commands/package.json | 14 +- packages/interaction/permission/package.json | 24 +- .../interaction/tool-ask-user/package.json | 12 +- .../interaction/user-approval/package.json | 20 +- .../interaction/user-interaction/package.json | 10 +- packages/llm/llm-deepseek/package.json | 18 +- packages/llm/llm-pi-ai/package.json | 20 +- packages/llm/llm-retry/package.json | 18 +- packages/llm/llm/package.json | 14 +- packages/llm/token-meter/package.json | 16 +- packages/lsp/lsp-local/package.json | 20 +- packages/lsp/lsp/package.json | 10 +- packages/lsp/tool-lsp/package.json | 18 +- packages/mcp/mcp-client/package.json | 14 +- packages/plan/plan-mode/package.json | 22 +- packages/preset/agent-presets/package.json | 22 +- packages/preset/persona/package.json | 10 +- packages/pty/pty-local/package.json | 20 +- packages/pty/pty/package.json | 10 +- .../pty/tool-bash-persistent/package.json | 16 +- packages/pty/tool-pty/package.json | 22 +- packages/sandbox/sandbox-local/package.json | 14 +- packages/sandbox/sandbox-policy/package.json | 16 +- .../sandbox/sandbox-windows-acl/package.json | 6 +- packages/sandbox/sandbox/package.json | 10 +- packages/scaffold/client/package.json | 12 +- packages/scaffold/create-sdk/package.json | 6 +- packages/scaffold/helper/package.json | 10 +- packages/scaffold/protocol/package.json | 12 +- packages/scaffold/scripts/package.json | 6 +- packages/scaffold/server/package.json | 22 +- packages/scaffold/telemetry/package.json | 10 +- .../tool-cordis/package.json | 14 +- .../session-query-sqlite/package.json | 14 +- .../session-query/session-query/package.json | 16 +- .../tool-session-query/package.json | 20 +- .../session-checkpoint-policy/package.json | 16 +- .../session-persistence-jsonl/package.json | 12 +- .../session-persistence-sqlite/package.json | 12 +- .../session/session-persistence/package.json | 12 +- .../session-projection-cache/package.json | 16 +- .../session/session-projection/package.json | 8 +- .../session-telemetry-otel/package.json | 18 +- .../session/session-telemetry/package.json | 10 +- .../package.json | 16 +- .../package.json | 16 +- .../session/session-title-llm/package.json | 16 +- packages/session/session-title/package.json | 16 +- packages/session/user-id/package.json | 10 +- packages/settings/settings-local/package.json | 14 +- packages/settings/settings/package.json | 12 +- packages/skill/skill-badge/package.json | 8 +- packages/skill/skill-local/package.json | 14 +- packages/skill/skill/package.json | 12 +- packages/skill/tool-skill/package.json | 16 +- packages/spill/spill-local/package.json | 10 +- packages/spill/spill-policy/package.json | 18 +- packages/spill/spill/package.json | 12 +- packages/storage/storage-domain/package.json | 10 +- packages/storage/storage-json/package.json | 10 +- packages/storage/storage-sqlite/package.json | 10 +- packages/storage/storage/package.json | 6 +- packages/subagent/subagent-acp/package.json | 22 +- .../subagent-claude-code/package.json | 18 +- packages/subagent/subagent-codex/package.json | 22 +- .../subagent/subagent-dsh-sdk/package.json | 22 +- packages/subagent/subagent-fork/package.json | 18 +- .../subagent/subagent-inprocess/package.json | 22 +- packages/subagent/subagent-spawn/package.json | 14 +- packages/subagent/subagent/package.json | 34 +- .../tool-subagent-control/package.json | 14 +- .../tool-subagent-report/package.json | 14 +- packages/subagent/tool-subagent/package.json | 20 +- .../subprocess/subprocess-local/package.json | 10 +- packages/subprocess/subprocess/package.json | 6 +- packages/support/acp-snapshot/package.json | 8 +- .../support/agent-loop-testkit/package.json | 16 +- packages/support/invariants/package.json | 6 +- packages/support/llm-mock-server/package.json | 6 +- packages/support/llm-replay/package.json | 12 +- packages/support/loader-smoke/package.json | 12 +- packages/tasks/tasks-local/package.json | 14 +- packages/tasks/tasks/package.json | 12 +- packages/tasks/tool-tasks/package.json | 20 +- packages/todo/tool-todo/package.json | 16 +- packages/typert/generator/package.json | 6 +- packages/typert/loader/package.json | 12 +- packages/typert/registry/package.json | 6 +- packages/typert/type-meta/package.json | 6 +- packages/util/atomic-write/package.json | 6 +- packages/util/brand/package.json | 6 +- packages/util/environment/package.json | 6 +- packages/util/native-command/package.json | 6 +- packages/util/paths/package.json | 6 +- packages/util/retention/package.json | 6 +- packages/util/timeout/package.json | 6 +- packages/web/tool-web/package.json | 16 +- packages/web/web-fetch-local/package.json | 12 +- packages/web/web-search-deepseek/package.json | 18 +- packages/web/web-search-exa/package.json | 12 +- .../web/web-search-perplexity/package.json | 12 +- packages/web/web/package.json | 10 +- packages/workflow/tool-ralph/package.json | 20 +- packages/workflow/tool-workflow/package.json | 18 +- .../workflow-workerthread/package.json | 22 +- packages/workflow/workflow/package.json | 14 +- packages/workspace/workspace/package.json | 16 +- pnpm-lock.yaml | 460 +++++++++--------- scripts/check-workspace-constraints.ts | 33 +- vendor/cordis/package.json | 6 +- vendor/group/package.json | 4 +- vendor/hmr/package.json | 8 +- vendor/include/package.json | 6 +- vendor/loader/package.json | 4 +- vendor/logger-console/package.json | 6 +- vendor/schemastery/package.json | 2 +- vendor/timer/package.json | 4 +- 218 files changed, 1774 insertions(+), 1736 deletions(-) diff --git a/apps/cli/package.json b/apps/cli/package.json index 3155032205..71f64a0f41 100644 --- a/apps/cli/package.json +++ b/apps/cli/package.json @@ -72,7 +72,7 @@ "@deepseek-ai/dsh-workflow-workerthread": "workspace:^", "@deepseek-ai/dsh-workspace-context": "workspace:^", "commander": "^15.0.0", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/cordis": "workspace:^", "js-yaml": "^4.2.0", "node-addon-require-builtin": "^0.1.4" }, diff --git a/packages/acp/acp/package.json b/packages/acp/acp/package.json index c5564b0b2f..5293a94e5d 100644 --- a/packages/acp/acp/package.json +++ b/packages/acp/acp/package.json @@ -33,14 +33,14 @@ "license": "BSD-3-Clause", "dependencies": { "@agentclientprotocol/sdk": "0.25.1", - "@deepseek-ai/schemastery": "^3.17.0" + "@deepseek-ai/schemastery": "workspace:^" }, "peerDependencies": { - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-user-approval": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-user-approval": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -51,6 +51,6 @@ "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", "@deepseek-ai/dsh-user-approval": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/api/gateway/package.json b/packages/api/gateway/package.json index 10a315302a..bd90451fdc 100644 --- a/packages/api/gateway/package.json +++ b/packages/api/gateway/package.json @@ -59,17 +59,17 @@ "@deepseek-ai/dsh-type-meta": "workspace:^" }, "peerDependencies": { - "@deepseek-ai/dsh-client-connection": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-typert-registry": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-client-connection": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-typert-registry": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-client-connection": "workspace:^", "@deepseek-ai/dsh-host-webserver": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-typert-registry": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/cordis": "workspace:^", "zod": "^4.4.3" } } diff --git a/packages/api/remotes/package.json b/packages/api/remotes/package.json index 8a31f138e3..0a96fb2239 100644 --- a/packages/api/remotes/package.json +++ b/packages/api/remotes/package.json @@ -53,13 +53,13 @@ "@deepseek-ai/dsh-type-meta": "workspace:^" }, "peerDependencies": { - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-goal": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-session-persistence": "^0.0.1", - "@deepseek-ai/dsh-typert-registry": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-goal": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-session-persistence": "workspace:^", + "@deepseek-ai/dsh-typert-registry": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -68,6 +68,6 @@ "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-session-persistence": "workspace:^", "@deepseek-ai/dsh-typert-registry": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/attachment/attachment-local/package.json b/packages/attachment/attachment-local/package.json index 4219c40d30..c8804218f1 100644 --- a/packages/attachment/attachment-local/package.json +++ b/packages/attachment/attachment-local/package.json @@ -22,19 +22,19 @@ "files": ["lib/index.js", "lib/invariant.js", "lib/types/**/*.d.ts"], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-attachment": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-paths": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-attachment": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-paths": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0", + "@deepseek-ai/schemastery": "workspace:^", "sharp": "^0.35.3" }, "devDependencies": { "@deepseek-ai/dsh-attachment": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-paths": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/attachment/attachment/package.json b/packages/attachment/attachment/package.json index ad212f3933..9d58dccdf6 100644 --- a/packages/attachment/attachment/package.json +++ b/packages/attachment/attachment/package.json @@ -22,13 +22,13 @@ "files": ["lib/index.js", "lib/invariant.js", "lib/types/**/*.d.ts"], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-brand": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-brand": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/bash/bash-env/package.json b/packages/bash/bash-env/package.json index 8983029c0d..cde53b2bd1 100644 --- a/packages/bash/bash-env/package.json +++ b/packages/bash/bash-env/package.json @@ -32,15 +32,15 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-bash": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-paths": "^0.0.1", - "@deepseek-ai/dsh-session-persistence": "^0.0.1", - "@deepseek-ai/dsh-tools": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-bash": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-paths": "workspace:^", + "@deepseek-ai/dsh-session-persistence": "workspace:^", + "@deepseek-ai/dsh-tools": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -50,6 +50,6 @@ "@deepseek-ai/dsh-paths": "workspace:^", "@deepseek-ai/dsh-session-persistence": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/bash/bash-local/package.json b/packages/bash/bash-local/package.json index f147b01f72..85eb6f2655 100644 --- a/packages/bash/bash-local/package.json +++ b/packages/bash/bash-local/package.json @@ -32,14 +32,14 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-bash": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-subprocess": "^0.0.1", - "@deepseek-ai/dsh-timeout": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-bash": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-subprocess": "workspace:^", + "@deepseek-ai/dsh-timeout": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-bash": "workspace:^", @@ -47,6 +47,6 @@ "@deepseek-ai/dsh-subprocess": "workspace:^", "@deepseek-ai/dsh-subprocess-local": "workspace:^", "@deepseek-ai/dsh-timeout": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/bash/bash-sandbox/package.json b/packages/bash/bash-sandbox/package.json index b1d1b4a13a..e77dba32e5 100644 --- a/packages/bash/bash-sandbox/package.json +++ b/packages/bash/bash-sandbox/package.json @@ -32,12 +32,12 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-bash": "^0.0.1", - "@deepseek-ai/dsh-bash-local": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-sandbox": "^0.0.1", - "@deepseek-ai/dsh-sandbox-policy": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-bash": "workspace:^", + "@deepseek-ai/dsh-bash-local": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-sandbox": "workspace:^", + "@deepseek-ai/dsh-sandbox-policy": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-bash": "workspace:^", @@ -47,7 +47,7 @@ "@deepseek-ai/dsh-sandbox": "workspace:^", "@deepseek-ai/dsh-sandbox-local": "workspace:^", "@deepseek-ai/dsh-sandbox-policy": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/cordis": "workspace:^", "@deepseek-ai/node-addon-landlock-run": "workspace:*" } } diff --git a/packages/bash/bash/package.json b/packages/bash/bash/package.json index 320f077f28..8d22d657fe 100644 --- a/packages/bash/bash/package.json +++ b/packages/bash/bash/package.json @@ -32,15 +32,15 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-subprocess": "^0.0.1", - "@deepseek-ai/dsh-sandbox": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-subprocess": "workspace:^", + "@deepseek-ai/dsh-sandbox": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-subprocess": "workspace:^", "@deepseek-ai/dsh-sandbox": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/bash/pwsh-local/package.json b/packages/bash/pwsh-local/package.json index a3b5d6aa7d..5e58a5cd3f 100644 --- a/packages/bash/pwsh-local/package.json +++ b/packages/bash/pwsh-local/package.json @@ -32,14 +32,14 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-bash": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-subprocess": "^0.0.1", - "@deepseek-ai/dsh-timeout": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-bash": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-subprocess": "workspace:^", + "@deepseek-ai/dsh-timeout": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-bash": "workspace:^", @@ -47,6 +47,6 @@ "@deepseek-ai/dsh-subprocess": "workspace:^", "@deepseek-ai/dsh-subprocess-local": "workspace:^", "@deepseek-ai/dsh-timeout": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/bash/pwsh-sandbox/package.json b/packages/bash/pwsh-sandbox/package.json index 727496274b..12669329c4 100644 --- a/packages/bash/pwsh-sandbox/package.json +++ b/packages/bash/pwsh-sandbox/package.json @@ -32,12 +32,12 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-bash": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-pwsh-local": "^0.0.1", - "@deepseek-ai/dsh-sandbox": "^0.0.1", - "@deepseek-ai/dsh-sandbox-policy": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-bash": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-pwsh-local": "workspace:^", + "@deepseek-ai/dsh-sandbox": "workspace:^", + "@deepseek-ai/dsh-sandbox-policy": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-bash": "workspace:^", @@ -47,6 +47,6 @@ "@deepseek-ai/dsh-sandbox-local": "workspace:^", "@deepseek-ai/dsh-sandbox-policy": "workspace:^", "@deepseek-ai/dsh-subprocess-local": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/bash/tool-bash/package.json b/packages/bash/tool-bash/package.json index 6440e990b0..a3d878e8e2 100644 --- a/packages/bash/tool-bash/package.json +++ b/packages/bash/tool-bash/package.json @@ -32,21 +32,21 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-bash": "^0.0.1", - "@deepseek-ai/dsh-bash-env": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-sandbox": "^0.0.1", - "@deepseek-ai/dsh-sandbox-policy": "^0.0.1", - "@deepseek-ai/dsh-system-prompt": "^0.0.1", - "@deepseek-ai/dsh-tasks": "^0.0.1", - "@deepseek-ai/dsh-tools": "^0.0.1", - "@deepseek-ai/dsh-user-approval": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-bash": "workspace:^", + "@deepseek-ai/dsh-bash-env": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-sandbox": "workspace:^", + "@deepseek-ai/dsh-sandbox-policy": "workspace:^", + "@deepseek-ai/dsh-system-prompt": "workspace:^", + "@deepseek-ai/dsh-tasks": "workspace:^", + "@deepseek-ai/dsh-tools": "workspace:^", + "@deepseek-ai/dsh-user-approval": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -68,6 +68,6 @@ "@deepseek-ai/dsh-tool-tasks": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", "@deepseek-ai/dsh-user-approval": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/bash/tool-pwsh/package.json b/packages/bash/tool-pwsh/package.json index b06df9a992..5188891aea 100644 --- a/packages/bash/tool-pwsh/package.json +++ b/packages/bash/tool-pwsh/package.json @@ -32,21 +32,21 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-bash": "^0.0.1", - "@deepseek-ai/dsh-bash-env": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-sandbox": "^0.0.1", - "@deepseek-ai/dsh-sandbox-policy": "^0.0.1", - "@deepseek-ai/dsh-system-prompt": "^0.0.1", - "@deepseek-ai/dsh-tasks": "^0.0.1", - "@deepseek-ai/dsh-tools": "^0.0.1", - "@deepseek-ai/dsh-user-approval": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-bash": "workspace:^", + "@deepseek-ai/dsh-bash-env": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-sandbox": "workspace:^", + "@deepseek-ai/dsh-sandbox-policy": "workspace:^", + "@deepseek-ai/dsh-system-prompt": "workspace:^", + "@deepseek-ai/dsh-tasks": "workspace:^", + "@deepseek-ai/dsh-tools": "workspace:^", + "@deepseek-ai/dsh-user-approval": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -65,6 +65,6 @@ "@deepseek-ai/dsh-tool-tasks": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", "@deepseek-ai/dsh-user-approval": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/boot/app-boot/package.json b/packages/boot/app-boot/package.json index f47611040d..4139847364 100644 --- a/packages/boot/app-boot/package.json +++ b/packages/boot/app-boot/package.json @@ -35,15 +35,15 @@ "js-yaml": "^4.2.0" }, "peerDependencies": { - "@deepseek-ai/cordis-plugin-group": "^1.0.0", - "@deepseek-ai/cordis-plugin-hmr": "^1.0.15", - "@deepseek-ai/cordis-plugin-include": "^1.0.4", - "@deepseek-ai/cordis-plugin-loader": "^1.0.0-rc.5", - "@deepseek-ai/dsh-environment": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-paths": "^0.0.1", - "@deepseek-ai/dsh-system-prompt": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis-plugin-group": "workspace:^", + "@deepseek-ai/cordis-plugin-hmr": "workspace:^", + "@deepseek-ai/cordis-plugin-include": "workspace:^", + "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/dsh-environment": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-paths": "workspace:^", + "@deepseek-ai/dsh-system-prompt": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "peerDependenciesMeta": { "@deepseek-ai/cordis-plugin-hmr": { @@ -61,6 +61,6 @@ "@deepseek-ai/dsh-paths": "workspace:^", "@deepseek-ai/dsh-system-prompt": "workspace:^", "@types/js-yaml": "^4.0.9", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/boot/cmdline/package.json b/packages/boot/cmdline/package.json index 28647bfc24..131c254af0 100644 --- a/packages/boot/cmdline/package.json +++ b/packages/boot/cmdline/package.json @@ -2,7 +2,14 @@ "name": "@deepseek-ai/dsh-cmdline", "description": "Immutable command-line handoff from a dsh launcher to any app plugin that injects cmdlineArgs", "version": "0.0.1", - "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", + "directory": "packages/boot/cmdline" + }, "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", @@ -25,15 +32,15 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/cordis-plugin-loader": "^1.0.0-rc.5", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/cordis-plugin-include": "workspace:^", "@deepseek-ai/cordis-plugin-loader": "workspace:^", "commander": "^15.0.0", "@deepseek-ai/dsh-invariants": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/bundle/base/package.json b/packages/bundle/base/package.json index c2547f9aae..dc54c75012 100644 --- a/packages/bundle/base/package.json +++ b/packages/bundle/base/package.json @@ -122,11 +122,11 @@ "@deepseek-ai/dsh-workspace-context": "workspace:^" }, "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/bundle/headless/package.json b/packages/bundle/headless/package.json index 4bdd04efd9..7778b7be8b 100644 --- a/packages/bundle/headless/package.json +++ b/packages/bundle/headless/package.json @@ -46,17 +46,17 @@ "dependencies": { "@deepseek-ai/dsh-cmdline": "workspace:^", "@deepseek-ai/dsh-code-runtime-worker": "workspace:^", - "@deepseek-ai/schemastery": "^3.18.0", + "@deepseek-ai/schemastery": "workspace:^", "commander": "^15.0.0" }, "peerDependencies": { - "@deepseek-ai/cordis-plugin-loader": "^1.0.0-rc.5", - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-agent-default-model": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-agent-default-model": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/cordis-plugin-loader": "workspace:^", @@ -65,6 +65,6 @@ "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/bundle/web-app/package.json b/packages/bundle/web-app/package.json index c9ec594f28..cde4fa1013 100644 --- a/packages/bundle/web-app/package.json +++ b/packages/bundle/web-app/package.json @@ -87,21 +87,21 @@ "@deepseek-ai/dsh-storage-domain": "workspace:^", "@deepseek-ai/dsh-storage-json": "workspace:^", "@deepseek-ai/dsh-workspace": "workspace:^", - "@deepseek-ai/schemastery": "^3.18.0", + "@deepseek-ai/schemastery": "workspace:^", "commander": "^15.0.0" }, "peerDependencies": { - "@deepseek-ai/cordis-plugin-loader": "^1.0.0-rc.5", - "@deepseek-ai/dsh-bash-env": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-system-prompt": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/dsh-bash-env": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-system-prompt": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/cordis-plugin-loader": "workspace:^", "@deepseek-ai/dsh-bash-env": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-system-prompt": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/client/connection/package.json b/packages/client/connection/package.json index f03afb8eda..1b9481db93 100644 --- a/packages/client/connection/package.json +++ b/packages/client/connection/package.json @@ -44,7 +44,7 @@ "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/schemastery": "^3.18.0", + "@deepseek-ai/schemastery": "workspace:^", "ws": "^8.21.0" }, "files": [ @@ -54,14 +54,14 @@ "lib/types/**/*.d.ts" ], "peerDependencies": { - "@deepseek-ai/dsh-host-webserver": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-host-webserver": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-host-webserver": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@types/ws": "^8.18.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/client/hmr/package.json b/packages/client/hmr/package.json index 82d8cb18e1..3dad86d07a 100644 --- a/packages/client/hmr/package.json +++ b/packages/client/hmr/package.json @@ -38,21 +38,21 @@ }, "license": "BSD-3-Clause", "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "peerDependencies": { - "@deepseek-ai/cordis-plugin-loader": "^1.0.0-rc.5", - "@deepseek-ai/dsh-client-modules": "^0.0.1", - "@deepseek-ai/dsh-host-webserver": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/dsh-client-modules": "workspace:^", + "@deepseek-ai/dsh-host-webserver": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/cordis-plugin-loader": "workspace:^", "@deepseek-ai/dsh-client-modules": "workspace:^", "@deepseek-ai/dsh-host-webserver": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" }, "files": [ "lib/index.js", diff --git a/packages/client/locale/package.json b/packages/client/locale/package.json index f845feacc9..d44e8ee529 100644 --- a/packages/client/locale/package.json +++ b/packages/client/locale/package.json @@ -41,12 +41,12 @@ }, "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-client-connection": "^0.0.1", - "@deepseek-ai/dsh-client-runtime": "^0.0.1", - "@deepseek-ai/dsh-client-ui-primitives": "^0.0.1", - "@deepseek-ai/dsh-client-ui-slots": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/dsh-client-connection": "workspace:^", + "@deepseek-ai/dsh-client-runtime": "workspace:^", + "@deepseek-ai/dsh-client-ui-primitives": "workspace:^", + "@deepseek-ai/dsh-client-ui-slots": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^", "react": "^18.2.0" }, "devDependencies": { @@ -55,12 +55,12 @@ "@deepseek-ai/dsh-client-ui-slots": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@types/react": "~18.3.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/cordis": "workspace:^", "react": "^18.2.0" }, "dependencies": { "@deepseek-ai/dsh-settings": "workspace:^", - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "files": [ "lib/index.js", diff --git a/packages/client/modules/package.json b/packages/client/modules/package.json index e980619017..e93cd2951d 100644 --- a/packages/client/modules/package.json +++ b/packages/client/modules/package.json @@ -45,7 +45,7 @@ "@deepseek-ai/cordis-plugin-loader": "workspace:^", "@deepseek-ai/dsh-host-webserver": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" }, "files": [ "lib/index.js", @@ -54,7 +54,7 @@ "lib/types/**/*.d.ts" ], "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/client/runtime/package.json b/packages/client/runtime/package.json index 168e916223..87e259f64c 100644 --- a/packages/client/runtime/package.json +++ b/packages/client/runtime/package.json @@ -60,10 +60,10 @@ "zustand": "~4.4.7" }, "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-type-meta": "^0.0.1", - "@deepseek-ai/dsh-typert-registry": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-type-meta": "workspace:^", + "@deepseek-ai/dsh-typert-registry": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", @@ -71,8 +71,8 @@ "@deepseek-ai/dsh-type-meta": "workspace:^", "@deepseek-ai/dsh-typert-registry": "workspace:^", "@types/react": "~18.3.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7", - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/schemastery": "workspace:^" }, "files": [ "lib/index.js", diff --git a/packages/client/schema-form/package.json b/packages/client/schema-form/package.json index 30e0c24353..35d80feba6 100644 --- a/packages/client/schema-form/package.json +++ b/packages/client/schema-form/package.json @@ -27,15 +27,15 @@ }, "license": "BSD-3-Clause", "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" }, "files": [ "lib/index.js", diff --git a/packages/client/test-runtime/package.json b/packages/client/test-runtime/package.json index 1efc9228d4..54088ded59 100644 --- a/packages/client/test-runtime/package.json +++ b/packages/client/test-runtime/package.json @@ -32,12 +32,12 @@ "vitest": "^4.1.8" }, "peerDependencies": { - "@deepseek-ai/dsh-client-runtime": "^0.0.1", - "@deepseek-ai/dsh-client-ui-slots": "^0.0.1", - "@deepseek-ai/dsh-client-web-react": "^0.0.1", - "@deepseek-ai/dsh-host-apiproxy": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/dsh-client-runtime": "workspace:^", + "@deepseek-ai/dsh-client-ui-slots": "workspace:^", + "@deepseek-ai/dsh-client-web-react": "workspace:^", + "@deepseek-ai/dsh-host-apiproxy": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^", "react": "^18.2.0", "react-dom": "^18.2.0" }, @@ -49,7 +49,7 @@ "@deepseek-ai/dsh-invariants": "workspace:^", "@types/react": "~18.3.1", "@types/react-dom": "~18.3.0", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/cordis": "workspace:^", "react": "^18.2.0", "react-dom": "^18.2.0" }, diff --git a/packages/client/ui-agent-preset/package.json b/packages/client/ui-agent-preset/package.json index 90b6fc4fa8..77133dac21 100644 --- a/packages/client/ui-agent-preset/package.json +++ b/packages/client/ui-agent-preset/package.json @@ -47,16 +47,16 @@ }, "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-client-connection": "^0.0.1", - "@deepseek-ai/dsh-client-locale": "^0.0.1", - "@deepseek-ai/dsh-client-runtime": "^0.0.1", - "@deepseek-ai/dsh-client-ui-conversation": "^0.0.1", - "@deepseek-ai/dsh-client-ui-primitives": "^0.0.1", - "@deepseek-ai/dsh-client-ui-settings": "^0.0.1", - "@deepseek-ai/dsh-client-ui-slots": "^0.0.1", - "@deepseek-ai/dsh-client-web-react": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/dsh-client-connection": "workspace:^", + "@deepseek-ai/dsh-client-locale": "workspace:^", + "@deepseek-ai/dsh-client-runtime": "workspace:^", + "@deepseek-ai/dsh-client-ui-conversation": "workspace:^", + "@deepseek-ai/dsh-client-ui-primitives": "workspace:^", + "@deepseek-ai/dsh-client-ui-settings": "workspace:^", + "@deepseek-ai/dsh-client-ui-slots": "workspace:^", + "@deepseek-ai/dsh-client-web-react": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^", "react": "^18.2.0" }, "devDependencies": { @@ -71,7 +71,7 @@ "@deepseek-ai/dsh-client-web-react": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@types/react": "~18.3.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/cordis": "workspace:^", "react": "^18.2.0" }, "files": [ diff --git a/packages/client/ui-command/package.json b/packages/client/ui-command/package.json index 513f6cf8a4..d6b015eb96 100644 --- a/packages/client/ui-command/package.json +++ b/packages/client/ui-command/package.json @@ -49,15 +49,15 @@ "clsx": "^2.0.0" }, "peerDependencies": { - "@deepseek-ai/dsh-client-connection": "^0.0.1", - "@deepseek-ai/dsh-client-locale": "^0.0.1", - "@deepseek-ai/dsh-client-runtime": "^0.0.1", - "@deepseek-ai/dsh-client-ui-conversation": "^0.0.1", - "@deepseek-ai/dsh-client-ui-primitives": "^0.0.1", - "@deepseek-ai/dsh-client-ui-slash": "^0.0.1", - "@deepseek-ai/dsh-client-ui-slots": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/dsh-client-connection": "workspace:^", + "@deepseek-ai/dsh-client-locale": "workspace:^", + "@deepseek-ai/dsh-client-runtime": "workspace:^", + "@deepseek-ai/dsh-client-ui-conversation": "workspace:^", + "@deepseek-ai/dsh-client-ui-primitives": "workspace:^", + "@deepseek-ai/dsh-client-ui-slash": "workspace:^", + "@deepseek-ai/dsh-client-ui-slots": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^", "react": "^18.2.0" }, "devDependencies": { @@ -71,7 +71,7 @@ "@deepseek-ai/dsh-client-ui-slots": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@types/react": "~18.3.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/cordis": "workspace:^", "react": "^18.2.0" }, "files": [ diff --git a/packages/client/ui-conversation/package.json b/packages/client/ui-conversation/package.json index bb93c82608..f3dd749dde 100644 --- a/packages/client/ui-conversation/package.json +++ b/packages/client/ui-conversation/package.json @@ -48,25 +48,25 @@ "dependencies": { "@deepseek-ai/dsh-settings": "workspace:^", "clsx": "^2.0.0", - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "peerDependencies": { - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-attachment": "^0.0.1", - "@deepseek-ai/dsh-brand": "^0.0.1", - "@deepseek-ai/dsh-client-connection": "^0.0.1", - "@deepseek-ai/dsh-client-locale": "^0.0.1", - "@deepseek-ai/dsh-client-runtime": "^0.0.1", - "@deepseek-ai/dsh-client-ui-primitives": "^0.0.1", - "@deepseek-ai/dsh-client-ui-slash": "^0.0.1", - "@deepseek-ai/dsh-client-ui-slots": "^0.0.1", - "@deepseek-ai/dsh-compact": "^0.0.1", - "@deepseek-ai/dsh-commands": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm-retry": "^0.0.1", - "@deepseek-ai/dsh-token-meter": "^0.0.1", - "@deepseek-ai/dsh-tools": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-attachment": "workspace:^", + "@deepseek-ai/dsh-brand": "workspace:^", + "@deepseek-ai/dsh-client-connection": "workspace:^", + "@deepseek-ai/dsh-client-locale": "workspace:^", + "@deepseek-ai/dsh-client-runtime": "workspace:^", + "@deepseek-ai/dsh-client-ui-primitives": "workspace:^", + "@deepseek-ai/dsh-client-ui-slash": "workspace:^", + "@deepseek-ai/dsh-client-ui-slots": "workspace:^", + "@deepseek-ai/dsh-compact": "workspace:^", + "@deepseek-ai/dsh-commands": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm-retry": "workspace:^", + "@deepseek-ai/dsh-token-meter": "workspace:^", + "@deepseek-ai/dsh-tools": "workspace:^", + "@deepseek-ai/cordis": "workspace:^", "react": "^18.2.0" }, "devDependencies": { @@ -93,7 +93,7 @@ "@deepseek-ai/dsh-tools": "workspace:^", "@deepseek-ai/dsh-tool-todo": "workspace:^", "@types/react": "~18.3.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/cordis": "workspace:^", "react": "^18.2.0" }, "files": [ diff --git a/packages/client/ui-deliverables/package.json b/packages/client/ui-deliverables/package.json index e60fc8262b..a5a82a833f 100644 --- a/packages/client/ui-deliverables/package.json +++ b/packages/client/ui-deliverables/package.json @@ -48,12 +48,12 @@ "react": "^18.2.0" }, "peerDependencies": { - "@deepseek-ai/dsh-client-locale": "^0.0.1", - "@deepseek-ai/dsh-client-runtime": "^0.0.1", - "@deepseek-ai/dsh-client-ui-conversation": "^0.0.1", - "@deepseek-ai/dsh-client-ui-slots": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-client-locale": "workspace:^", + "@deepseek-ai/dsh-client-runtime": "workspace:^", + "@deepseek-ai/dsh-client-ui-conversation": "workspace:^", + "@deepseek-ai/dsh-client-ui-slots": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-client-locale": "workspace:^", @@ -63,7 +63,7 @@ "@deepseek-ai/dsh-client-ui-slots": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@types/react": "~18.3.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" }, "files": [ "lib/index.js", diff --git a/packages/client/ui-goal/package.json b/packages/client/ui-goal/package.json index 648fb0e609..d1ed34e43c 100644 --- a/packages/client/ui-goal/package.json +++ b/packages/client/ui-goal/package.json @@ -46,15 +46,15 @@ }, "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-client-locale": "^0.0.1", - "@deepseek-ai/dsh-api-remotes": "^0.0.1", - "@deepseek-ai/dsh-client-runtime": "^0.0.1", - "@deepseek-ai/dsh-client-ui-conversation": "^0.0.1", - "@deepseek-ai/dsh-client-ui-primitives": "^0.0.1", - "@deepseek-ai/dsh-client-ui-slots": "^0.0.1", - "@deepseek-ai/dsh-goal": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/dsh-client-locale": "workspace:^", + "@deepseek-ai/dsh-api-remotes": "workspace:^", + "@deepseek-ai/dsh-client-runtime": "workspace:^", + "@deepseek-ai/dsh-client-ui-conversation": "workspace:^", + "@deepseek-ai/dsh-client-ui-primitives": "workspace:^", + "@deepseek-ai/dsh-client-ui-slots": "workspace:^", + "@deepseek-ai/dsh-goal": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^", "react": "^18.2.0" }, "devDependencies": { @@ -69,7 +69,7 @@ "@deepseek-ai/dsh-invariants": "workspace:^", "@testing-library/react": "^16.1.0", "@types/react": "~18.3.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/cordis": "workspace:^", "react": "^18.2.0", "react-dom": "^18.2.0" }, diff --git a/packages/client/ui-layout/package.json b/packages/client/ui-layout/package.json index 26c056f602..879100dbe6 100644 --- a/packages/client/ui-layout/package.json +++ b/packages/client/ui-layout/package.json @@ -44,11 +44,11 @@ }, "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-client-runtime": "^0.0.1", - "@deepseek-ai/dsh-client-ui-slots": "^0.0.1", - "@deepseek-ai/dsh-client-ui-theme": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/dsh-client-runtime": "workspace:^", + "@deepseek-ai/dsh-client-ui-slots": "workspace:^", + "@deepseek-ai/dsh-client-ui-theme": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^", "react": "^18.2.0" }, "devDependencies": { @@ -58,7 +58,7 @@ "@deepseek-ai/dsh-client-ui-theme": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@types/react": "~18.3.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/cordis": "workspace:^", "react": "^18.2.0" }, "files": [ diff --git a/packages/client/ui-model/package.json b/packages/client/ui-model/package.json index d2ca1b3318..b8f411cdc7 100644 --- a/packages/client/ui-model/package.json +++ b/packages/client/ui-model/package.json @@ -45,17 +45,17 @@ }, "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-client-connection": "^0.0.1", - "@deepseek-ai/dsh-client-locale": "^0.0.1", - "@deepseek-ai/dsh-client-runtime": "^0.0.1", - "@deepseek-ai/dsh-client-ui-command": "^0.0.1", - "@deepseek-ai/dsh-client-ui-conversation": "^0.0.1", - "@deepseek-ai/dsh-client-ui-primitives": "^0.0.1", - "@deepseek-ai/dsh-client-ui-slash": "^0.0.1", - "@deepseek-ai/dsh-client-ui-slots": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", + "@deepseek-ai/dsh-client-connection": "workspace:^", + "@deepseek-ai/dsh-client-locale": "workspace:^", + "@deepseek-ai/dsh-client-runtime": "workspace:^", + "@deepseek-ai/dsh-client-ui-command": "workspace:^", + "@deepseek-ai/dsh-client-ui-conversation": "workspace:^", + "@deepseek-ai/dsh-client-ui-primitives": "workspace:^", + "@deepseek-ai/dsh-client-ui-slash": "workspace:^", + "@deepseek-ai/dsh-client-ui-slots": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", "clsx": "^2.1.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/cordis": "workspace:^", "react": "^18.2.0" }, "devDependencies": { @@ -70,7 +70,7 @@ "@deepseek-ai/dsh-invariants": "workspace:^", "@types/react": "~18.3.1", "clsx": "^2.1.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/cordis": "workspace:^", "react": "^18.2.0" }, "files": [ diff --git a/packages/client/ui-models/package.json b/packages/client/ui-models/package.json index 8eaac3bccf..0a7b6bbae8 100644 --- a/packages/client/ui-models/package.json +++ b/packages/client/ui-models/package.json @@ -45,14 +45,14 @@ }, "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-client-connection": "^0.0.1", - "@deepseek-ai/dsh-client-runtime": "^0.0.1", - "@deepseek-ai/dsh-client-schema-form": "^0.0.1", - "@deepseek-ai/dsh-client-ui-primitives": "^0.0.1", - "@deepseek-ai/dsh-client-ui-slots": "^0.0.1", - "@deepseek-ai/dsh-client-web-react": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/dsh-client-connection": "workspace:^", + "@deepseek-ai/dsh-client-runtime": "workspace:^", + "@deepseek-ai/dsh-client-schema-form": "workspace:^", + "@deepseek-ai/dsh-client-ui-primitives": "workspace:^", + "@deepseek-ai/dsh-client-ui-slots": "workspace:^", + "@deepseek-ai/dsh-client-web-react": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^", "react": "^18.2.0" }, "devDependencies": { @@ -67,7 +67,7 @@ "@deepseek-ai/dsh-client-web-react": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@types/react": "~18.3.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/cordis": "workspace:^", "react": "^18.2.0" }, "files": [ diff --git a/packages/client/ui-permission/package.json b/packages/client/ui-permission/package.json index 12f1a25509..880666ecad 100644 --- a/packages/client/ui-permission/package.json +++ b/packages/client/ui-permission/package.json @@ -46,17 +46,17 @@ }, "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-client-connection": "^0.0.1", - "@deepseek-ai/dsh-client-locale": "^0.0.1", - "@deepseek-ai/dsh-client-runtime": "^0.0.1", - "@deepseek-ai/dsh-client-schema-form": "^0.0.1", - "@deepseek-ai/dsh-client-ui-command": "^0.0.1", - "@deepseek-ai/dsh-client-ui-primitives": "^0.0.1", - "@deepseek-ai/dsh-client-ui-slash": "^0.0.1", - "@deepseek-ai/dsh-client-ui-slots": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-permission": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/dsh-client-connection": "workspace:^", + "@deepseek-ai/dsh-client-locale": "workspace:^", + "@deepseek-ai/dsh-client-runtime": "workspace:^", + "@deepseek-ai/dsh-client-schema-form": "workspace:^", + "@deepseek-ai/dsh-client-ui-command": "workspace:^", + "@deepseek-ai/dsh-client-ui-primitives": "workspace:^", + "@deepseek-ai/dsh-client-ui-slash": "workspace:^", + "@deepseek-ai/dsh-client-ui-slots": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-permission": "workspace:^", + "@deepseek-ai/cordis": "workspace:^", "react": "^18.2.0" }, "devDependencies": { @@ -72,7 +72,7 @@ "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-permission": "workspace:^", "@types/react": "~18.3.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/cordis": "workspace:^", "react": "^18.2.0" }, "files": [ diff --git a/packages/client/ui-plan/package.json b/packages/client/ui-plan/package.json index 23d03b88d3..52d8e9fffd 100644 --- a/packages/client/ui-plan/package.json +++ b/packages/client/ui-plan/package.json @@ -45,15 +45,15 @@ }, "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-client-connection": "^0.0.1", - "@deepseek-ai/dsh-client-locale": "^0.0.1", - "@deepseek-ai/dsh-client-runtime": "^0.0.1", - "@deepseek-ai/dsh-client-ui-conversation": "^0.0.1", - "@deepseek-ai/dsh-client-ui-primitives": "^0.0.1", - "@deepseek-ai/dsh-client-ui-slots": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-plan-mode": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/dsh-client-connection": "workspace:^", + "@deepseek-ai/dsh-client-locale": "workspace:^", + "@deepseek-ai/dsh-client-runtime": "workspace:^", + "@deepseek-ai/dsh-client-ui-conversation": "workspace:^", + "@deepseek-ai/dsh-client-ui-primitives": "workspace:^", + "@deepseek-ai/dsh-client-ui-slots": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-plan-mode": "workspace:^", + "@deepseek-ai/cordis": "workspace:^", "react": "^18.2.0" }, "devDependencies": { @@ -68,7 +68,7 @@ "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-plan-mode": "workspace:^", "@types/react": "~18.3.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/cordis": "workspace:^", "react": "^18.2.0" }, "files": [ diff --git a/packages/client/ui-primitives/package.json b/packages/client/ui-primitives/package.json index dc0c21d31f..732321b932 100644 --- a/packages/client/ui-primitives/package.json +++ b/packages/client/ui-primitives/package.json @@ -52,7 +52,7 @@ "@deepseek-ai/dsh-invariants": "workspace:^", "@types/react": "~18.3.1", "@types/react-dom": "~18.3.0", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" }, "files": [ "lib/index.js", @@ -60,7 +60,7 @@ "lib/types/**/*.d.ts" ], "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/client/ui-question/package.json b/packages/client/ui-question/package.json index 172f4fb4f8..3153f8fd69 100644 --- a/packages/client/ui-question/package.json +++ b/packages/client/ui-question/package.json @@ -53,9 +53,9 @@ "react": "^18.2.0" }, "peerDependencies": { - "@deepseek-ai/dsh-client-locale": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-client-locale": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -65,7 +65,7 @@ "@deepseek-ai/dsh-tools": "workspace:^", "@deepseek-ai/dsh-user-interaction": "workspace:^", "@types/react": "~18.3.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" }, "files": [ "lib/index.js", diff --git a/packages/client/ui-settings-general/package.json b/packages/client/ui-settings-general/package.json index b67d12a709..8eee8eab62 100644 --- a/packages/client/ui-settings-general/package.json +++ b/packages/client/ui-settings-general/package.json @@ -47,18 +47,18 @@ "license": "BSD-3-Clause", "dependencies": { "@deepseek-ai/dsh-settings": "workspace:^", - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "peerDependencies": { - "@deepseek-ai/dsh-client-connection": "^0.0.1", - "@deepseek-ai/dsh-client-locale": "^0.0.1", - "@deepseek-ai/dsh-client-runtime": "^0.0.1", - "@deepseek-ai/dsh-client-ui-primitives": "^0.0.1", - "@deepseek-ai/dsh-client-ui-settings": "^0.0.1", - "@deepseek-ai/dsh-client-ui-slots": "^0.0.1", - "@deepseek-ai/dsh-client-web-react": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/dsh-client-connection": "workspace:^", + "@deepseek-ai/dsh-client-locale": "workspace:^", + "@deepseek-ai/dsh-client-runtime": "workspace:^", + "@deepseek-ai/dsh-client-ui-primitives": "workspace:^", + "@deepseek-ai/dsh-client-ui-settings": "workspace:^", + "@deepseek-ai/dsh-client-ui-slots": "workspace:^", + "@deepseek-ai/dsh-client-web-react": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^", "react": "^18.2.0" }, "devDependencies": { @@ -72,7 +72,7 @@ "@deepseek-ai/dsh-client-web-react": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@types/react": "~18.3.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/cordis": "workspace:^", "react": "^18.2.0" }, "files": [ diff --git a/packages/client/ui-settings/package.json b/packages/client/ui-settings/package.json index a65466e2c2..37c1e1607c 100644 --- a/packages/client/ui-settings/package.json +++ b/packages/client/ui-settings/package.json @@ -47,11 +47,11 @@ "clsx": "^2.0.0" }, "peerDependencies": { - "@deepseek-ai/dsh-client-runtime": "^0.0.1", - "@deepseek-ai/dsh-client-ui-primitives": "^0.0.1", - "@deepseek-ai/dsh-client-ui-slots": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/dsh-client-runtime": "workspace:^", + "@deepseek-ai/dsh-client-ui-primitives": "workspace:^", + "@deepseek-ai/dsh-client-ui-slots": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^", "react": "^18.2.0", "react-dom": "^18.2.0" }, @@ -64,7 +64,7 @@ "@deepseek-ai/dsh-invariants": "workspace:^", "@types/react-dom": "~18.3.0", "@types/react": "~18.3.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/cordis": "workspace:^", "react": "^18.2.0", "react-dom": "^18.2.0" }, diff --git a/packages/client/ui-sidebar/package.json b/packages/client/ui-sidebar/package.json index c4022d04d0..bffbbfd54c 100644 --- a/packages/client/ui-sidebar/package.json +++ b/packages/client/ui-sidebar/package.json @@ -48,12 +48,12 @@ "clsx": "^2.0.0" }, "peerDependencies": { - "@deepseek-ai/dsh-client-locale": "^0.0.1", - "@deepseek-ai/dsh-client-runtime": "^0.0.1", - "@deepseek-ai/dsh-client-ui-primitives": "^0.0.1", - "@deepseek-ai/dsh-client-ui-slots": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/dsh-client-locale": "workspace:^", + "@deepseek-ai/dsh-client-runtime": "workspace:^", + "@deepseek-ai/dsh-client-ui-primitives": "workspace:^", + "@deepseek-ai/dsh-client-ui-slots": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^", "react": "^18.2.0" }, "devDependencies": { @@ -65,7 +65,7 @@ "@deepseek-ai/dsh-client-ui-slots": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@types/react": "~18.3.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/cordis": "workspace:^", "react": "^18.2.0" }, "files": [ diff --git a/packages/client/ui-skill/package.json b/packages/client/ui-skill/package.json index d87425625a..c1ee7720bb 100644 --- a/packages/client/ui-skill/package.json +++ b/packages/client/ui-skill/package.json @@ -46,15 +46,15 @@ }, "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-client-connection": "^0.0.1", - "@deepseek-ai/dsh-client-locale": "^0.0.1", - "@deepseek-ai/dsh-client-runtime": "^0.0.1", - "@deepseek-ai/dsh-client-ui-tool": "^0.0.1", - "@deepseek-ai/dsh-client-ui-primitives": "^0.0.1", - "@deepseek-ai/dsh-client-ui-slash": "^0.0.1", - "@deepseek-ai/dsh-client-ui-slots": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/dsh-client-connection": "workspace:^", + "@deepseek-ai/dsh-client-locale": "workspace:^", + "@deepseek-ai/dsh-client-runtime": "workspace:^", + "@deepseek-ai/dsh-client-ui-tool": "workspace:^", + "@deepseek-ai/dsh-client-ui-primitives": "workspace:^", + "@deepseek-ai/dsh-client-ui-slash": "workspace:^", + "@deepseek-ai/dsh-client-ui-slots": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^", "react": "^18.2.0" }, "devDependencies": { @@ -69,7 +69,7 @@ "@deepseek-ai/dsh-invariants": "workspace:^", "@testing-library/react": "^16.1.0", "@types/react": "~18.3.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/cordis": "workspace:^", "react": "^18.2.0", "react-dom": "^18.2.0" }, diff --git a/packages/client/ui-slash/package.json b/packages/client/ui-slash/package.json index 46de2a5951..00b5bd1f9a 100644 --- a/packages/client/ui-slash/package.json +++ b/packages/client/ui-slash/package.json @@ -47,12 +47,12 @@ "clsx": "^2.0.0" }, "peerDependencies": { - "@deepseek-ai/dsh-client-locale": "^0.0.1", - "@deepseek-ai/dsh-client-runtime": "^0.0.1", - "@deepseek-ai/dsh-client-ui-primitives": "^0.0.1", - "@deepseek-ai/dsh-client-ui-slots": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/dsh-client-locale": "workspace:^", + "@deepseek-ai/dsh-client-runtime": "workspace:^", + "@deepseek-ai/dsh-client-ui-primitives": "workspace:^", + "@deepseek-ai/dsh-client-ui-slots": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^", "react": "^18.2.0" }, "devDependencies": { @@ -63,7 +63,7 @@ "@deepseek-ai/dsh-client-ui-slots": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@types/react": "~18.3.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/cordis": "workspace:^", "react": "^18.2.0" }, "files": [ diff --git a/packages/client/ui-slots/package.json b/packages/client/ui-slots/package.json index c9825022e8..54b3d64925 100644 --- a/packages/client/ui-slots/package.json +++ b/packages/client/ui-slots/package.json @@ -29,7 +29,7 @@ "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@types/react": "~18.3.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" }, "files": [ "lib/index.js", @@ -37,7 +37,7 @@ "lib/types/**/*.d.ts" ], "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/client/ui-subagent/package.json b/packages/client/ui-subagent/package.json index bbae62edb6..997bfadcf6 100644 --- a/packages/client/ui-subagent/package.json +++ b/packages/client/ui-subagent/package.json @@ -50,16 +50,16 @@ "react": "^18.2.0" }, "peerDependencies": { - "@deepseek-ai/dsh-client-locale": "^0.0.1", - "@deepseek-ai/dsh-client-runtime": "^0.0.1", - "@deepseek-ai/dsh-client-ui-conversation": "^0.0.1", - "@deepseek-ai/dsh-client-ui-primitives": "^0.0.1", - "@deepseek-ai/dsh-client-ui-slash": "^0.0.1", - "@deepseek-ai/dsh-client-ui-slots": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-subagent": "^0.0.1", - "@deepseek-ai/dsh-token-meter": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-client-locale": "workspace:^", + "@deepseek-ai/dsh-client-runtime": "workspace:^", + "@deepseek-ai/dsh-client-ui-conversation": "workspace:^", + "@deepseek-ai/dsh-client-ui-primitives": "workspace:^", + "@deepseek-ai/dsh-client-ui-slash": "workspace:^", + "@deepseek-ai/dsh-client-ui-slots": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-subagent": "workspace:^", + "@deepseek-ai/dsh-token-meter": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-client-locale": "workspace:^", @@ -73,7 +73,7 @@ "@deepseek-ai/dsh-subagent": "workspace:^", "@deepseek-ai/dsh-token-meter": "workspace:^", "@types/react": "~18.3.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" }, "files": [ "lib/index.js", diff --git a/packages/client/ui-theme/package.json b/packages/client/ui-theme/package.json index 1ad1274427..8d22586ffd 100644 --- a/packages/client/ui-theme/package.json +++ b/packages/client/ui-theme/package.json @@ -43,13 +43,13 @@ }, "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-client-connection": "^0.0.1", - "@deepseek-ai/dsh-client-locale": "^0.0.1", - "@deepseek-ai/dsh-client-runtime": "^0.0.1", - "@deepseek-ai/dsh-client-ui-primitives": "^0.0.1", - "@deepseek-ai/dsh-client-ui-slots": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/dsh-client-connection": "workspace:^", + "@deepseek-ai/dsh-client-locale": "workspace:^", + "@deepseek-ai/dsh-client-runtime": "workspace:^", + "@deepseek-ai/dsh-client-ui-primitives": "workspace:^", + "@deepseek-ai/dsh-client-ui-slots": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^", "react": "^18.2.0" }, "devDependencies": { @@ -60,7 +60,7 @@ "@deepseek-ai/dsh-client-ui-slots": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@types/react": "~18.3.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/cordis": "workspace:^", "react": "^18.2.0" }, "files": [ @@ -77,6 +77,6 @@ "dependencies": { "@deepseek-ai/dsh-settings": "workspace:^", "clsx": "^2.0.0", - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" } } diff --git a/packages/client/ui-tool/package.json b/packages/client/ui-tool/package.json index eb3b9366ba..c0465db10c 100644 --- a/packages/client/ui-tool/package.json +++ b/packages/client/ui-tool/package.json @@ -48,13 +48,13 @@ "clsx": "^2.0.0" }, "peerDependencies": { - "@deepseek-ai/dsh-client-locale": "^0.0.1", - "@deepseek-ai/dsh-client-runtime": "^0.0.1", - "@deepseek-ai/dsh-client-ui-conversation": "^0.0.1", - "@deepseek-ai/dsh-client-ui-primitives": "^0.0.1", - "@deepseek-ai/dsh-client-ui-slots": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/dsh-client-locale": "workspace:^", + "@deepseek-ai/dsh-client-runtime": "workspace:^", + "@deepseek-ai/dsh-client-ui-conversation": "workspace:^", + "@deepseek-ai/dsh-client-ui-primitives": "workspace:^", + "@deepseek-ai/dsh-client-ui-slots": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^", "react": "^18.2.0" }, "devDependencies": { @@ -69,7 +69,7 @@ "@deepseek-ai/dsh-invariants": "workspace:^", "@testing-library/react": "^16.1.0", "@types/react": "~18.3.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/cordis": "workspace:^", "react": "^18.2.0", "react-dom": "^18.2.0" }, diff --git a/packages/client/ui-trajectory/package.json b/packages/client/ui-trajectory/package.json index 4aef2a424b..c50633c2c1 100644 --- a/packages/client/ui-trajectory/package.json +++ b/packages/client/ui-trajectory/package.json @@ -48,10 +48,10 @@ "diff": "^9.0.0" }, "peerDependencies": { - "@deepseek-ai/dsh-client-runtime": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-client-ui-primitives": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/dsh-client-runtime": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-client-ui-primitives": "workspace:^", + "@deepseek-ai/cordis": "workspace:^", "react": "^18.2.0", "react-dom": "^18.2.0" }, @@ -63,7 +63,7 @@ "@deepseek-ai/dsh-invariants": "workspace:^", "@types/react": "~18.3.1", "@types/react-dom": "~18.3.0", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/cordis": "workspace:^", "react": "^18.2.0", "react-dom": "^18.2.0" }, diff --git a/packages/client/ui-workspace/package.json b/packages/client/ui-workspace/package.json index 7b4ad80acf..206e037bc1 100644 --- a/packages/client/ui-workspace/package.json +++ b/packages/client/ui-workspace/package.json @@ -49,12 +49,12 @@ "clsx": "^2.0.0" }, "peerDependencies": { - "@deepseek-ai/dsh-client-locale": "^0.0.1", - "@deepseek-ai/dsh-client-runtime": "^0.0.1", - "@deepseek-ai/dsh-client-ui-primitives": "^0.0.1", - "@deepseek-ai/dsh-client-ui-slots": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/dsh-client-locale": "workspace:^", + "@deepseek-ai/dsh-client-runtime": "workspace:^", + "@deepseek-ai/dsh-client-ui-primitives": "workspace:^", + "@deepseek-ai/dsh-client-ui-slots": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^", "react": "^18.2.0" }, "devDependencies": { @@ -67,7 +67,7 @@ "@deepseek-ai/dsh-client-ui-slots": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@types/react": "~18.3.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/cordis": "workspace:^", "react": "^18.2.0" }, "files": [ diff --git a/packages/client/web-react/package.json b/packages/client/web-react/package.json index 3f65de4ad8..1fe9231134 100644 --- a/packages/client/web-react/package.json +++ b/packages/client/web-react/package.json @@ -32,13 +32,13 @@ "use-sync-external-store": "1.2.0" }, "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@types/react": "~18.3.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" }, "files": [ "lib/index.js", diff --git a/packages/client/web/package.json b/packages/client/web/package.json index e4a1e60136..eff725c83d 100644 --- a/packages/client/web/package.json +++ b/packages/client/web/package.json @@ -43,13 +43,13 @@ "@deepseek-ai/dsh-invariants": "workspace:^", "@types/react": "~18.3.1", "@types/react-dom": "~18.3.0", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/cordis": "workspace:^", "typescript": "^6.0.3" }, "peerDependencies": { - "@deepseek-ai/cordis-plugin-loader": "^1.0.0-rc.5", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "files": [ "lib/index.js", diff --git a/packages/code-runtime/code-runtime-worker/package.json b/packages/code-runtime/code-runtime-worker/package.json index 55e2cbc398..bacaca170a 100644 --- a/packages/code-runtime/code-runtime-worker/package.json +++ b/packages/code-runtime/code-runtime-worker/package.json @@ -36,20 +36,20 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-code-runtime": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-timeout": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-code-runtime": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-timeout": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-code-runtime": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-timeout": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/code-runtime/code-runtime/package.json b/packages/code-runtime/code-runtime/package.json index 57b85721a3..89db4e6d88 100644 --- a/packages/code-runtime/code-runtime/package.json +++ b/packages/code-runtime/code-runtime/package.json @@ -32,11 +32,11 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/compact/command-compact/package.json b/packages/compact/command-compact/package.json index ff64dba2a6..3b36536a34 100644 --- a/packages/compact/command-compact/package.json +++ b/packages/compact/command-compact/package.json @@ -32,10 +32,10 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-commands": "^0.0.1", - "@deepseek-ai/dsh-compact": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-commands": "workspace:^", + "@deepseek-ai/dsh-compact": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/cordis-plugin-include": "workspace:^", @@ -46,6 +46,6 @@ "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/compact/compact-basic/package.json b/packages/compact/compact-basic/package.json index 1f6c2b402e..941e3aa32d 100644 --- a/packages/compact/compact-basic/package.json +++ b/packages/compact/compact-basic/package.json @@ -32,15 +32,15 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-compact": "^0.0.1", - "@deepseek-ai/dsh-commands": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-token-meter": "^0.0.1", - "@deepseek-ai/dsh-compact-tool-result-prune": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-compact": "workspace:^", + "@deepseek-ai/dsh-commands": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-token-meter": "workspace:^", + "@deepseek-ai/dsh-compact-tool-result-prune": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "peerDependenciesMeta": { "@deepseek-ai/dsh-compact-tool-result-prune": { @@ -48,7 +48,7 @@ } }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/cordis-plugin-include": "workspace:^", @@ -65,6 +65,6 @@ "@deepseek-ai/dsh-token-meter": "workspace:^", "@deepseek-ai/dsh-compact-tool-result-prune": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/compact/compact-tool-result-prune/package.json b/packages/compact/compact-tool-result-prune/package.json index 45eab7b091..21951f5750 100644 --- a/packages/compact/compact-tool-result-prune/package.json +++ b/packages/compact/compact-tool-result-prune/package.json @@ -32,15 +32,15 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-compact": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-token-meter": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-compact": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-token-meter": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/cordis-plugin-include": "workspace:^", @@ -50,6 +50,6 @@ "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-token-meter": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/compact/compact/package.json b/packages/compact/compact/package.json index abdcd8a090..18879ad5b5 100644 --- a/packages/compact/compact/package.json +++ b/packages/compact/compact/package.json @@ -41,12 +41,12 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-brand": "^0.0.1", - "@deepseek-ai/dsh-commands": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-brand": "workspace:^", + "@deepseek-ai/dsh-commands": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-brand": "workspace:^", @@ -54,6 +54,6 @@ "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/context/session-reference/package.json b/packages/context/session-reference/package.json index 900ec038e3..4c7c7af3f8 100644 --- a/packages/context/session-reference/package.json +++ b/packages/context/session-reference/package.json @@ -32,17 +32,17 @@ ], "license": "BSD-3-Clause", "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "peerDependencies": { - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-compact": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-retention": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-session-query": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-compact": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-retention": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-session-query": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -52,6 +52,6 @@ "@deepseek-ai/dsh-retention": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-session-query": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/context/time-context/package.json b/packages/context/time-context/package.json index 08bb776c47..6956bf48e0 100644 --- a/packages/context/time-context/package.json +++ b/packages/context/time-context/package.json @@ -32,13 +32,13 @@ ], "license": "BSD-3-Clause", "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "peerDependencies": { - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -50,6 +50,6 @@ "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/context/tmux-context/package.json b/packages/context/tmux-context/package.json index 6cff253fac..241661250f 100644 --- a/packages/context/tmux-context/package.json +++ b/packages/context/tmux-context/package.json @@ -32,14 +32,14 @@ ], "license": "BSD-3-Clause", "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "peerDependencies": { - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-bash": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-bash": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -48,6 +48,6 @@ "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-system-prompt": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/context/workspace-context/package.json b/packages/context/workspace-context/package.json index 843d038dc5..236009f90d 100644 --- a/packages/context/workspace-context/package.json +++ b/packages/context/workspace-context/package.json @@ -32,17 +32,17 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-fs": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-paths": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-tools": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.6" + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-fs": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-paths": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-tools": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/cordis-plugin-loader": "workspace:^", @@ -58,6 +58,6 @@ "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-tool-fs": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.6" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/core/agent-default-model/package.json b/packages/core/agent-default-model/package.json index 8a6341208e..8826a9fcc4 100644 --- a/packages/core/agent-default-model/package.json +++ b/packages/core/agent-default-model/package.json @@ -32,20 +32,20 @@ ], "license": "BSD-3-Clause", "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "peerDependencies": { - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-settings": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-settings": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-settings": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/core/agent-loop/package.json b/packages/core/agent-loop/package.json index d37d92aede..9f37505853 100644 --- a/packages/core/agent-loop/package.json +++ b/packages/core/agent-loop/package.json @@ -31,18 +31,18 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-scope": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-session-persistence": "^0.0.1", - "@deepseek-ai/dsh-system-prompt": "^0.0.1", - "@deepseek-ai/dsh-tools": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-scope": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-session-persistence": "workspace:^", + "@deepseek-ai/dsh-system-prompt": "workspace:^", + "@deepseek-ai/dsh-tools": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -54,6 +54,6 @@ "@deepseek-ai/dsh-session-persistence-jsonl": "workspace:^", "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/core/agent-tool-mode/package.json b/packages/core/agent-tool-mode/package.json index bb25b4a14c..a47dbd1434 100644 --- a/packages/core/agent-tool-mode/package.json +++ b/packages/core/agent-tool-mode/package.json @@ -32,12 +32,12 @@ ], "license": "BSD-3-Clause", "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-tools": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-tools": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -47,6 +47,6 @@ "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/core/agent/package.json b/packages/core/agent/package.json index b75f720ad4..b4fe30f2e5 100644 --- a/packages/core/agent/package.json +++ b/packages/core/agent/package.json @@ -37,13 +37,13 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-scope": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-system-prompt": "^0.0.1", - "@deepseek-ai/dsh-type-meta": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-scope": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-system-prompt": "workspace:^", + "@deepseek-ai/dsh-type-meta": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", @@ -53,6 +53,6 @@ "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-type-meta": "workspace:^", "@deepseek-ai/dsh-typert-registry": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/core/scope/package.json b/packages/core/scope/package.json index e82a8650e5..53bd185aa5 100644 --- a/packages/core/scope/package.json +++ b/packages/core/scope/package.json @@ -32,11 +32,11 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/core/session/package.json b/packages/core/session/package.json index 8fe45b8bed..40508e9a64 100644 --- a/packages/core/session/package.json +++ b/packages/core/session/package.json @@ -41,12 +41,12 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-brand": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-scope": "^0.0.1", - "@deepseek-ai/dsh-type-meta": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-brand": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-scope": "workspace:^", + "@deepseek-ai/dsh-type-meta": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-brand": "workspace:^", @@ -55,6 +55,6 @@ "@deepseek-ai/dsh-scope": "workspace:^", "@deepseek-ai/dsh-type-meta": "workspace:^", "@deepseek-ai/dsh-typert-registry": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/core/system-prompt/package.json b/packages/core/system-prompt/package.json index 3dc65c9391..e219dfa37a 100644 --- a/packages/core/system-prompt/package.json +++ b/packages/core/system-prompt/package.json @@ -32,18 +32,18 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-scope": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-scope": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-scope": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/core/tools/package.json b/packages/core/tools/package.json index 6db89c3b0f..e02c4afaef 100644 --- a/packages/core/tools/package.json +++ b/packages/core/tools/package.json @@ -41,18 +41,18 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-code-runtime": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-scope": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-system-prompt": "^0.0.1", - "@deepseek-ai/dsh-user-approval": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-code-runtime": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-scope": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-system-prompt": "workspace:^", + "@deepseek-ai/dsh-user-approval": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -63,6 +63,6 @@ "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-user-approval": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/credentials/credentials-local/package.json b/packages/credentials/credentials-local/package.json index b29c9d2fbb..004c5caec4 100644 --- a/packages/credentials/credentials-local/package.json +++ b/packages/credentials/credentials-local/package.json @@ -32,16 +32,16 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-atomic-write": "^0.0.1", - "@deepseek-ai/dsh-credentials": "^0.0.1", - "@deepseek-ai/dsh-environment": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-paths": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-atomic-write": "workspace:^", + "@deepseek-ai/dsh-credentials": "workspace:^", + "@deepseek-ai/dsh-environment": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-paths": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { "chokidar": "^4.0.3", - "@deepseek-ai/schemastery": "^3.18.0", + "@deepseek-ai/schemastery": "workspace:^", "yaml": "^2.9.0" }, "devDependencies": { @@ -50,6 +50,6 @@ "@deepseek-ai/dsh-environment": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-paths": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/credentials/credentials/package.json b/packages/credentials/credentials/package.json index f0c9c43694..8cc0d61e40 100644 --- a/packages/credentials/credentials/package.json +++ b/packages/credentials/credentials/package.json @@ -32,13 +32,13 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-brand": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-brand": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/e2b/e2b/package.json b/packages/e2b/e2b/package.json index 98dff52be8..fb47ba6c83 100644 --- a/packages/e2b/e2b/package.json +++ b/packages/e2b/e2b/package.json @@ -32,17 +32,17 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { "e2b": "2.29.1", - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-loader-smoke": "workspace:^", "@deepseek-ai/dsh-sandbox-policy": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/e2b/fs-e2b/package.json b/packages/e2b/fs-e2b/package.json index bb3190c4be..47c026eaf2 100644 --- a/packages/e2b/fs-e2b/package.json +++ b/packages/e2b/fs-e2b/package.json @@ -32,15 +32,15 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-e2b": "^0.0.1", - "@deepseek-ai/dsh-fs": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-e2b": "workspace:^", + "@deepseek-ai/dsh-fs": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-e2b": "workspace:^", "@deepseek-ai/dsh-fs": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/e2b/subprocess-e2b/package.json b/packages/e2b/subprocess-e2b/package.json index ca5de7a893..b7be6db8be 100644 --- a/packages/e2b/subprocess-e2b/package.json +++ b/packages/e2b/subprocess-e2b/package.json @@ -32,20 +32,20 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-e2b": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-subprocess": "^0.0.1", - "@deepseek-ai/dsh-timeout": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-e2b": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-subprocess": "workspace:^", + "@deepseek-ai/dsh-timeout": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-e2b": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-subprocess": "workspace:^", "@deepseek-ai/dsh-timeout": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/examples/acp-demo/package.json b/packages/examples/acp-demo/package.json index e21a3b21a2..1c7763482c 100644 --- a/packages/examples/acp-demo/package.json +++ b/packages/examples/acp-demo/package.json @@ -40,20 +40,20 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/cordis-plugin-include": "^1.0.4", - "@deepseek-ai/cordis-plugin-loader": "^1.0.0-rc.5", - "@deepseek-ai/dsh-acp": "^0.0.1", - "@deepseek-ai/dsh-agent-spine-demo": "^0.0.1", - "@deepseek-ai/dsh-app-boot": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-session-checkpoint-policy": "^0.0.1", - "@deepseek-ai/dsh-session-persistence-jsonl": "^0.0.1", - "@deepseek-ai/dsh-session-query": "^0.0.1", - "@deepseek-ai/dsh-session-query-sqlite": "^0.0.1", - "@deepseek-ai/dsh-tools": "^0.0.1", - "@deepseek-ai/dsh-workspace-context": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7", - "@deepseek-ai/schemastery": "^3.17.0" + "@deepseek-ai/cordis-plugin-include": "workspace:^", + "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/dsh-acp": "workspace:^", + "@deepseek-ai/dsh-agent-spine-demo": "workspace:^", + "@deepseek-ai/dsh-app-boot": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-session-checkpoint-policy": "workspace:^", + "@deepseek-ai/dsh-session-persistence-jsonl": "workspace:^", + "@deepseek-ai/dsh-session-query": "workspace:^", + "@deepseek-ai/dsh-session-query-sqlite": "workspace:^", + "@deepseek-ai/dsh-tools": "workspace:^", + "@deepseek-ai/dsh-workspace-context": "workspace:^", + "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/cordis-plugin-include": "workspace:^", @@ -70,7 +70,7 @@ "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", "@deepseek-ai/dsh-workspace-context": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7", - "@deepseek-ai/schemastery": "^3.17.0" + "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/schemastery": "workspace:^" } } diff --git a/packages/examples/agent-spine-demo/package.json b/packages/examples/agent-spine-demo/package.json index 470cb869df..3bfac5084c 100644 --- a/packages/examples/agent-spine-demo/package.json +++ b/packages/examples/agent-spine-demo/package.json @@ -32,30 +32,30 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/cordis-plugin-timer": "^1.1.2", - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-agent-loop": "^0.0.1", - "@deepseek-ai/dsh-goal": "^0.0.1", - "@deepseek-ai/dsh-goal-session": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-paths": "^0.0.1", - "@deepseek-ai/dsh-llm-retry": "^0.0.1", - "@deepseek-ai/dsh-scope": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-session-title": "^0.0.1", - "@deepseek-ai/dsh-skill": "^0.0.1", - "@deepseek-ai/dsh-skill-local": "^0.0.1", - "@deepseek-ai/dsh-system-prompt": "^0.0.1", - "@deepseek-ai/dsh-tasks-local": "^0.0.1", - "@deepseek-ai/dsh-bash-env": "^0.0.1", - "@deepseek-ai/dsh-tool-bash": "^0.0.1", - "@deepseek-ai/dsh-tool-goal": "^0.0.1", - "@deepseek-ai/dsh-tool-skill": "^0.0.1", - "@deepseek-ai/dsh-tool-tasks": "^0.0.1", - "@deepseek-ai/dsh-tools": "^0.0.1", - "@deepseek-ai/dsh-workspace-context": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis-plugin-timer": "workspace:^", + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-agent-loop": "workspace:^", + "@deepseek-ai/dsh-goal": "workspace:^", + "@deepseek-ai/dsh-goal-session": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-paths": "workspace:^", + "@deepseek-ai/dsh-llm-retry": "workspace:^", + "@deepseek-ai/dsh-scope": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-session-title": "workspace:^", + "@deepseek-ai/dsh-skill": "workspace:^", + "@deepseek-ai/dsh-skill-local": "workspace:^", + "@deepseek-ai/dsh-system-prompt": "workspace:^", + "@deepseek-ai/dsh-tasks-local": "workspace:^", + "@deepseek-ai/dsh-bash-env": "workspace:^", + "@deepseek-ai/dsh-tool-bash": "workspace:^", + "@deepseek-ai/dsh-tool-goal": "workspace:^", + "@deepseek-ai/dsh-tool-skill": "workspace:^", + "@deepseek-ai/dsh-tool-tasks": "workspace:^", + "@deepseek-ai/dsh-tools": "workspace:^", + "@deepseek-ai/dsh-workspace-context": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/cordis-plugin-timer": "workspace:^", @@ -92,9 +92,9 @@ "@deepseek-ai/dsh-tools": "workspace:^", "@deepseek-ai/dsh-workspace-context": "workspace:^", "@deepseek-ai/node-addon-landlock-run": "workspace:*", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" } } diff --git a/packages/examples/jsonrpc-demo/package.json b/packages/examples/jsonrpc-demo/package.json index a9452b6a22..ac6b0f05ee 100644 --- a/packages/examples/jsonrpc-demo/package.json +++ b/packages/examples/jsonrpc-demo/package.json @@ -48,11 +48,11 @@ "@deepseek-ai/dsh-app-boot": "workspace:^" }, "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/feedback/command-feedback/package.json b/packages/feedback/command-feedback/package.json index e3d72eb3cb..afdba48641 100644 --- a/packages/feedback/command-feedback/package.json +++ b/packages/feedback/command-feedback/package.json @@ -32,11 +32,11 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-commands": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-user-id": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-commands": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-user-id": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/cordis-plugin-include": "workspace:^", @@ -47,6 +47,6 @@ "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-user-id": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/fs/fs-local/package.json b/packages/fs/fs-local/package.json index feb0b621d5..c79a13a9d2 100644 --- a/packages/fs/fs-local/package.json +++ b/packages/fs/fs-local/package.json @@ -32,18 +32,18 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-fs": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-fs": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { "koffi": "^3.1.0", - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-fs": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/fs/fs-policy/package.json b/packages/fs/fs-policy/package.json index 26273eb031..39b6e0b6f0 100644 --- a/packages/fs/fs-policy/package.json +++ b/packages/fs/fs-policy/package.json @@ -32,14 +32,14 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-fs": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-fs": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-fs": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/fs/fs-sandbox/package.json b/packages/fs/fs-sandbox/package.json index 1622fc2621..610724a528 100644 --- a/packages/fs/fs-sandbox/package.json +++ b/packages/fs/fs-sandbox/package.json @@ -32,12 +32,12 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-fs": "^0.0.1", - "@deepseek-ai/dsh-fs-local": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-sandbox": "^0.0.1", - "@deepseek-ai/dsh-sandbox-policy": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-fs": "workspace:^", + "@deepseek-ai/dsh-fs-local": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-sandbox": "workspace:^", + "@deepseek-ai/dsh-sandbox-policy": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-fs": "workspace:^", @@ -45,6 +45,6 @@ "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-sandbox": "workspace:^", "@deepseek-ai/dsh-sandbox-policy": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/fs/fs/package.json b/packages/fs/fs/package.json index e14e5f0a15..fa97204f47 100644 --- a/packages/fs/fs/package.json +++ b/packages/fs/fs/package.json @@ -32,17 +32,17 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-brand": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-sandbox": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-brand": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-sandbox": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-sandbox": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/fs/tool-fs-search/package.json b/packages/fs/tool-fs-search/package.json index 6e8c611782..8a6a50f1b3 100644 --- a/packages/fs/tool-fs-search/package.json +++ b/packages/fs/tool-fs-search/package.json @@ -33,19 +33,19 @@ "license": "BSD-3-Clause", "dependencies": { "@vscode/ripgrep": "^1.18.0", - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-retention": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-spill": "^0.0.1", - "@deepseek-ai/dsh-subprocess": "^0.0.1", - "@deepseek-ai/dsh-system-prompt": "^0.0.1", - "@deepseek-ai/dsh-timeout": "^0.0.1", - "@deepseek-ai/dsh-tools": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.6" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-retention": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-spill": "workspace:^", + "@deepseek-ai/dsh-subprocess": "workspace:^", + "@deepseek-ai/dsh-system-prompt": "workspace:^", + "@deepseek-ai/dsh-timeout": "workspace:^", + "@deepseek-ai/dsh-tools": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -59,6 +59,6 @@ "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-timeout": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.6" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/fs/tool-fs/package.json b/packages/fs/tool-fs/package.json index 456f7514af..1e4ef4fbf8 100644 --- a/packages/fs/tool-fs/package.json +++ b/packages/fs/tool-fs/package.json @@ -33,19 +33,19 @@ "license": "BSD-3-Clause", "dependencies": { "diff": "^9.0.0", - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "peerDependencies": { - "@deepseek-ai/dsh-fs": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-sandbox": "^0.0.1", - "@deepseek-ai/dsh-sandbox-policy": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-system-prompt": "^0.0.1", - "@deepseek-ai/dsh-tools": "^0.0.1", - "@deepseek-ai/dsh-user-approval": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-fs": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-sandbox": "workspace:^", + "@deepseek-ai/dsh-sandbox-policy": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-system-prompt": "workspace:^", + "@deepseek-ai/dsh-tools": "workspace:^", + "@deepseek-ai/dsh-user-approval": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -63,6 +63,6 @@ "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", "@deepseek-ai/dsh-user-approval": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/fs/tool-str-replace-editor/package.json b/packages/fs/tool-str-replace-editor/package.json index 7dfd74c7cd..2a3b18bfdc 100644 --- a/packages/fs/tool-str-replace-editor/package.json +++ b/packages/fs/tool-str-replace-editor/package.json @@ -31,15 +31,15 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-fs": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-sandbox": "^0.0.1", - "@deepseek-ai/dsh-sandbox-policy": "^0.0.1", - "@deepseek-ai/dsh-tools": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-fs": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-sandbox": "workspace:^", + "@deepseek-ai/dsh-sandbox-policy": "workspace:^", + "@deepseek-ai/dsh-tools": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -54,6 +54,6 @@ "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/goal/command-goal/package.json b/packages/goal/command-goal/package.json index 8a34968cb6..bac6e02048 100644 --- a/packages/goal/command-goal/package.json +++ b/packages/goal/command-goal/package.json @@ -32,10 +32,10 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-commands": "^0.0.1", - "@deepseek-ai/dsh-goal": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-commands": "workspace:^", + "@deepseek-ai/dsh-goal": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/cordis-plugin-loader": "workspace:^", @@ -45,6 +45,6 @@ "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/goal/goal-session/package.json b/packages/goal/goal-session/package.json index 9fdb8e83e1..a43a4b1169 100644 --- a/packages/goal/goal-session/package.json +++ b/packages/goal/goal-session/package.json @@ -32,12 +32,12 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-goal": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-goal": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -49,6 +49,6 @@ "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/goal/goal/package.json b/packages/goal/goal/package.json index db2fe9c3c1..5ae59a8093 100644 --- a/packages/goal/goal/package.json +++ b/packages/goal/goal/package.json @@ -55,18 +55,18 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-session-projection": "^0.0.1", - "@deepseek-ai/dsh-brand": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-scope": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-type-meta": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-session-projection": "workspace:^", + "@deepseek-ai/dsh-brand": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-scope": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-type-meta": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.17.2", + "@deepseek-ai/schemastery": "workspace:^", "zod": "^4.4.3" }, "devDependencies": { @@ -79,6 +79,6 @@ "@deepseek-ai/dsh-scope": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-type-meta": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/goal/tool-goal/package.json b/packages/goal/tool-goal/package.json index 8c843fe7e8..309e020842 100644 --- a/packages/goal/tool-goal/package.json +++ b/packages/goal/tool-goal/package.json @@ -32,17 +32,17 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-goal": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-system-prompt": "^0.0.1", - "@deepseek-ai/dsh-tools": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-goal": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-system-prompt": "workspace:^", + "@deepseek-ai/dsh-tools": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/cordis-plugin-loader": "workspace:^", @@ -53,6 +53,6 @@ "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/guard/repeat-tool-guard/package.json b/packages/guard/repeat-tool-guard/package.json index 2f9bf37a0f..fbb6a39192 100644 --- a/packages/guard/repeat-tool-guard/package.json +++ b/packages/guard/repeat-tool-guard/package.json @@ -32,13 +32,13 @@ ], "license": "BSD-3-Clause", "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "peerDependencies": { - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-tools": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-tools": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -48,6 +48,6 @@ "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/guard/timeout-policy/package.json b/packages/guard/timeout-policy/package.json index 9ea624ee83..ab07cc70e0 100644 --- a/packages/guard/timeout-policy/package.json +++ b/packages/guard/timeout-policy/package.json @@ -32,17 +32,17 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-timeout": "^0.0.1", - "@deepseek-ai/dsh-tools": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-timeout": "workspace:^", + "@deepseek-ai/dsh-tools": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-timeout": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/hooks/hook-protocol/package.json b/packages/hooks/hook-protocol/package.json index d628b7772c..7d842222e0 100644 --- a/packages/hooks/hook-protocol/package.json +++ b/packages/hooks/hook-protocol/package.json @@ -32,15 +32,15 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-bash": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-bash": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-bash": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/hooks/hooks-claude/package.json b/packages/hooks/hooks-claude/package.json index 79ea6ec65b..a41e2e3b4d 100644 --- a/packages/hooks/hooks-claude/package.json +++ b/packages/hooks/hooks-claude/package.json @@ -32,18 +32,18 @@ ], "license": "BSD-3-Clause", "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "peerDependencies": { - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-hook-protocol": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-session-persistence": "^0.0.1", - "@deepseek-ai/dsh-subagent": "^0.0.1", - "@deepseek-ai/dsh-tools": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-hook-protocol": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-session-persistence": "workspace:^", + "@deepseek-ai/dsh-subagent": "workspace:^", + "@deepseek-ai/dsh-tools": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -60,6 +60,6 @@ "@deepseek-ai/dsh-session-persistence-jsonl": "workspace:^", "@deepseek-ai/dsh-subagent": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/hooks/hooks-codex/package.json b/packages/hooks/hooks-codex/package.json index 2f567eed26..4ff3f3dc38 100644 --- a/packages/hooks/hooks-codex/package.json +++ b/packages/hooks/hooks-codex/package.json @@ -32,17 +32,17 @@ ], "license": "BSD-3-Clause", "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "peerDependencies": { - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-hook-protocol": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-session-persistence": "^0.0.1", - "@deepseek-ai/dsh-tools": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-hook-protocol": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-session-persistence": "workspace:^", + "@deepseek-ai/dsh-tools": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -58,6 +58,6 @@ "@deepseek-ai/dsh-session-persistence": "workspace:^", "@deepseek-ai/dsh-session-persistence-jsonl": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/host/apiproxy/package.json b/packages/host/apiproxy/package.json index 219704e6dd..c6da4ab3ae 100644 --- a/packages/host/apiproxy/package.json +++ b/packages/host/apiproxy/package.json @@ -69,13 +69,13 @@ "@deepseek-ai/dsh-user-approval": "workspace:^", "@deepseek-ai/dsh-user-interaction": "workspace:^", "@deepseek-ai/dsh-workspace": "workspace:^", - "@deepseek-ai/schemastery": "^3.18.0", + "@deepseek-ai/schemastery": "workspace:^", "zod": "^4.4.3" }, "peerDependencies": { - "@deepseek-ai/dsh-agent-presets": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-agent-presets": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-agent-presets": "workspace:^", @@ -84,6 +84,6 @@ "@deepseek-ai/dsh-storage-domain": "workspace:^", "@deepseek-ai/dsh-type-meta": "workspace:^", "@deepseek-ai/dsh-typert-registry": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/host/directory-picker-auto/package.json b/packages/host/directory-picker-auto/package.json index a553fc2c85..bea692eedc 100644 --- a/packages/host/directory-picker-auto/package.json +++ b/packages/host/directory-picker-auto/package.json @@ -32,12 +32,12 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/cordis-plugin-loader": "^1.0.0-rc.5", - "@deepseek-ai/dsh-host-directory-picker-browse": "^0.0.1", - "@deepseek-ai/dsh-host-directory-picker-native": "^0.0.1", - "@deepseek-ai/dsh-host-webserver": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/dsh-host-directory-picker-browse": "workspace:^", + "@deepseek-ai/dsh-host-directory-picker-native": "workspace:^", + "@deepseek-ai/dsh-host-webserver": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/cordis-plugin-include": "workspace:^", @@ -47,6 +47,6 @@ "@deepseek-ai/dsh-host-directory-picker-native": "workspace:^", "@deepseek-ai/dsh-host-webserver": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/host/directory-picker-browse/package.json b/packages/host/directory-picker-browse/package.json index 329e955c54..224f73de29 100644 --- a/packages/host/directory-picker-browse/package.json +++ b/packages/host/directory-picker-browse/package.json @@ -39,16 +39,16 @@ "dependencies": { "@deepseek-ai/dsh-host-directory-picker": "workspace:^", "clsx": "^2.0.0", - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "peerDependencies": { - "@deepseek-ai/dsh-client-locale": "^0.0.1", - "@deepseek-ai/dsh-client-runtime": "^0.0.1", - "@deepseek-ai/dsh-client-ui-primitives": "^0.0.1", - "@deepseek-ai/dsh-client-ui-slots": "^0.0.1", - "@deepseek-ai/dsh-client-ui-workspace": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/dsh-client-locale": "workspace:^", + "@deepseek-ai/dsh-client-runtime": "workspace:^", + "@deepseek-ai/dsh-client-ui-primitives": "workspace:^", + "@deepseek-ai/dsh-client-ui-slots": "workspace:^", + "@deepseek-ai/dsh-client-ui-workspace": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^", "react": "^18.2.0" }, "devDependencies": { @@ -60,7 +60,7 @@ "@deepseek-ai/dsh-client-ui-workspace": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@types/react": "~18.3.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/cordis": "workspace:^", "react": "^18.2.0" }, "dsh": { diff --git a/packages/host/directory-picker-native/package.json b/packages/host/directory-picker-native/package.json index d3000b1e98..acf9278c89 100644 --- a/packages/host/directory-picker-native/package.json +++ b/packages/host/directory-picker-native/package.json @@ -47,11 +47,11 @@ "koffi": "^3.1.0" }, "peerDependencies": { - "@deepseek-ai/dsh-client-runtime": "^0.0.1", - "@deepseek-ai/dsh-client-ui-slots": "^0.0.1", - "@deepseek-ai/dsh-client-ui-workspace": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/dsh-client-runtime": "workspace:^", + "@deepseek-ai/dsh-client-ui-slots": "workspace:^", + "@deepseek-ai/dsh-client-ui-workspace": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^", "react": "^18.2.0" }, "devDependencies": { @@ -60,7 +60,7 @@ "@deepseek-ai/dsh-client-ui-workspace": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@types/react": "~18.3.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/cordis": "workspace:^", "react": "^18.2.0", "tsx": "^4.19.2" }, diff --git a/packages/host/directory-picker/package.json b/packages/host/directory-picker/package.json index a8feccefbe..afad024fa2 100644 --- a/packages/host/directory-picker/package.json +++ b/packages/host/directory-picker/package.json @@ -32,11 +32,11 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/host/frontend-static/package.json b/packages/host/frontend-static/package.json index 9da90e8b20..de7ceb9cf2 100644 --- a/packages/host/frontend-static/package.json +++ b/packages/host/frontend-static/package.json @@ -32,17 +32,17 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-host-webserver": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-host-webserver": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/cordis-plugin-loader": "workspace:^", "@deepseek-ai/dsh-host-webserver": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/host/webserver/package.json b/packages/host/webserver/package.json index 0f29d976e6..48378f5ff9 100644 --- a/packages/host/webserver/package.json +++ b/packages/host/webserver/package.json @@ -32,14 +32,14 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/cordis": "^4.0.0-rc.7", - "@deepseek-ai/dsh-invariants": "^0.0.1" + "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/cordis": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^" } } diff --git a/packages/interaction/commands/package.json b/packages/interaction/commands/package.json index 2909fda952..8e527f64be 100644 --- a/packages/interaction/commands/package.json +++ b/packages/interaction/commands/package.json @@ -41,12 +41,12 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-brand": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-scope": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-brand": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-scope": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -54,6 +54,6 @@ "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-scope": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/interaction/permission/package.json b/packages/interaction/permission/package.json index 4ec76c4e16..85c959315d 100644 --- a/packages/interaction/permission/package.json +++ b/packages/interaction/permission/package.json @@ -41,19 +41,19 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-bash": "^0.0.1", - "@deepseek-ai/dsh-commands": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-sandbox": "^0.0.1", - "@deepseek-ai/dsh-sandbox-policy": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-session-projection": "^0.0.1", - "@deepseek-ai/dsh-settings": "^0.0.1", - "@deepseek-ai/dsh-user-approval": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-bash": "workspace:^", + "@deepseek-ai/dsh-commands": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-sandbox": "workspace:^", + "@deepseek-ai/dsh-sandbox-policy": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-session-projection": "workspace:^", + "@deepseek-ai/dsh-settings": "workspace:^", + "@deepseek-ai/dsh-user-approval": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0", + "@deepseek-ai/schemastery": "workspace:^", "zod": "^4.4.3" }, "devDependencies": { @@ -66,6 +66,6 @@ "@deepseek-ai/dsh-session-projection": "workspace:^", "@deepseek-ai/dsh-settings": "workspace:^", "@deepseek-ai/dsh-user-approval": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/interaction/tool-ask-user/package.json b/packages/interaction/tool-ask-user/package.json index 76b103ca04..b0ffe378ee 100644 --- a/packages/interaction/tool-ask-user/package.json +++ b/packages/interaction/tool-ask-user/package.json @@ -32,11 +32,11 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-tools": "^0.0.1", - "@deepseek-ai/dsh-user-interaction": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-tools": "workspace:^", + "@deepseek-ai/dsh-user-interaction": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -45,6 +45,6 @@ "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", "@deepseek-ai/dsh-user-interaction": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/interaction/user-approval/package.json b/packages/interaction/user-approval/package.json index 99f1e82f1f..892dcbcf87 100644 --- a/packages/interaction/user-approval/package.json +++ b/packages/interaction/user-approval/package.json @@ -37,17 +37,17 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-brand": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-scope": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-system-prompt": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-brand": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-scope": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-system-prompt": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -57,6 +57,6 @@ "@deepseek-ai/dsh-scope": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-system-prompt": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/interaction/user-interaction/package.json b/packages/interaction/user-interaction/package.json index 67022c524b..cd0336ae5c 100644 --- a/packages/interaction/user-interaction/package.json +++ b/packages/interaction/user-interaction/package.json @@ -37,15 +37,15 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/llm/llm-deepseek/package.json b/packages/llm/llm-deepseek/package.json index 3bc2702d1b..8baa42f0c9 100644 --- a/packages/llm/llm-deepseek/package.json +++ b/packages/llm/llm-deepseek/package.json @@ -32,17 +32,17 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-credentials": "^0.0.1", - "@deepseek-ai/dsh-environment": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-settings": "^0.0.1", - "@deepseek-ai/dsh-timeout": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-credentials": "workspace:^", + "@deepseek-ai/dsh-environment": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-settings": "workspace:^", + "@deepseek-ai/dsh-timeout": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { "eventsource-parser": "^3.1.0", - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-credentials": "workspace:^", @@ -51,6 +51,6 @@ "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-settings": "workspace:^", "@deepseek-ai/dsh-timeout": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/llm/llm-pi-ai/package.json b/packages/llm/llm-pi-ai/package.json index 06003f4165..5427a26277 100644 --- a/packages/llm/llm-pi-ai/package.json +++ b/packages/llm/llm-pi-ai/package.json @@ -32,18 +32,18 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-attachment": "^0.0.1", - "@deepseek-ai/dsh-credentials": "^0.0.1", - "@deepseek-ai/dsh-environment": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-settings": "^0.0.1", - "@deepseek-ai/dsh-timeout": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-attachment": "workspace:^", + "@deepseek-ai/dsh-credentials": "workspace:^", + "@deepseek-ai/dsh-environment": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-settings": "workspace:^", + "@deepseek-ai/dsh-timeout": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { "@earendil-works/pi-ai": "^0.82.1", - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-attachment": "workspace:^", @@ -54,6 +54,6 @@ "@deepseek-ai/dsh-llm-deepseek": "workspace:^", "@deepseek-ai/dsh-settings": "workspace:^", "@deepseek-ai/dsh-timeout": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/llm/llm-retry/package.json b/packages/llm/llm-retry/package.json index 8baa7e8e5d..556d42abf9 100644 --- a/packages/llm/llm-retry/package.json +++ b/packages/llm/llm-retry/package.json @@ -36,16 +36,16 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-brand": "^0.0.1", - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-timeout": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-brand": "workspace:^", + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-timeout": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-brand": "workspace:^", @@ -64,6 +64,6 @@ "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-timeout": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/llm/llm/package.json b/packages/llm/llm/package.json index 67a45ccf88..9341670dd1 100644 --- a/packages/llm/llm/package.json +++ b/packages/llm/llm/package.json @@ -45,20 +45,20 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-attachment": "^0.0.1", - "@deepseek-ai/dsh-brand": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-timeout": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-attachment": "workspace:^", + "@deepseek-ai/dsh-brand": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-timeout": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-attachment": "workspace:^", "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-timeout": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/llm/token-meter/package.json b/packages/llm/token-meter/package.json index 50762fc86f..0755e6842a 100644 --- a/packages/llm/token-meter/package.json +++ b/packages/llm/token-meter/package.json @@ -37,15 +37,15 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-compact": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-session-projection": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-compact": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-session-projection": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0", + "@deepseek-ai/schemastery": "workspace:^", "zod": "^4.4.3" }, "devDependencies": { @@ -54,6 +54,6 @@ "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-session-projection": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/lsp/lsp-local/package.json b/packages/lsp/lsp-local/package.json index 0a2181c3de..9cdc20a6c7 100644 --- a/packages/lsp/lsp-local/package.json +++ b/packages/lsp/lsp-local/package.json @@ -32,17 +32,17 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-brand": "^0.0.1", - "@deepseek-ai/dsh-fs": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-lsp": "^0.0.1", - "@deepseek-ai/dsh-subprocess": "^0.0.1", - "@deepseek-ai/dsh-timeout": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-brand": "workspace:^", + "@deepseek-ai/dsh-fs": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-lsp": "workspace:^", + "@deepseek-ai/dsh-subprocess": "workspace:^", + "@deepseek-ai/dsh-timeout": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-brand": "workspace:^", @@ -54,7 +54,7 @@ "@deepseek-ai/dsh-subprocess": "workspace:^", "@deepseek-ai/dsh-subprocess-local": "workspace:^", "@deepseek-ai/dsh-timeout": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/cordis": "workspace:^", "typescript": "^6.0.3", "typescript-language-server": "^5.0.0" } diff --git a/packages/lsp/lsp/package.json b/packages/lsp/lsp/package.json index c4a2385665..41b5f12e42 100644 --- a/packages/lsp/lsp/package.json +++ b/packages/lsp/lsp/package.json @@ -32,15 +32,15 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-brand": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-brand": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/lsp/tool-lsp/package.json b/packages/lsp/tool-lsp/package.json index 4a23cffe88..ab5b9603e8 100644 --- a/packages/lsp/tool-lsp/package.json +++ b/packages/lsp/tool-lsp/package.json @@ -32,16 +32,16 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-lsp": "^0.0.1", - "@deepseek-ai/dsh-system-prompt": "^0.0.1", - "@deepseek-ai/dsh-timeout": "^0.0.1", - "@deepseek-ai/dsh-tools": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-lsp": "workspace:^", + "@deepseek-ai/dsh-system-prompt": "workspace:^", + "@deepseek-ai/dsh-timeout": "workspace:^", + "@deepseek-ai/dsh-tools": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -56,6 +56,6 @@ "@deepseek-ai/dsh-timeout": "workspace:^", "@deepseek-ai/dsh-timeout-policy": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/mcp/mcp-client/package.json b/packages/mcp/mcp-client/package.json index a7f3fc3b90..1a12f7c674 100644 --- a/packages/mcp/mcp-client/package.json +++ b/packages/mcp/mcp-client/package.json @@ -32,15 +32,15 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-subprocess": "^0.0.1", - "@deepseek-ai/dsh-tools": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-subprocess": "workspace:^", + "@deepseek-ai/dsh-tools": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { "@modelcontextprotocol/sdk": "^1.12.0", - "@deepseek-ai/schemastery": "^3.18.0", + "@deepseek-ai/schemastery": "workspace:^", "zod": "^4.4.3" }, "devDependencies": { @@ -50,6 +50,6 @@ "@deepseek-ai/dsh-tools": "workspace:^", "@modelcontextprotocol/server-everything": "^2026.7.4", "@modelcontextprotocol/server-filesystem": "^2026.7.4", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/plan/plan-mode/package.json b/packages/plan/plan-mode/package.json index 1c8b81cc30..c8c228e00a 100644 --- a/packages/plan/plan-mode/package.json +++ b/packages/plan/plan-mode/package.json @@ -41,16 +41,16 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-commands": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-session-projection": "^0.0.1", - "@deepseek-ai/dsh-system-prompt": "^0.0.1", - "@deepseek-ai/dsh-tools": "^0.0.1", - "@deepseek-ai/dsh-user-interaction": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-commands": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-session-projection": "workspace:^", + "@deepseek-ai/dsh-system-prompt": "workspace:^", + "@deepseek-ai/dsh-tools": "workspace:^", + "@deepseek-ai/dsh-user-interaction": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "peerDependenciesMeta": { "@deepseek-ai/dsh-commands": { @@ -72,6 +72,6 @@ "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", "@deepseek-ai/dsh-user-interaction": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/preset/agent-presets/package.json b/packages/preset/agent-presets/package.json index 00a8318ad0..c5fc5eb165 100644 --- a/packages/preset/agent-presets/package.json +++ b/packages/preset/agent-presets/package.json @@ -32,19 +32,19 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/cordis-plugin-include": "^1.0.4", - "@deepseek-ai/cordis-plugin-loader": "^1.0.0-rc.5", - "@deepseek-ai/dsh-atomic-write": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-paths": "^0.0.1", - "@deepseek-ai/dsh-scope": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-settings": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis-plugin-include": "workspace:^", + "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/dsh-atomic-write": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-paths": "workspace:^", + "@deepseek-ai/dsh-scope": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-settings": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { "js-yaml": "^4.1.0", - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/cordis-plugin-include": "workspace:^", @@ -61,6 +61,6 @@ "@deepseek-ai/dsh-settings-local": "workspace:^", "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/preset/persona/package.json b/packages/preset/persona/package.json index 193a9cb45e..db3121cdaa 100644 --- a/packages/preset/persona/package.json +++ b/packages/preset/persona/package.json @@ -32,17 +32,17 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-system-prompt": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-system-prompt": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-scope": "workspace:^", "@deepseek-ai/dsh-system-prompt": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/pty/pty-local/package.json b/packages/pty/pty-local/package.json index 9aad0c1502..f7f84504bd 100644 --- a/packages/pty/pty-local/package.json +++ b/packages/pty/pty-local/package.json @@ -32,17 +32,17 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-pty": "^0.0.1", - "@deepseek-ai/dsh-sandbox": "^0.0.1", - "@deepseek-ai/dsh-sandbox-policy": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-subprocess": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-pty": "workspace:^", + "@deepseek-ai/dsh-sandbox": "workspace:^", + "@deepseek-ai/dsh-sandbox-policy": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-subprocess": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -53,6 +53,6 @@ "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-subprocess": "workspace:^", "@deepseek-ai/dsh-subprocess-local": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/pty/pty/package.json b/packages/pty/pty/package.json index 75f3b33302..ad874ee876 100644 --- a/packages/pty/pty/package.json +++ b/packages/pty/pty/package.json @@ -32,16 +32,16 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-brand": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-brand": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/pty/tool-bash-persistent/package.json b/packages/pty/tool-bash-persistent/package.json index 34d95c6f78..25f248e047 100644 --- a/packages/pty/tool-bash-persistent/package.json +++ b/packages/pty/tool-bash-persistent/package.json @@ -31,15 +31,15 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-pty": "^0.0.1", - "@deepseek-ai/dsh-timeout": "^0.0.1", - "@deepseek-ai/dsh-tools": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-pty": "workspace:^", + "@deepseek-ai/dsh-timeout": "workspace:^", + "@deepseek-ai/dsh-tools": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/cordis-plugin-include": "workspace:^", @@ -56,6 +56,6 @@ "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-timeout": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/pty/tool-pty/package.json b/packages/pty/tool-pty/package.json index 2db01c4416..c60acc3572 100644 --- a/packages/pty/tool-pty/package.json +++ b/packages/pty/tool-pty/package.json @@ -32,18 +32,18 @@ ], "license": "BSD-3-Clause", "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "peerDependencies": { - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-pty": "^0.0.1", - "@deepseek-ai/dsh-retention": "^0.0.1", - "@deepseek-ai/dsh-system-prompt": "^0.0.1", - "@deepseek-ai/dsh-tasks": "^0.0.1", - "@deepseek-ai/dsh-tools": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-pty": "workspace:^", + "@deepseek-ai/dsh-retention": "workspace:^", + "@deepseek-ai/dsh-system-prompt": "workspace:^", + "@deepseek-ai/dsh-tasks": "workspace:^", + "@deepseek-ai/dsh-tools": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/cordis-plugin-include": "workspace:^", @@ -63,6 +63,6 @@ "@deepseek-ai/dsh-tasks-local": "workspace:^", "@deepseek-ai/dsh-tool-tasks": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/sandbox/sandbox-local/package.json b/packages/sandbox/sandbox-local/package.json index c68cd8532a..52a2801b7b 100644 --- a/packages/sandbox/sandbox-local/package.json +++ b/packages/sandbox/sandbox-local/package.json @@ -32,22 +32,22 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-sandbox": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-sandbox": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { "@deepseek-ai/dsh-sandbox-windows-acl": "workspace:^", "@deepseek-ai/node-addon-landlock-run": "workspace:*", - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-sandbox": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/sandbox/sandbox-policy/package.json b/packages/sandbox/sandbox-policy/package.json index d90befdd9e..9aaf77e59f 100644 --- a/packages/sandbox/sandbox-policy/package.json +++ b/packages/sandbox/sandbox-policy/package.json @@ -32,15 +32,15 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-sandbox": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-system-prompt": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-sandbox": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-system-prompt": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -48,6 +48,6 @@ "@deepseek-ai/dsh-sandbox": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-system-prompt": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/sandbox/sandbox-windows-acl/package.json b/packages/sandbox/sandbox-windows-acl/package.json index 6d8d9c722b..a59898ea86 100644 --- a/packages/sandbox/sandbox-windows-acl/package.json +++ b/packages/sandbox/sandbox-windows-acl/package.json @@ -38,8 +38,8 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { "koffi": "^3.1.0" @@ -48,6 +48,6 @@ "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-pwsh-local": "workspace:^", "@deepseek-ai/dsh-sandbox-local": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/sandbox/sandbox/package.json b/packages/sandbox/sandbox/package.json index 9fc9f8a460..057920ce44 100644 --- a/packages/sandbox/sandbox/package.json +++ b/packages/sandbox/sandbox/package.json @@ -32,15 +32,15 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/scaffold/client/package.json b/packages/scaffold/client/package.json index 227e00a1ab..41786be068 100644 --- a/packages/scaffold/client/package.json +++ b/packages/scaffold/client/package.json @@ -31,17 +31,17 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-sdk-protocol": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-sdk-protocol": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-sdk-protocol": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/scaffold/create-sdk/package.json b/packages/scaffold/create-sdk/package.json index e61b645303..3f4395eed7 100644 --- a/packages/scaffold/create-sdk/package.json +++ b/packages/scaffold/create-sdk/package.json @@ -39,11 +39,11 @@ "commander": "^15.0.0" }, "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/scaffold/helper/package.json b/packages/scaffold/helper/package.json index 0266daaba1..d79661c0ea 100644 --- a/packages/scaffold/helper/package.json +++ b/packages/scaffold/helper/package.json @@ -38,10 +38,10 @@ "yaml": "^2.9.0" }, "peerDependencies": { - "@deepseek-ai/dsh-brand": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-subprocess": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-brand": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-subprocess": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-brand": "workspace:^", @@ -54,6 +54,6 @@ "@deepseek-ai/dsh-tool-subagent": "workspace:^", "@deepseek-ai/dsh-tool-todo": "workspace:^", "@deepseek-ai/dsh-tool-web": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/scaffold/protocol/package.json b/packages/scaffold/protocol/package.json index feb8784a6d..7fc86b5fc3 100644 --- a/packages/scaffold/protocol/package.json +++ b/packages/scaffold/protocol/package.json @@ -31,17 +31,17 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-subagent": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-subagent": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-subagent": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/scaffold/scripts/package.json b/packages/scaffold/scripts/package.json index e24969d78d..20fd286b50 100644 --- a/packages/scaffold/scripts/package.json +++ b/packages/scaffold/scripts/package.json @@ -48,8 +48,8 @@ }, "peerDependencies": { "@deepseek-ai/dsh-app-boot": "workspace:^", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^", "tsdown": "^0.22.2", "tsx": "^4.22.4" }, @@ -64,7 +64,7 @@ "devDependencies": { "@deepseek-ai/dsh-app-boot": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/cordis": "workspace:^", "tsdown": "^0.22.2", "tsx": "^4.22.4" } diff --git a/packages/scaffold/server/package.json b/packages/scaffold/server/package.json index 6911f4b117..237ce06ecc 100644 --- a/packages/scaffold/server/package.json +++ b/packages/scaffold/server/package.json @@ -32,18 +32,18 @@ ], "license": "BSD-3-Clause", "dependencies": { - "@deepseek-ai/schemastery": "^3.17.0" + "@deepseek-ai/schemastery": "workspace:^" }, "peerDependencies": { - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-llm-deepseek": "^0.0.1", - "@deepseek-ai/dsh-scope": "^0.0.1", - "@deepseek-ai/dsh-sdk-protocol": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-subagent": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-llm-deepseek": "workspace:^", + "@deepseek-ai/dsh-scope": "workspace:^", + "@deepseek-ai/dsh-sdk-protocol": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-subagent": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/cordis-plugin-loader": "workspace:^", @@ -57,6 +57,6 @@ "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-session-persistence-jsonl": "workspace:^", "@deepseek-ai/dsh-subagent": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/scaffold/telemetry/package.json b/packages/scaffold/telemetry/package.json index 419d8f9ed1..50c501cd51 100644 --- a/packages/scaffold/telemetry/package.json +++ b/packages/scaffold/telemetry/package.json @@ -35,15 +35,15 @@ "yaml": "^2.9.0" }, "peerDependencies": { - "@deepseek-ai/dsh-brand": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-paths": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-brand": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-paths": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-paths": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/self-modification/tool-cordis/package.json b/packages/self-modification/tool-cordis/package.json index 1fc3fcebb1..ed0f466b62 100644 --- a/packages/self-modification/tool-cordis/package.json +++ b/packages/self-modification/tool-cordis/package.json @@ -32,16 +32,16 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-scope": "^0.0.1", - "@deepseek-ai/dsh-tools": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-scope": "workspace:^", + "@deepseek-ai/dsh-tools": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { - "@deepseek-ai/cordis-plugin-loader": "^1.0.0-rc.5", + "@deepseek-ai/cordis-plugin-loader": "workspace:^", "@deepseek-ai/cordis-plugin-timer": "workspace:^", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-agent-loop": "workspace:^", @@ -52,6 +52,6 @@ "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/session-query/session-query-sqlite/package.json b/packages/session-query/session-query-sqlite/package.json index a54c9e0e1b..9a799bf167 100644 --- a/packages/session-query/session-query-sqlite/package.json +++ b/packages/session-query/session-query-sqlite/package.json @@ -32,11 +32,11 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-session-persistence": "^0.0.1", - "@deepseek-ai/dsh-session-query": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-session-persistence": "workspace:^", + "@deepseek-ai/dsh-session-query": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "peerDependenciesMeta": { "@deepseek-ai/dsh-session-persistence": { @@ -44,7 +44,7 @@ } }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/cordis-plugin-loader": "workspace:^", @@ -53,6 +53,6 @@ "@deepseek-ai/dsh-session-persistence": "workspace:^", "@deepseek-ai/dsh-session-persistence-sqlite": "workspace:^", "@deepseek-ai/dsh-session-query": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/session-query/session-query/package.json b/packages/session-query/session-query/package.json index cdd3d740f5..6f19563c7b 100644 --- a/packages/session-query/session-query/package.json +++ b/packages/session-query/session-query/package.json @@ -32,13 +32,13 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-brand": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-session-title": "^0.0.1", - "@deepseek-ai/dsh-session-persistence": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-brand": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-session-title": "workspace:^", + "@deepseek-ai/dsh-session-persistence": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "peerDependenciesMeta": { "@deepseek-ai/dsh-session-persistence": { @@ -52,6 +52,6 @@ "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-session-title": "workspace:^", "@deepseek-ai/dsh-session-persistence": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/session-query/tool-session-query/package.json b/packages/session-query/tool-session-query/package.json index 0da248f48a..71afb52687 100644 --- a/packages/session-query/tool-session-query/package.json +++ b/packages/session-query/tool-session-query/package.json @@ -32,17 +32,17 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-session-query": "^0.0.1", - "@deepseek-ai/dsh-system-prompt": "^0.0.1", - "@deepseek-ai/dsh-timeout": "^0.0.1", - "@deepseek-ai/dsh-tools": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-session-query": "workspace:^", + "@deepseek-ai/dsh-system-prompt": "workspace:^", + "@deepseek-ai/dsh-timeout": "workspace:^", + "@deepseek-ai/dsh-tools": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -58,6 +58,6 @@ "@deepseek-ai/dsh-timeout": "workspace:^", "@deepseek-ai/dsh-timeout-policy": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/session/session-checkpoint-policy/package.json b/packages/session/session-checkpoint-policy/package.json index 8a5766641f..1151cf1a9c 100644 --- a/packages/session/session-checkpoint-policy/package.json +++ b/packages/session/session-checkpoint-policy/package.json @@ -32,13 +32,13 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-session-persistence": "^0.0.1", - "@deepseek-ai/dsh-tools": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-session-persistence": "workspace:^", + "@deepseek-ai/dsh-tools": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/cordis-plugin-loader": "workspace:^", @@ -52,6 +52,6 @@ "@deepseek-ai/dsh-session-persistence-jsonl": "workspace:^", "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/session/session-persistence-jsonl/package.json b/packages/session/session-persistence-jsonl/package.json index 6bc752ed0f..38d6cfba97 100644 --- a/packages/session/session-persistence-jsonl/package.json +++ b/packages/session/session-persistence-jsonl/package.json @@ -32,19 +32,19 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-session-persistence": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-session-persistence": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { "koffi": "^3.1.0", - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-session-persistence": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/session/session-persistence-sqlite/package.json b/packages/session/session-persistence-sqlite/package.json index 8d6f05cbd8..f52fdc6bca 100644 --- a/packages/session/session-persistence-sqlite/package.json +++ b/packages/session/session-persistence-sqlite/package.json @@ -32,18 +32,18 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-session-persistence": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-session-persistence": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-session-persistence": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/session/session-persistence/package.json b/packages/session/session-persistence/package.json index d556ebff73..8430c7c91a 100644 --- a/packages/session/session-persistence/package.json +++ b/packages/session/session-persistence/package.json @@ -32,11 +32,11 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-brand": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-timeout": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-brand": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-timeout": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-brand": "workspace:^", @@ -44,6 +44,6 @@ "@deepseek-ai/dsh-scope": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-timeout": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/session/session-projection-cache/package.json b/packages/session/session-projection-cache/package.json index 885c293dc9..cbc40eebe0 100644 --- a/packages/session/session-projection-cache/package.json +++ b/packages/session/session-projection-cache/package.json @@ -32,16 +32,16 @@ ], "license": "BSD-3-Clause", "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0", + "@deepseek-ai/schemastery": "workspace:^", "zod": "^4.4.3" }, "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-session-persistence": "^0.0.1", - "@deepseek-ai/dsh-session-projection": "^0.0.1", - "@deepseek-ai/dsh-storage-domain": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-session-persistence": "workspace:^", + "@deepseek-ai/dsh-session-projection": "workspace:^", + "@deepseek-ai/dsh-storage-domain": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", @@ -50,6 +50,6 @@ "@deepseek-ai/dsh-session-projection": "workspace:^", "@deepseek-ai/dsh-storage": "workspace:^", "@deepseek-ai/dsh-storage-domain": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/session/session-projection/package.json b/packages/session/session-projection/package.json index d17884eadb..4d7a438fae 100644 --- a/packages/session/session-projection/package.json +++ b/packages/session/session-projection/package.json @@ -40,13 +40,13 @@ "zod": "^4.4.3" }, "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/session/session-telemetry-otel/package.json b/packages/session/session-telemetry-otel/package.json index 569e62e70b..0d2a88bc6a 100644 --- a/packages/session/session-telemetry-otel/package.json +++ b/packages/session/session-telemetry-otel/package.json @@ -38,16 +38,16 @@ "@opentelemetry/otlp-exporter-base": "^0.220.0", "@opentelemetry/resources": "^2.9.0", "@opentelemetry/sdk-logs": "^0.220.0", - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "peerDependencies": { - "@deepseek-ai/dsh-command-feedback": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-session-telemetry": "^0.0.1", - "@deepseek-ai/dsh-user-id": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-command-feedback": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-session-telemetry": "workspace:^", + "@deepseek-ai/dsh-user-id": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/cordis-plugin-loader": "workspace:^", @@ -57,6 +57,6 @@ "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-session-telemetry": "workspace:^", "@deepseek-ai/dsh-user-id": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/session/session-telemetry/package.json b/packages/session/session-telemetry/package.json index d9ac09b6b7..613d1f6ac3 100644 --- a/packages/session/session-telemetry/package.json +++ b/packages/session/session-telemetry/package.json @@ -32,15 +32,15 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/session/session-title-all-messages-llm/package.json b/packages/session/session-title-all-messages-llm/package.json index ecd82f5f72..c406342a9f 100644 --- a/packages/session/session-title-all-messages-llm/package.json +++ b/packages/session/session-title-all-messages-llm/package.json @@ -27,15 +27,15 @@ "files": ["lib/index.js", "lib/invariant.js", "lib/types/**/*.d.ts"], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-session-title": "^0.0.1", - "@deepseek-ai/dsh-session-title-llm": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-session-title": "workspace:^", + "@deepseek-ai/dsh-session-title-llm": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", @@ -43,6 +43,6 @@ "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-session-title": "workspace:^", "@deepseek-ai/dsh-session-title-llm": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/session/session-title-first-message-llm/package.json b/packages/session/session-title-first-message-llm/package.json index 88e8ddb1ca..a75f220053 100644 --- a/packages/session/session-title-first-message-llm/package.json +++ b/packages/session/session-title-first-message-llm/package.json @@ -27,15 +27,15 @@ "files": ["lib/index.js", "lib/invariant.js", "lib/types/**/*.d.ts"], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-session-title": "^0.0.1", - "@deepseek-ai/dsh-session-title-llm": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-session-title": "workspace:^", + "@deepseek-ai/dsh-session-title-llm": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/cordis-plugin-include": "workspace:^", @@ -46,6 +46,6 @@ "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-session-title": "workspace:^", "@deepseek-ai/dsh-session-title-llm": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/session/session-title-llm/package.json b/packages/session/session-title-llm/package.json index 7b2c4caacd..062eca9259 100644 --- a/packages/session/session-title-llm/package.json +++ b/packages/session/session-title-llm/package.json @@ -32,15 +32,15 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-session-title": "^0.0.1", - "@deepseek-ai/dsh-timeout": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-session-title": "workspace:^", + "@deepseek-ai/dsh-timeout": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", @@ -48,6 +48,6 @@ "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-session-title": "workspace:^", "@deepseek-ai/dsh-timeout": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/session/session-title/package.json b/packages/session/session-title/package.json index 84a3b8caaf..e0239f185b 100644 --- a/packages/session/session-title/package.json +++ b/packages/session/session-title/package.json @@ -41,15 +41,15 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-brand": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-session-projection": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-brand": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-session-projection": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0", + "@deepseek-ai/schemastery": "workspace:^", "zod": "^4.4.3" }, "devDependencies": { @@ -60,6 +60,6 @@ "@deepseek-ai/dsh-session-persistence-jsonl": "workspace:^", "@deepseek-ai/dsh-session-persistence-sqlite": "workspace:^", "@deepseek-ai/dsh-session-projection": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/session/user-id/package.json b/packages/session/user-id/package.json index fe733ccfd0..36046b5b58 100644 --- a/packages/session/user-id/package.json +++ b/packages/session/user-id/package.json @@ -32,15 +32,15 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-brand": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-paths": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-brand": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-paths": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-paths": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/settings/settings-local/package.json b/packages/settings/settings-local/package.json index c66e51274d..0f5bca31f3 100644 --- a/packages/settings/settings-local/package.json +++ b/packages/settings/settings-local/package.json @@ -32,15 +32,15 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-atomic-write": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-paths": "^0.0.1", - "@deepseek-ai/dsh-settings": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-atomic-write": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-paths": "workspace:^", + "@deepseek-ai/dsh-settings": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { "chokidar": "^4.0.3", - "@deepseek-ai/schemastery": "^3.18.0", + "@deepseek-ai/schemastery": "workspace:^", "yaml": "^2.9.0" }, "devDependencies": { @@ -48,6 +48,6 @@ "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-paths": "workspace:^", "@deepseek-ai/dsh-settings": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/settings/settings/package.json b/packages/settings/settings/package.json index da6a1cccc0..568a8fba58 100644 --- a/packages/settings/settings/package.json +++ b/packages/settings/settings/package.json @@ -32,15 +32,15 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-brand": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7", - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/dsh-brand": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7", - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/schemastery": "workspace:^" } } diff --git a/packages/skill/skill-badge/package.json b/packages/skill/skill-badge/package.json index 5b23d44f9c..eb55678529 100644 --- a/packages/skill/skill-badge/package.json +++ b/packages/skill/skill-badge/package.json @@ -32,13 +32,13 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-skill": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-skill": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-skill": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/skill/skill-local/package.json b/packages/skill/skill-local/package.json index 1cec60bf92..386da9386b 100644 --- a/packages/skill/skill-local/package.json +++ b/packages/skill/skill-local/package.json @@ -32,15 +32,15 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-fs": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-paths": "^0.0.1", - "@deepseek-ai/dsh-skill": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-fs": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-paths": "workspace:^", + "@deepseek-ai/dsh-skill": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { "chokidar": "^5.0.0", - "@deepseek-ai/schemastery": "^3.18.0", + "@deepseek-ai/schemastery": "workspace:^", "yaml": "^2.4.2" }, "devDependencies": { @@ -48,6 +48,6 @@ "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-paths": "workspace:^", "@deepseek-ai/dsh-skill": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/skill/skill/package.json b/packages/skill/skill/package.json index 921adf7632..b546ae9c60 100644 --- a/packages/skill/skill/package.json +++ b/packages/skill/skill/package.json @@ -32,18 +32,18 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-scope": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-scope": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-scope": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/skill/tool-skill/package.json b/packages/skill/tool-skill/package.json index 25e0f9b2c9..f1315b47cf 100644 --- a/packages/skill/tool-skill/package.json +++ b/packages/skill/tool-skill/package.json @@ -32,15 +32,15 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-skill": "^0.0.1", - "@deepseek-ai/dsh-tools": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-skill": "workspace:^", + "@deepseek-ai/dsh-tools": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -51,6 +51,6 @@ "@deepseek-ai/dsh-skill": "workspace:^", "@deepseek-ai/dsh-skill-local": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/spill/spill-local/package.json b/packages/spill/spill-local/package.json index 7dd63ce56a..43f1bfcfeb 100644 --- a/packages/spill/spill-local/package.json +++ b/packages/spill/spill-local/package.json @@ -32,12 +32,12 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-spill": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.6" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-spill": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-brand": "workspace:^", @@ -45,6 +45,6 @@ "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-spill": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.6" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/spill/spill-policy/package.json b/packages/spill/spill-policy/package.json index f425208b8d..8236e9104a 100644 --- a/packages/spill/spill-policy/package.json +++ b/packages/spill/spill-policy/package.json @@ -32,16 +32,16 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-retention": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-spill": "^0.0.1", - "@deepseek-ai/dsh-tools": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.6" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-retention": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-spill": "workspace:^", + "@deepseek-ai/dsh-tools": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -52,6 +52,6 @@ "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-spill": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.6" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/spill/spill/package.json b/packages/spill/spill/package.json index 9340d28a37..48a21f52c9 100644 --- a/packages/spill/spill/package.json +++ b/packages/spill/spill/package.json @@ -32,17 +32,17 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-brand": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.6" + "@deepseek-ai/dsh-brand": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.6" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/storage/storage-domain/package.json b/packages/storage/storage-domain/package.json index 5c6f8836f0..9c3acd2ba7 100644 --- a/packages/storage/storage-domain/package.json +++ b/packages/storage/storage-domain/package.json @@ -32,17 +32,17 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-storage": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-storage": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0", + "@deepseek-ai/schemastery": "workspace:^", "zod": "^4.4.3" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-storage": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/storage/storage-json/package.json b/packages/storage/storage-json/package.json index 73d8ed9e74..86ec3dc5b8 100644 --- a/packages/storage/storage-json/package.json +++ b/packages/storage/storage-json/package.json @@ -32,16 +32,16 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-storage": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-storage": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-storage": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/storage/storage-sqlite/package.json b/packages/storage/storage-sqlite/package.json index 4ad22a7946..b30e80b5e7 100644 --- a/packages/storage/storage-sqlite/package.json +++ b/packages/storage/storage-sqlite/package.json @@ -32,16 +32,16 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-storage": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-storage": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-storage": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/storage/storage/package.json b/packages/storage/storage/package.json index b638d392e0..efe8294de3 100644 --- a/packages/storage/storage/package.json +++ b/packages/storage/storage/package.json @@ -32,11 +32,11 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/subagent/subagent-acp/package.json b/packages/subagent/subagent-acp/package.json index 155e89ced1..62a648e3d5 100644 --- a/packages/subagent/subagent-acp/package.json +++ b/packages/subagent/subagent-acp/package.json @@ -32,21 +32,21 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-subagent": "^0.0.1", - "@deepseek-ai/dsh-subprocess": "^0.0.1", - "@deepseek-ai/dsh-timeout": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-subagent": "workspace:^", + "@deepseek-ai/dsh-subprocess": "workspace:^", + "@deepseek-ai/dsh-timeout": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { "@agentclientprotocol/sdk": "0.25.1", - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { - "@deepseek-ai/cordis-plugin-loader": "^1.0.0-rc.5", + "@deepseek-ai/cordis-plugin-loader": "workspace:^", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", @@ -56,6 +56,6 @@ "@deepseek-ai/dsh-subprocess": "workspace:^", "@deepseek-ai/dsh-subprocess-local": "workspace:^", "@deepseek-ai/dsh-timeout": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/subagent/subagent-claude-code/package.json b/packages/subagent/subagent-claude-code/package.json index 758d30435c..22876aa0ca 100644 --- a/packages/subagent/subagent-claude-code/package.json +++ b/packages/subagent/subagent-claude-code/package.json @@ -32,18 +32,18 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-subagent": "^0.0.1", - "@deepseek-ai/dsh-subprocess": "^0.0.1", - "@deepseek-ai/dsh-timeout": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-subagent": "workspace:^", + "@deepseek-ai/dsh-subprocess": "workspace:^", + "@deepseek-ai/dsh-timeout": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { "@anthropic-ai/sdk": "0.93.0", "@anthropic-ai/claude-agent-sdk": "0.3.220", - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -55,6 +55,6 @@ "@deepseek-ai/dsh-subprocess": "workspace:^", "@deepseek-ai/dsh-subprocess-local": "workspace:^", "@deepseek-ai/dsh-timeout": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/subagent/subagent-codex/package.json b/packages/subagent/subagent-codex/package.json index e44de3fa75..d22b5c517f 100644 --- a/packages/subagent/subagent-codex/package.json +++ b/packages/subagent/subagent-codex/package.json @@ -32,20 +32,20 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-sdk-protocol": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-subagent": "^0.0.1", - "@deepseek-ai/dsh-subprocess": "^0.0.1", - "@deepseek-ai/dsh-timeout": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-sdk-protocol": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-subagent": "workspace:^", + "@deepseek-ai/dsh-subprocess": "workspace:^", + "@deepseek-ai/dsh-timeout": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { - "@deepseek-ai/cordis-plugin-loader": "^1.0.0-rc.5", + "@deepseek-ai/cordis-plugin-loader": "workspace:^", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", @@ -57,6 +57,6 @@ "@deepseek-ai/dsh-subprocess-local": "workspace:^", "@deepseek-ai/dsh-timeout": "workspace:^", "@openai/codex": "0.147.0", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/subagent/subagent-dsh-sdk/package.json b/packages/subagent/subagent-dsh-sdk/package.json index 22d66af4bd..d6cc3a3eef 100644 --- a/packages/subagent/subagent-dsh-sdk/package.json +++ b/packages/subagent/subagent-dsh-sdk/package.json @@ -32,20 +32,20 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-sdk-client": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-subagent": "^0.0.1", - "@deepseek-ai/dsh-subprocess": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-sdk-client": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-subagent": "workspace:^", + "@deepseek-ai/dsh-subprocess": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { - "@deepseek-ai/cordis-plugin-loader": "^1.0.0-rc.5", + "@deepseek-ai/cordis-plugin-loader": "workspace:^", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", @@ -55,6 +55,6 @@ "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-subagent": "workspace:^", "@deepseek-ai/dsh-subprocess": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/subagent/subagent-fork/package.json b/packages/subagent/subagent-fork/package.json index c0abf8ab3f..08515ea47b 100644 --- a/packages/subagent/subagent-fork/package.json +++ b/packages/subagent/subagent-fork/package.json @@ -32,18 +32,18 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-subagent": "^0.0.1", - "@deepseek-ai/dsh-subagent-inprocess": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-subagent": "workspace:^", + "@deepseek-ai/dsh-subagent-inprocess": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { - "@deepseek-ai/cordis-plugin-loader": "^1.0.0-rc.5", + "@deepseek-ai/cordis-plugin-loader": "workspace:^", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-agent-loop": "workspace:^", "@deepseek-ai/dsh-agent-loop-testkit": "workspace:^", @@ -53,6 +53,6 @@ "@deepseek-ai/dsh-subagent": "workspace:^", "@deepseek-ai/dsh-subagent-inprocess": "workspace:^", "@deepseek-ai/dsh-subagent-spawn": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/subagent/subagent-inprocess/package.json b/packages/subagent/subagent-inprocess/package.json index 09fe807748..8bf3d7a8ca 100644 --- a/packages/subagent/subagent-inprocess/package.json +++ b/packages/subagent/subagent-inprocess/package.json @@ -32,18 +32,18 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-subagent": "^0.0.1", - "@deepseek-ai/dsh-system-prompt": "^0.0.1", - "@deepseek-ai/dsh-tools": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-subagent": "workspace:^", + "@deepseek-ai/dsh-system-prompt": "workspace:^", + "@deepseek-ai/dsh-tools": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { - "@deepseek-ai/cordis-plugin-include": "^1.0.4", - "@deepseek-ai/cordis-plugin-loader": "^1.0.0-rc.5", + "@deepseek-ai/cordis-plugin-include": "workspace:^", + "@deepseek-ai/cordis-plugin-loader": "workspace:^", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-agent-loop": "workspace:^", "@deepseek-ai/dsh-agent-loop-testkit": "workspace:^", @@ -58,6 +58,6 @@ "@deepseek-ai/dsh-tool-fs": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", "@deepseek-ai/dsh-user-approval": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/subagent/subagent-spawn/package.json b/packages/subagent/subagent-spawn/package.json index c865aa5251..a45bc78143 100644 --- a/packages/subagent/subagent-spawn/package.json +++ b/packages/subagent/subagent-spawn/package.json @@ -32,16 +32,16 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-subagent": "^0.0.1", - "@deepseek-ai/dsh-subagent-inprocess": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-subagent": "workspace:^", + "@deepseek-ai/dsh-subagent-inprocess": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { - "@deepseek-ai/cordis-plugin-loader": "^1.0.0-rc.5", + "@deepseek-ai/cordis-plugin-loader": "workspace:^", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-agent-loop": "workspace:^", "@deepseek-ai/dsh-agent-loop-testkit": "workspace:^", @@ -55,6 +55,6 @@ "@deepseek-ai/dsh-subagent-inprocess": "workspace:^", "@deepseek-ai/dsh-tool-bash": "workspace:^", "@deepseek-ai/dsh-tool-subagent": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/subagent/subagent/package.json b/packages/subagent/subagent/package.json index 070fe2c8cb..4be1d4d947 100644 --- a/packages/subagent/subagent/package.json +++ b/packages/subagent/subagent/package.json @@ -40,22 +40,22 @@ "zod": "^4.4.3" }, "peerDependencies": { - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-agent-presets": "^0.0.1", - "@deepseek-ai/dsh-brand": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-sandbox": "^0.0.1", - "@deepseek-ai/dsh-sandbox-policy": "^0.0.1", - "@deepseek-ai/dsh-scope": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-session-persistence": "^0.0.1", - "@deepseek-ai/dsh-session-projection": "^0.0.1", - "@deepseek-ai/dsh-session-projection-cache": "^0.0.1", - "@deepseek-ai/dsh-tasks": "^0.0.1", - "@deepseek-ai/dsh-tools": "^0.0.1", - "@deepseek-ai/dsh-user-approval": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-agent-presets": "workspace:^", + "@deepseek-ai/dsh-brand": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-sandbox": "workspace:^", + "@deepseek-ai/dsh-sandbox-policy": "workspace:^", + "@deepseek-ai/dsh-scope": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-session-persistence": "workspace:^", + "@deepseek-ai/dsh-session-projection": "workspace:^", + "@deepseek-ai/dsh-session-projection-cache": "workspace:^", + "@deepseek-ai/dsh-tasks": "workspace:^", + "@deepseek-ai/dsh-tools": "workspace:^", + "@deepseek-ai/dsh-user-approval": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "peerDependenciesMeta": { "@deepseek-ai/dsh-agent-presets": { @@ -101,6 +101,6 @@ "@deepseek-ai/dsh-tasks": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", "@deepseek-ai/dsh-user-approval": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/subagent/tool-subagent-control/package.json b/packages/subagent/tool-subagent-control/package.json index c89d35c727..0184a5af1a 100644 --- a/packages/subagent/tool-subagent-control/package.json +++ b/packages/subagent/tool-subagent-control/package.json @@ -37,12 +37,12 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-subagent": "^0.0.1", - "@deepseek-ai/dsh-tools": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-subagent": "workspace:^", + "@deepseek-ai/dsh-tools": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -57,6 +57,6 @@ "@deepseek-ai/dsh-subagent": "workspace:^", "@deepseek-ai/dsh-subagent-spawn": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/subagent/tool-subagent-report/package.json b/packages/subagent/tool-subagent-report/package.json index 665230bdbd..78adfef325 100644 --- a/packages/subagent/tool-subagent-report/package.json +++ b/packages/subagent/tool-subagent-report/package.json @@ -32,14 +32,14 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-subagent": "^0.0.1", - "@deepseek-ai/dsh-tools": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-subagent": "workspace:^", + "@deepseek-ai/dsh-tools": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -54,6 +54,6 @@ "@deepseek-ai/dsh-subagent-spawn": "workspace:^", "@deepseek-ai/dsh-tool-subagent-control": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/subagent/tool-subagent/package.json b/packages/subagent/tool-subagent/package.json index 5ba14c54b7..6930f5dcc2 100644 --- a/packages/subagent/tool-subagent/package.json +++ b/packages/subagent/tool-subagent/package.json @@ -32,19 +32,19 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-subagent": "^0.0.1", - "@deepseek-ai/dsh-tasks": "^0.0.1", - "@deepseek-ai/dsh-tools": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-subagent": "workspace:^", + "@deepseek-ai/dsh-tasks": "workspace:^", + "@deepseek-ai/dsh-tools": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { - "@deepseek-ai/cordis-plugin-loader": "^1.0.0-rc.5", + "@deepseek-ai/cordis-plugin-loader": "workspace:^", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", @@ -58,6 +58,6 @@ "@deepseek-ai/dsh-tasks-local": "workspace:^", "@deepseek-ai/dsh-tool-tasks": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/subprocess/subprocess-local/package.json b/packages/subprocess/subprocess-local/package.json index a9547a9c48..d307a0742b 100644 --- a/packages/subprocess/subprocess-local/package.json +++ b/packages/subprocess/subprocess-local/package.json @@ -36,10 +36,10 @@ }, "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-subprocess": "^0.0.1", - "@deepseek-ai/dsh-timeout": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-subprocess": "workspace:^", + "@deepseek-ai/dsh-timeout": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { "node-pty": "^1.1.0" @@ -48,6 +48,6 @@ "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-subprocess": "workspace:^", "@deepseek-ai/dsh-timeout": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/subprocess/subprocess/package.json b/packages/subprocess/subprocess/package.json index a1a4e40865..214f5f67a8 100644 --- a/packages/subprocess/subprocess/package.json +++ b/packages/subprocess/subprocess/package.json @@ -32,11 +32,11 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/support/acp-snapshot/package.json b/packages/support/acp-snapshot/package.json index 929ba31708..642565885f 100644 --- a/packages/support/acp-snapshot/package.json +++ b/packages/support/acp-snapshot/package.json @@ -37,13 +37,13 @@ "vitest": "^4.1.8" }, "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/support/agent-loop-testkit/package.json b/packages/support/agent-loop-testkit/package.json index 5ca1382750..0bde847ca9 100644 --- a/packages/support/agent-loop-testkit/package.json +++ b/packages/support/agent-loop-testkit/package.json @@ -32,13 +32,13 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-system-prompt": "^0.0.1", - "@deepseek-ai/dsh-tools": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-system-prompt": "workspace:^", + "@deepseek-ai/dsh-tools": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -48,6 +48,6 @@ "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/support/invariants/package.json b/packages/support/invariants/package.json index 0f1503b835..122ab3dd9f 100644 --- a/packages/support/invariants/package.json +++ b/packages/support/invariants/package.json @@ -32,12 +32,12 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/support/llm-mock-server/package.json b/packages/support/llm-mock-server/package.json index 9f5acda6cb..13456d14e7 100644 --- a/packages/support/llm-mock-server/package.json +++ b/packages/support/llm-mock-server/package.json @@ -32,11 +32,11 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/support/llm-replay/package.json b/packages/support/llm-replay/package.json index d199ea5a4f..326d13bb81 100644 --- a/packages/support/llm-replay/package.json +++ b/packages/support/llm-replay/package.json @@ -32,17 +32,17 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-compact": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-compact": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-compact": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/support/loader-smoke/package.json b/packages/support/loader-smoke/package.json index 0de74f6e60..169bf2f548 100644 --- a/packages/support/loader-smoke/package.json +++ b/packages/support/loader-smoke/package.json @@ -36,17 +36,17 @@ "tsx": "^4.22.4" }, "peerDependencies": { - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.6" + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.6" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/tasks/tasks-local/package.json b/packages/tasks/tasks-local/package.json index aa4673b811..b92cbfe03f 100644 --- a/packages/tasks/tasks-local/package.json +++ b/packages/tasks/tasks-local/package.json @@ -32,12 +32,12 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-scope": "^0.0.1", - "@deepseek-ai/dsh-tasks": "^0.0.1", - "@deepseek-ai/dsh-timeout": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-scope": "workspace:^", + "@deepseek-ai/dsh-tasks": "workspace:^", + "@deepseek-ai/dsh-timeout": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -47,6 +47,6 @@ "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-tasks": "workspace:^", "@deepseek-ai/dsh-timeout": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/tasks/tasks/package.json b/packages/tasks/tasks/package.json index 2e59a68679..5bd6a7e3c1 100644 --- a/packages/tasks/tasks/package.json +++ b/packages/tasks/tasks/package.json @@ -32,17 +32,17 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-brand": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.6" + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-brand": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.6" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/tasks/tool-tasks/package.json b/packages/tasks/tool-tasks/package.json index f55816cc82..69aed7e859 100644 --- a/packages/tasks/tool-tasks/package.json +++ b/packages/tasks/tool-tasks/package.json @@ -32,17 +32,17 @@ ], "license": "BSD-3-Clause", "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "peerDependencies": { - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-retention": "^0.0.1", - "@deepseek-ai/dsh-system-prompt": "^0.0.1", - "@deepseek-ai/dsh-tasks": "^0.0.1", - "@deepseek-ai/dsh-tools": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.6" + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-retention": "workspace:^", + "@deepseek-ai/dsh-system-prompt": "workspace:^", + "@deepseek-ai/dsh-tasks": "workspace:^", + "@deepseek-ai/dsh-tools": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -54,6 +54,6 @@ "@deepseek-ai/dsh-tasks": "workspace:^", "@deepseek-ai/dsh-tasks-local": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.6" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/todo/tool-todo/package.json b/packages/todo/tool-todo/package.json index 3bd9294687..d15d05bb10 100644 --- a/packages/todo/tool-todo/package.json +++ b/packages/todo/tool-todo/package.json @@ -37,16 +37,16 @@ ], "license": "BSD-3-Clause", "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0", + "@deepseek-ai/schemastery": "workspace:^", "zod": "^4.4.3" }, "peerDependencies": { - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-session-projection": "^0.0.1", - "@deepseek-ai/dsh-tools": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-session-projection": "workspace:^", + "@deepseek-ai/dsh-tools": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/cordis-plugin-include": "workspace:^", @@ -62,6 +62,6 @@ "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", "@deepseek-ai/dsh-user-interaction": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/typert/generator/package.json b/packages/typert/generator/package.json index 117f18f48b..f17ce63b8a 100644 --- a/packages/typert/generator/package.json +++ b/packages/typert/generator/package.json @@ -41,14 +41,14 @@ "typescript": "^6.0.3" }, "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-tool-cordis": "workspace:^", "@deepseek-ai/dsh-typert-registry": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/cordis": "workspace:^", "zod": "^4.4.3" } } diff --git a/packages/typert/loader/package.json b/packages/typert/loader/package.json index 4f33f4bc23..7d1baa743a 100644 --- a/packages/typert/loader/package.json +++ b/packages/typert/loader/package.json @@ -32,19 +32,19 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/cordis-plugin-loader": "^1.0.0-rc.5", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-typert-registry": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-typert-registry": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/cordis-plugin-loader": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-typert-registry": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/cordis": "workspace:^", "zod": "^4.4.3" } } diff --git a/packages/typert/registry/package.json b/packages/typert/registry/package.json index 67f2611db1..464415116b 100644 --- a/packages/typert/registry/package.json +++ b/packages/typert/registry/package.json @@ -57,11 +57,11 @@ "zod": "^4.4.3" }, "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/typert/type-meta/package.json b/packages/typert/type-meta/package.json index ae3fb96a2b..e383ba0eec 100644 --- a/packages/typert/type-meta/package.json +++ b/packages/typert/type-meta/package.json @@ -37,11 +37,11 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/util/atomic-write/package.json b/packages/util/atomic-write/package.json index 5556d4ab96..b514058816 100644 --- a/packages/util/atomic-write/package.json +++ b/packages/util/atomic-write/package.json @@ -32,11 +32,11 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/util/brand/package.json b/packages/util/brand/package.json index cdf9307e73..01f33fefe5 100644 --- a/packages/util/brand/package.json +++ b/packages/util/brand/package.json @@ -32,11 +32,11 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/util/environment/package.json b/packages/util/environment/package.json index 7eee1c2b1e..ddc2e40d23 100644 --- a/packages/util/environment/package.json +++ b/packages/util/environment/package.json @@ -32,11 +32,11 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/util/native-command/package.json b/packages/util/native-command/package.json index 81c6c8c771..b3145ee41a 100644 --- a/packages/util/native-command/package.json +++ b/packages/util/native-command/package.json @@ -32,11 +32,11 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/util/paths/package.json b/packages/util/paths/package.json index 2405fc5b65..04d692f56d 100644 --- a/packages/util/paths/package.json +++ b/packages/util/paths/package.json @@ -32,11 +32,11 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.6" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.6" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/util/retention/package.json b/packages/util/retention/package.json index d7eec5489a..7e172bb131 100644 --- a/packages/util/retention/package.json +++ b/packages/util/retention/package.json @@ -32,11 +32,11 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.6" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.6" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/util/timeout/package.json b/packages/util/timeout/package.json index 2404dd13ff..194662100a 100644 --- a/packages/util/timeout/package.json +++ b/packages/util/timeout/package.json @@ -32,11 +32,11 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/web/tool-web/package.json b/packages/web/tool-web/package.json index 2eb44ba59c..c5e1ea2b6b 100644 --- a/packages/web/tool-web/package.json +++ b/packages/web/tool-web/package.json @@ -32,16 +32,16 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-system-prompt": "^0.0.1", - "@deepseek-ai/dsh-tools": "^0.0.1", - "@deepseek-ai/dsh-web": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-system-prompt": "workspace:^", + "@deepseek-ai/dsh-tools": "workspace:^", + "@deepseek-ai/dsh-web": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { "@joplin/turndown-plugin-gfm": "^1.0.67", - "@deepseek-ai/schemastery": "^3.18.0", + "@deepseek-ai/schemastery": "workspace:^", "turndown": "^7.2.4" }, "devDependencies": { @@ -58,6 +58,6 @@ "@deepseek-ai/dsh-web": "workspace:^", "@deepseek-ai/dsh-web-fetch-local": "workspace:^", "@deepseek-ai/dsh-web-search-exa": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/web/web-fetch-local/package.json b/packages/web/web-fetch-local/package.json index 61948fb142..148ecde3e0 100644 --- a/packages/web/web-fetch-local/package.json +++ b/packages/web/web-fetch-local/package.json @@ -32,18 +32,18 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-timeout": "^0.0.1", - "@deepseek-ai/dsh-web": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-timeout": "workspace:^", + "@deepseek-ai/dsh-web": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-timeout": "workspace:^", "@deepseek-ai/dsh-web": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/web/web-search-deepseek/package.json b/packages/web/web-search-deepseek/package.json index bcca1d616a..f3b29d20a4 100644 --- a/packages/web/web-search-deepseek/package.json +++ b/packages/web/web-search-deepseek/package.json @@ -32,16 +32,16 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-credentials": "^0.0.1", - "@deepseek-ai/dsh-environment": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-web": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-credentials": "workspace:^", + "@deepseek-ai/dsh-environment": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-web": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -51,6 +51,6 @@ "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-web": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/web/web-search-exa/package.json b/packages/web/web-search-exa/package.json index 15e907649d..da16ca3fce 100644 --- a/packages/web/web-search-exa/package.json +++ b/packages/web/web-search-exa/package.json @@ -32,18 +32,18 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-environment": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-web": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-environment": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-web": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-environment": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-web": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/web/web-search-perplexity/package.json b/packages/web/web-search-perplexity/package.json index a952c7f83d..1d266f1d13 100644 --- a/packages/web/web-search-perplexity/package.json +++ b/packages/web/web-search-perplexity/package.json @@ -32,18 +32,18 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-environment": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-web": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-environment": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-web": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-environment": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-web": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/web/web/package.json b/packages/web/web/package.json index 6f74c65f2b..d9cf4f5726 100644 --- a/packages/web/web/package.json +++ b/packages/web/web/package.json @@ -32,16 +32,16 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/workflow/tool-ralph/package.json b/packages/workflow/tool-ralph/package.json index 184f656206..341508e3ed 100644 --- a/packages/workflow/tool-ralph/package.json +++ b/packages/workflow/tool-ralph/package.json @@ -32,17 +32,17 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-subagent": "^0.0.1", - "@deepseek-ai/dsh-system-prompt": "^0.0.1", - "@deepseek-ai/dsh-tools": "^0.0.1", - "@deepseek-ai/dsh-workflow": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-subagent": "workspace:^", + "@deepseek-ai/dsh-system-prompt": "workspace:^", + "@deepseek-ai/dsh-tools": "workspace:^", + "@deepseek-ai/dsh-workflow": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/cordis-plugin-loader": "workspace:^", @@ -59,6 +59,6 @@ "@deepseek-ai/dsh-tools": "workspace:^", "@deepseek-ai/dsh-workflow": "workspace:^", "@deepseek-ai/dsh-workflow-workerthread": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/workflow/tool-workflow/package.json b/packages/workflow/tool-workflow/package.json index 125df12935..d111d2797d 100644 --- a/packages/workflow/tool-workflow/package.json +++ b/packages/workflow/tool-workflow/package.json @@ -32,16 +32,16 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-system-prompt": "^0.0.1", - "@deepseek-ai/dsh-tools": "^0.0.1", - "@deepseek-ai/dsh-workflow": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-system-prompt": "workspace:^", + "@deepseek-ai/dsh-tools": "workspace:^", + "@deepseek-ai/dsh-workflow": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -53,6 +53,6 @@ "@deepseek-ai/dsh-tools": "workspace:^", "@deepseek-ai/dsh-workflow": "workspace:^", "@deepseek-ai/dsh-workflow-workerthread": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/workflow/workflow-workerthread/package.json b/packages/workflow/workflow-workerthread/package.json index d085ba235f..53e03ebc2d 100644 --- a/packages/workflow/workflow-workerthread/package.json +++ b/packages/workflow/workflow-workerthread/package.json @@ -37,18 +37,18 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-brand": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-subagent": "^0.0.1", - "@deepseek-ai/dsh-tools": "^0.0.1", - "@deepseek-ai/dsh-workflow": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-brand": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-subagent": "workspace:^", + "@deepseek-ai/dsh-tools": "workspace:^", + "@deepseek-ai/dsh-workflow": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -63,7 +63,7 @@ "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", "@deepseek-ai/dsh-workflow": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/cordis": "workspace:^", "tsx": "^4.19.2" } } diff --git a/packages/workflow/workflow/package.json b/packages/workflow/workflow/package.json index e2a6eb21d3..1c342bcebe 100644 --- a/packages/workflow/workflow/package.json +++ b/packages/workflow/workflow/package.json @@ -32,12 +32,12 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-agent": "^0.0.1", - "@deepseek-ai/dsh-brand": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-llm": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-agent": "workspace:^", + "@deepseek-ai/dsh-brand": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-llm": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -45,6 +45,6 @@ "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/packages/workspace/workspace/package.json b/packages/workspace/workspace/package.json index 9c0c5127d5..7efc53b6c8 100644 --- a/packages/workspace/workspace/package.json +++ b/packages/workspace/workspace/package.json @@ -37,13 +37,13 @@ ], "license": "BSD-3-Clause", "peerDependencies": { - "@deepseek-ai/dsh-brand": "^0.0.1", - "@deepseek-ai/dsh-storage-domain": "^0.0.1", - "@deepseek-ai/dsh-invariants": "^0.0.1", - "@deepseek-ai/dsh-session": "^0.0.1", - "@deepseek-ai/dsh-session-persistence": "^0.0.1", - "@deepseek-ai/dsh-storage": "^0.0.1", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/dsh-brand": "workspace:^", + "@deepseek-ai/dsh-storage-domain": "workspace:^", + "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-session": "workspace:^", + "@deepseek-ai/dsh-session-persistence": "workspace:^", + "@deepseek-ai/dsh-storage": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { "zod": "^4.4.3" @@ -55,6 +55,6 @@ "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-session-persistence": "workspace:^", "@deepseek-ai/dsh-storage": "workspace:^", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9e74ebfd80..16602cc946 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -127,7 +127,7 @@ importers: apps/cli: dependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../vendor/cordis '@deepseek-ai/cordis-plugin-hmr': specifier: workspace:* @@ -752,7 +752,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -786,7 +786,7 @@ importers: version: link:../../typert/type-meta devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-client-connection': specifier: workspace:^ @@ -811,7 +811,7 @@ importers: version: link:../../typert/type-meta devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -835,7 +835,7 @@ importers: packages/attachment/attachment: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-brand': specifier: workspace:^ @@ -854,7 +854,7 @@ importers: version: 0.35.3(@types/node@22.20.0) devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-attachment': specifier: workspace:^ @@ -869,7 +869,7 @@ importers: packages/bash/bash: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -888,7 +888,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -919,7 +919,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-bash': specifier: workspace:^ @@ -940,7 +940,7 @@ importers: packages/bash/bash-sandbox: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-bash': specifier: workspace:^ @@ -974,7 +974,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-bash': specifier: workspace:^ @@ -995,7 +995,7 @@ importers: packages/bash/pwsh-sandbox: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-bash': specifier: workspace:^ @@ -1026,7 +1026,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -1093,7 +1093,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -1151,7 +1151,7 @@ importers: version: 4.2.0 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-group': specifier: workspace:^ @@ -1187,7 +1187,7 @@ importers: packages/boot/cmdline: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-include': specifier: workspace:^ @@ -1443,7 +1443,7 @@ importers: version: link:../../context/workspace-context devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -1465,7 +1465,7 @@ importers: version: 15.0.0 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-loader': specifier: workspace:^ @@ -1625,7 +1625,7 @@ importers: version: 15.0.0 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-loader': specifier: workspace:^ @@ -1668,7 +1668,7 @@ importers: version: 8.21.0 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-host-webserver': specifier: workspace:^ @@ -1687,7 +1687,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-loader': specifier: workspace:^ @@ -1705,7 +1705,7 @@ importers: packages/client/locale: dependencies: '@deepseek-ai/dsh-client-connection': - specifier: ^0.0.1 + specifier: workspace:^ version: link:../connection '@deepseek-ai/dsh-settings': specifier: workspace:^ @@ -1715,7 +1715,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-client-runtime': specifier: workspace:^ @@ -1739,7 +1739,7 @@ importers: packages/client/modules: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-loader': specifier: workspace:^ @@ -1806,7 +1806,7 @@ importers: version: 4.4.7(@types/react@18.3.31)(immer@10.2.0)(react@18.3.1) devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -1834,7 +1834,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -1853,7 +1853,7 @@ importers: version: 4.1.8(@opentelemetry/api@1.9.1)(@types/node@25.9.3)(@vitest/coverage-v8@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-client-runtime': specifier: workspace:^ @@ -1886,7 +1886,7 @@ importers: packages/client/ui-agent-preset: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-client-connection': specifier: workspace:^ @@ -1932,7 +1932,7 @@ importers: version: 2.1.1 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-client-connection': specifier: workspace:^ @@ -1981,7 +1981,7 @@ importers: version: 2.1.1 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -2063,7 +2063,7 @@ importers: version: 18.3.1 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-client-locale': specifier: workspace:^ @@ -2090,7 +2090,7 @@ importers: packages/client/ui-goal: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-api-remotes': specifier: workspace:^ @@ -2135,7 +2135,7 @@ importers: packages/client/ui-layout: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-client-locale': specifier: workspace:^ @@ -2162,7 +2162,7 @@ importers: packages/client/ui-model: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-client-connection': specifier: workspace:^ @@ -2204,7 +2204,7 @@ importers: packages/client/ui-models: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-client-connection': specifier: workspace:^ @@ -2246,7 +2246,7 @@ importers: packages/client/ui-permission: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-client-connection': specifier: workspace:^ @@ -2291,7 +2291,7 @@ importers: packages/client/ui-plan: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-client-connection': specifier: workspace:^ @@ -2394,7 +2394,7 @@ importers: version: 4.3.1 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -2431,7 +2431,7 @@ importers: version: 18.3.1 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -2462,7 +2462,7 @@ importers: version: 2.1.1 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-client-locale': specifier: workspace:^ @@ -2505,7 +2505,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-client-connection': specifier: workspace:^ @@ -2548,7 +2548,7 @@ importers: version: 2.1.1 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-client-locale': specifier: workspace:^ @@ -2581,7 +2581,7 @@ importers: packages/client/ui-skill: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-client-connection': specifier: workspace:^ @@ -2630,7 +2630,7 @@ importers: version: 2.1.1 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-client-locale': specifier: workspace:^ @@ -2660,7 +2660,7 @@ importers: packages/client/ui-slots: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -2676,7 +2676,7 @@ importers: version: 18.3.1 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-client-locale': specifier: workspace:^ @@ -2715,7 +2715,7 @@ importers: packages/client/ui-theme: dependencies: '@deepseek-ai/dsh-client-connection': - specifier: ^0.0.1 + specifier: workspace:^ version: link:../connection '@deepseek-ai/dsh-settings': specifier: workspace:^ @@ -2728,7 +2728,7 @@ importers: version: 2.1.1 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-client-locale': specifier: workspace:^ @@ -2762,7 +2762,7 @@ importers: version: 2.1.1 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-client-connection': specifier: workspace:^ @@ -2814,7 +2814,7 @@ importers: version: 9.0.0 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-client-runtime': specifier: workspace:^ @@ -2851,7 +2851,7 @@ importers: version: 2.1.1 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-client-locale': specifier: workspace:^ @@ -2912,7 +2912,7 @@ importers: version: 18.3.1(react@18.3.1) devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-loader': specifier: workspace:^ @@ -2949,7 +2949,7 @@ importers: version: 1.2.0(react@18.3.1) devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -2961,7 +2961,7 @@ importers: packages/code-runtime/code-runtime: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -2974,7 +2974,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-code-runtime': specifier: workspace:^ @@ -2992,7 +2992,7 @@ importers: packages/compact/command-compact: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-include': specifier: workspace:^ @@ -3022,7 +3022,7 @@ importers: packages/compact/compact: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-brand': specifier: workspace:^ @@ -3047,7 +3047,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-include': specifier: workspace:^ @@ -3099,7 +3099,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-include': specifier: workspace:^ @@ -3130,7 +3130,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -3161,7 +3161,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -3198,7 +3198,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -3226,7 +3226,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.6 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-loader': specifier: workspace:^ @@ -3271,7 +3271,7 @@ importers: packages/core/agent: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -3302,7 +3302,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -3324,7 +3324,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -3361,7 +3361,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -3388,7 +3388,7 @@ importers: packages/core/scope: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -3397,7 +3397,7 @@ importers: packages/core/session: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-brand': specifier: workspace:^ @@ -3425,7 +3425,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -3444,7 +3444,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -3474,7 +3474,7 @@ importers: packages/credentials/credentials: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-brand': specifier: workspace:^ @@ -3496,7 +3496,7 @@ importers: version: 2.9.0 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-atomic-write': specifier: workspace:^ @@ -3524,7 +3524,7 @@ importers: version: 2.29.1 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -3539,7 +3539,7 @@ importers: packages/e2b/fs-e2b: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-e2b': specifier: workspace:^ @@ -3558,7 +3558,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-e2b': specifier: workspace:^ @@ -3580,7 +3580,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-include': specifier: workspace:^ @@ -3632,7 +3632,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-timer': specifier: workspace:^ @@ -3744,7 +3744,7 @@ importers: version: link:../../boot/app-boot devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -3753,7 +3753,7 @@ importers: packages/feedback/command-feedback: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-include': specifier: workspace:^ @@ -3783,7 +3783,7 @@ importers: packages/fs/fs: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-brand': specifier: workspace:^ @@ -3808,7 +3808,7 @@ importers: version: 3.1.1 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-fs': specifier: workspace:^ @@ -3823,7 +3823,7 @@ importers: packages/fs/fs-policy: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-fs': specifier: workspace:^ @@ -3838,7 +3838,7 @@ importers: packages/fs/fs-sandbox: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-fs': specifier: workspace:^ @@ -3866,7 +3866,7 @@ importers: version: 9.0.0 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -3924,7 +3924,7 @@ importers: version: 1.18.0 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.6 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -3967,7 +3967,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -4009,7 +4009,7 @@ importers: packages/goal/command-goal: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-loader': specifier: workspace:^ @@ -4043,7 +4043,7 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -4076,7 +4076,7 @@ importers: packages/goal/goal-session: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -4113,7 +4113,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-loader': specifier: workspace:^ @@ -4147,7 +4147,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -4174,7 +4174,7 @@ importers: packages/guard/timeout-policy: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -4192,7 +4192,7 @@ importers: packages/hooks/hook-protocol: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-bash': specifier: workspace:^ @@ -4211,7 +4211,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -4263,7 +4263,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -4387,7 +4387,7 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent-presets': specifier: workspace:^ @@ -4411,7 +4411,7 @@ importers: packages/host/directory-picker: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -4420,7 +4420,7 @@ importers: packages/host/directory-picker-auto: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-include': specifier: workspace:^ @@ -4457,7 +4457,7 @@ importers: version: 2.1.1 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-client-locale': specifier: workspace:^ @@ -4500,7 +4500,7 @@ importers: version: 3.1.1 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-client-runtime': specifier: workspace:^ @@ -4531,7 +4531,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-loader': specifier: workspace:^ @@ -4550,7 +4550,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -4559,7 +4559,7 @@ importers: packages/interaction/commands: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -4587,7 +4587,7 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-bash': specifier: workspace:^ @@ -4620,7 +4620,7 @@ importers: packages/interaction/tool-ask-user: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -4648,7 +4648,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -4675,7 +4675,7 @@ importers: packages/interaction/user-interaction: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -4694,7 +4694,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-attachment': specifier: workspace:^ @@ -4719,7 +4719,7 @@ importers: version: 3.1.0 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-credentials': specifier: workspace:^ @@ -4750,7 +4750,7 @@ importers: version: 0.82.1(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(ws@8.21.0)(zod@4.4.3) devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-attachment': specifier: workspace:^ @@ -4784,7 +4784,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-include': specifier: workspace:^ @@ -4845,7 +4845,7 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-compact': specifier: workspace:^ @@ -4866,7 +4866,7 @@ importers: packages/lsp/lsp: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-brand': specifier: workspace:^ @@ -4885,7 +4885,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-brand': specifier: workspace:^ @@ -4928,7 +4928,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -4980,7 +4980,7 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -5008,7 +5008,7 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -5054,7 +5054,7 @@ importers: version: 4.2.0 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-include': specifier: workspace:^ @@ -5106,7 +5106,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -5121,7 +5121,7 @@ importers: packages/pty/pty: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -5143,7 +5143,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -5177,7 +5177,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-include': specifier: workspace:^ @@ -5229,7 +5229,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-include': specifier: workspace:^ @@ -5286,7 +5286,7 @@ importers: packages/sandbox/sandbox: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -5311,7 +5311,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -5333,7 +5333,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -5358,7 +5358,7 @@ importers: version: 3.1.1 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -5373,7 +5373,7 @@ importers: packages/scaffold/client: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -5398,7 +5398,7 @@ importers: version: 15.0.0 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -5423,7 +5423,7 @@ importers: version: 2.9.0 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-brand': specifier: workspace:^ @@ -5459,7 +5459,7 @@ importers: packages/scaffold/protocol: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -5490,7 +5490,7 @@ importers: version: 0.1.4 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-app-boot': specifier: workspace:^ @@ -5512,7 +5512,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-loader': specifier: workspace:^ @@ -5555,7 +5555,7 @@ importers: version: 2.9.0 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-brand': specifier: workspace:^ @@ -5574,10 +5574,10 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-loader': - specifier: ^1.0.0-rc.5 + specifier: workspace:^ version: link:../../../vendor/loader '@deepseek-ai/cordis-plugin-timer': specifier: workspace:^ @@ -5613,7 +5613,7 @@ importers: packages/session-query/session-query: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-brand': specifier: workspace:^ @@ -5641,7 +5641,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-loader': specifier: workspace:^ @@ -5669,7 +5669,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -5714,7 +5714,7 @@ importers: packages/session/session-checkpoint-policy: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-loader': specifier: workspace:^ @@ -5753,7 +5753,7 @@ importers: packages/session/session-persistence: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-brand': specifier: workspace:^ @@ -5781,7 +5781,7 @@ importers: version: 3.1.1 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -5800,7 +5800,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -5819,7 +5819,7 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -5838,7 +5838,7 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -5862,7 +5862,7 @@ importers: packages/session/session-telemetry: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -5899,7 +5899,7 @@ importers: version: 0.220.0(@opentelemetry/api@1.9.1) devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-loader': specifier: workspace:^ @@ -5933,7 +5933,7 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-brand': specifier: workspace:^ @@ -5964,7 +5964,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -5989,7 +5989,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-include': specifier: workspace:^ @@ -6023,7 +6023,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -6044,7 +6044,7 @@ importers: packages/session/user-id: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-brand': specifier: workspace:^ @@ -6063,7 +6063,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-brand': specifier: workspace:^ @@ -6085,7 +6085,7 @@ importers: version: 2.9.0 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-atomic-write': specifier: workspace:^ @@ -6107,7 +6107,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -6122,7 +6122,7 @@ importers: packages/skill/skill-badge: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -6144,7 +6144,7 @@ importers: version: 2.9.0 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-fs': specifier: workspace:^ @@ -6166,7 +6166,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -6196,7 +6196,7 @@ importers: packages/spill/spill: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.6 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-brand': specifier: workspace:^ @@ -6218,7 +6218,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.6 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-brand': specifier: workspace:^ @@ -6243,7 +6243,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.6 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -6273,7 +6273,7 @@ importers: packages/storage/storage: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -6289,7 +6289,7 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -6305,7 +6305,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -6321,7 +6321,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -6337,7 +6337,7 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -6401,10 +6401,10 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-loader': - specifier: ^1.0.0-rc.5 + specifier: workspace:^ version: link:../../../vendor/loader '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -6447,7 +6447,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -6484,10 +6484,10 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-loader': - specifier: ^1.0.0-rc.5 + specifier: workspace:^ version: link:../../../vendor/loader '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -6530,10 +6530,10 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-loader': - specifier: ^1.0.0-rc.5 + specifier: workspace:^ version: link:../../../vendor/loader '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -6570,10 +6570,10 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-loader': - specifier: ^1.0.0-rc.5 + specifier: workspace:^ version: link:../../../vendor/loader '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -6606,13 +6606,13 @@ importers: packages/subagent/subagent-inprocess: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-include': - specifier: ^1.0.4 + specifier: workspace:^ version: link:../../../vendor/include '@deepseek-ai/cordis-plugin-loader': - specifier: ^1.0.0-rc.5 + specifier: workspace:^ version: link:../../../vendor/loader '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -6664,10 +6664,10 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-loader': - specifier: ^1.0.0-rc.5 + specifier: workspace:^ version: link:../../../vendor/loader '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -6716,10 +6716,10 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-loader': - specifier: ^1.0.0-rc.5 + specifier: workspace:^ version: link:../../../vendor/loader '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -6764,7 +6764,7 @@ importers: packages/subagent/tool-subagent-control: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -6810,7 +6810,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -6852,7 +6852,7 @@ importers: packages/subprocess/subprocess: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -6865,7 +6865,7 @@ importers: version: 1.1.0(patch_hash=7a0c04f1f49d798a9ffe2f7f414c01064a44ca2489772d0c3e1235ab336755e6) devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -6890,7 +6890,7 @@ importers: version: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@25.9.3)(@vitest/coverage-v8@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -6902,7 +6902,7 @@ importers: packages/support/agent-loop-testkit: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -6933,13 +6933,13 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis packages/support/llm-mock-server: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -6948,7 +6948,7 @@ importers: packages/support/llm-replay: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-compact': specifier: workspace:^ @@ -6973,7 +6973,7 @@ importers: version: 4.22.4 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.6 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -6991,7 +6991,7 @@ importers: packages/tasks/tasks: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.6 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -7009,7 +7009,7 @@ importers: packages/tasks/tasks-local: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -7040,7 +7040,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.6 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -7080,7 +7080,7 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-include': specifier: workspace:^ @@ -7132,7 +7132,7 @@ importers: version: 6.0.3 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -7154,7 +7154,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-loader': specifier: workspace:^ @@ -7179,7 +7179,7 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -7188,7 +7188,7 @@ importers: packages/typert/type-meta: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -7197,7 +7197,7 @@ importers: packages/util/atomic-write: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -7206,7 +7206,7 @@ importers: packages/util/brand: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -7215,7 +7215,7 @@ importers: packages/util/environment: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -7224,7 +7224,7 @@ importers: packages/util/native-command: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -7233,7 +7233,7 @@ importers: packages/util/paths: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.6 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -7242,7 +7242,7 @@ importers: packages/util/retention: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.6 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -7251,7 +7251,7 @@ importers: packages/util/timeout: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -7270,7 +7270,7 @@ importers: version: 7.2.4 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -7319,7 +7319,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -7335,7 +7335,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -7354,7 +7354,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -7385,7 +7385,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-environment': specifier: workspace:^ @@ -7404,7 +7404,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-environment': specifier: workspace:^ @@ -7423,7 +7423,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-loader': specifier: workspace:^ @@ -7475,7 +7475,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -7508,7 +7508,7 @@ importers: packages/workflow/workflow: devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -7533,7 +7533,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -7582,7 +7582,7 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../../../vendor/cordis '@deepseek-ai/dsh-brand': specifier: workspace:^ @@ -7927,10 +7927,10 @@ importers: vendor/cordis: dependencies: '@deepseek-ai/cordis-plugin-include': - specifier: ^1.0.4 + specifier: workspace:^ version: link:../include '@deepseek-ai/cordis-plugin-loader': - specifier: ^1.0.0-rc.5 + specifier: workspace:^ version: link:../loader '@deepseek-ai/cosmokit': specifier: link:../cosmokit @@ -7944,10 +7944,10 @@ importers: vendor/group: dependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../cordis '@deepseek-ai/cordis-plugin-loader': - specifier: ^1.0.0-rc.5 + specifier: workspace:^ version: link:../loader vendor/hmr: @@ -7956,10 +7956,10 @@ importers: specifier: ^7.29.0 version: 7.29.7 '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../cordis '@deepseek-ai/cordis-plugin-timer': - specifier: ^1.1.2 + specifier: workspace:^ version: link:../timer '@deepseek-ai/cosmokit': specifier: link:../cosmokit @@ -7987,10 +7987,10 @@ importers: vendor/include: dependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../cordis '@deepseek-ai/cordis-plugin-loader': - specifier: ^1.0.0-rc.5 + specifier: workspace:^ version: link:../loader '@deepseek-ai/cosmokit': specifier: link:../cosmokit @@ -8002,7 +8002,7 @@ importers: vendor/loader: dependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../cordis '@deepseek-ai/cosmokit': specifier: link:../cosmokit @@ -8014,7 +8014,7 @@ importers: vendor/logger-console: dependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../cordis '@deepseek-ai/cosmokit': specifier: link:../cosmokit @@ -8038,7 +8038,7 @@ importers: vendor/timer: dependencies: '@deepseek-ai/cordis': - specifier: ^4.0.0-rc.7 + specifier: workspace:^ version: link:../cordis '@deepseek-ai/cosmokit': specifier: link:../cosmokit diff --git a/scripts/check-workspace-constraints.ts b/scripts/check-workspace-constraints.ts index cdada48fc5..30afce1e9f 100644 --- a/scripts/check-workspace-constraints.ts +++ b/scripts/check-workspace-constraints.ts @@ -80,6 +80,8 @@ interface PackageManifest { repository?: { type?: string; url?: string; directory?: string } peerDependencies?: Record devDependencies?: Record + dependencies?: Record + optionalDependencies?: Record } /** One workspace manifest and its repo-relative path. */ @@ -380,9 +382,38 @@ function checkRepositoryVersion(): string[] { return ['package.json: version must be stable X.Y.Z'] } +/** Dependency sections whose ranges reach a published tarball or a local install. */ +const dependencySections = ['dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies'] as const + +/** + * Require the `workspace:` protocol for every reference to a workspace member. + * + * A hand-written range says nothing about the version the workspace actually + * carries, and `pnpm pack` leaves it alone: `^0.0.1` published from version + * `0.0.2` names a version that does not exist. The protocol makes pack + * substitute the member's real version, so no release step rewrites ranges. + * @param manifests - every workspace manifest. + * @returns One error per reference that names a workspace member without the protocol. + */ +function checkWorkspaceProtocol(manifests: readonly WorkspaceManifest[]): string[] { + const members = new Set(manifests.map(entry => entry.manifest.name).filter(name => name !== undefined)) + const errors: string[] = [] + for (const { dir, manifest } of manifests) { + for (const section of dependencySections) { + for (const [name, range] of Object.entries(manifest[section] ?? {})) { + if (!members.has(name) || range.startsWith('workspace:')) continue + errors.push(`${manifest.name ?? dir}: ${section}.${name} must use the workspace: protocol, got ${range}`) + } + } + } + return errors +} + +const manifests = workspaceManifests() const errors = [ ...checkRepositoryVersion(), - ...workspaceManifests().flatMap(checkWorkspace), + ...manifests.flatMap(checkWorkspace), + ...checkWorkspaceProtocol(manifests), ...checkHierarchyShape(), ...collectProjectReferenceFaceViolations(root), ] diff --git a/vendor/cordis/package.json b/vendor/cordis/package.json index 3428ccbdbc..576ea209a7 100644 --- a/vendor/cordis/package.json +++ b/vendor/cordis/package.json @@ -32,8 +32,8 @@ "author": "Shigma ", "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis-plugin-include": "^1.0.4", - "@deepseek-ai/cordis-plugin-loader": "^1.0.0-rc.5" + "@deepseek-ai/cordis-plugin-include": "workspace:^", + "@deepseek-ai/cordis-plugin-loader": "workspace:^" }, "peerDependenciesMeta": { "@deepseek-ai/cordis-plugin-include": { @@ -45,6 +45,6 @@ }, "dependencies": { "@standard-schema/spec": "^1.1.0", - "@deepseek-ai/cosmokit": "^1.8.1" + "@deepseek-ai/cosmokit": "workspace:^" } } diff --git a/vendor/group/package.json b/vendor/group/package.json index c9f242a7d3..b5e07fdb66 100644 --- a/vendor/group/package.json +++ b/vendor/group/package.json @@ -30,7 +30,7 @@ "author": "Shigma ", "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis-plugin-loader": "^1.0.0-rc.5", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" } } diff --git a/vendor/hmr/package.json b/vendor/hmr/package.json index 019c027584..68617b430e 100644 --- a/vendor/hmr/package.json +++ b/vendor/hmr/package.json @@ -41,15 +41,15 @@ } }, "peerDependencies": { - "@deepseek-ai/cordis-plugin-timer": "^1.1.2", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis-plugin-timer": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { "@babel/code-frame": "^7.29.0", "chokidar": "^4.0.3", - "@deepseek-ai/cosmokit": "^1.8.1", + "@deepseek-ai/cosmokit": "workspace:^", "picomatch": "^4.0.3", - "@deepseek-ai/schemastery": "^3.18.0" + "@deepseek-ai/schemastery": "workspace:^" }, "devDependencies": { "@types/babel__code-frame": "^7.27.0", diff --git a/vendor/include/package.json b/vendor/include/package.json index 7fb6c3f36b..de1509c92b 100644 --- a/vendor/include/package.json +++ b/vendor/include/package.json @@ -30,11 +30,11 @@ "author": "Shigma ", "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis-plugin-loader": "^1.0.0-rc.5", - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/cosmokit": "^1.8.1", + "@deepseek-ai/cosmokit": "workspace:^", "js-yaml": "^4.1.0" } } diff --git a/vendor/loader/package.json b/vendor/loader/package.json index aab8c19bf5..62e88b2594 100644 --- a/vendor/loader/package.json +++ b/vendor/loader/package.json @@ -30,7 +30,7 @@ "author": "Shigma ", "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "^4.0.0-rc.7", + "@deepseek-ai/cordis": "workspace:^", "node-addon-require-builtin": "^0.1.4" }, "peerDependenciesMeta": { @@ -39,6 +39,6 @@ } }, "dependencies": { - "@deepseek-ai/cosmokit": "^1.8.1" + "@deepseek-ai/cosmokit": "workspace:^" } } diff --git a/vendor/logger-console/package.json b/vendor/logger-console/package.json index aeeb81fb50..29b4b423ab 100644 --- a/vendor/logger-console/package.json +++ b/vendor/logger-console/package.json @@ -32,11 +32,11 @@ "author": "Shigma ", "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/cosmokit": "^1.8.1", - "@deepseek-ai/schemastery": "^3.18.0", + "@deepseek-ai/cosmokit": "workspace:^", + "@deepseek-ai/schemastery": "workspace:^", "supports-color": "^9.4.0" } } diff --git a/vendor/schemastery/package.json b/vendor/schemastery/package.json index e31c6e6251..26cfd9b937 100644 --- a/vendor/schemastery/package.json +++ b/vendor/schemastery/package.json @@ -34,6 +34,6 @@ "license": "MIT", "dependencies": { "@standard-schema/spec": "^1.1.0", - "@deepseek-ai/cosmokit": "^1.8.1" + "@deepseek-ai/cosmokit": "workspace:^" } } diff --git a/vendor/timer/package.json b/vendor/timer/package.json index 32f564aa9d..a8138fae67 100644 --- a/vendor/timer/package.json +++ b/vendor/timer/package.json @@ -30,9 +30,9 @@ "author": "Shigma ", "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "^4.0.0-rc.7" + "@deepseek-ai/cordis": "workspace:^" }, "dependencies": { - "@deepseek-ai/cosmokit": "^1.8.1" + "@deepseek-ai/cosmokit": "workspace:^" } } From 27c9ca12a2d3079e51fc85dff048ccec1828186f Mon Sep 17 00:00:00 2001 From: imccyu <276526105+imccyu@users.noreply.github.com> Date: Tue, 11 Aug 2026 00:26:26 +0800 Subject: [PATCH 08/36] feat(release): drive the installed entry from the packed tarballs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A throwaway consumer outside the repository declares every member as a file: dependency, installs, and runs the installed executable with plain Node, asserting the version it reports. That is the check a workspace link or a stale lib/ in the checkout cannot pass for: it reads only what files selected. The family declares its executable, so the vendored family — libraries a consumer imports, with no executable — states that it has none instead of carrying a probe that would prove nothing. Both pack workflows run it after packing, still without credentials. --- .github/workflows/release-vendor.yml | 3 + .github/workflows/release.yml | 3 + package.json | 1 + scripts/release/families.ts | 19 ++++ scripts/release/verify-packed-install.ts | 105 +++++++++++++++++++++++ 5 files changed, 131 insertions(+) create mode 100644 scripts/release/verify-packed-install.ts diff --git a/.github/workflows/release-vendor.yml b/.github/workflows/release-vendor.yml index b83547b560..dc778f3d21 100644 --- a/.github/workflows/release-vendor.yml +++ b/.github/workflows/release-vendor.yml @@ -80,6 +80,9 @@ jobs: - name: Pack release tarballs run: pnpm run release:pack --family vendor --out dist/npm-vendor + - name: Verify packed install + run: pnpm run release:verify-packed-install --family vendor --from dist/npm-vendor + - uses: actions/upload-artifact@v4 with: name: vendor-npm-tarballs diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8b4005f42f..affdd3c900 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -79,6 +79,9 @@ jobs: - name: Pack release tarballs run: pnpm run release:pack --family dsh --out dist/npm + - name: Verify packed install + run: pnpm run release:verify-packed-install --family dsh --from dist/npm + - uses: actions/upload-artifact@v4 with: name: dsh-npm-tarballs diff --git a/package.json b/package.json index 32138d03e8..0d17549909 100644 --- a/package.json +++ b/package.json @@ -123,6 +123,7 @@ "publish:npm-baseline": "tsx scripts/publish-npm-baseline.ts", "release:verify": "tsx scripts/release/verify.ts", "release:pack": "tsx scripts/release/pack.ts", + "release:verify-packed-install": "tsx scripts/release/verify-packed-install.ts", "release:publish": "tsx scripts/release/publish.ts", "dsh": "node --import tsx/esm apps/cli/src/bin.ts", "demo:headless": "node --import tsx/esm apps/cli/src/bin.ts --profile headless", diff --git a/scripts/release/families.ts b/scripts/release/families.ts index b02c21cb1e..78f5de1951 100644 --- a/scripts/release/families.ts +++ b/scripts/release/families.ts @@ -57,6 +57,14 @@ function requireString(manifest: Record, field: string, context return value } +/** The executable a family's installed artifacts are driven through. */ +export interface InstalledEntry { + /** Package that carries the executable. */ + readonly packageName: string + /** Path to the executable inside that package. */ + readonly binPath: string +} + /** A release sequence: its members, its version baseline, and its tag naming. */ export abstract class ReleaseFamily { /** Workflow-facing identifier, also the `--family` argument. */ @@ -167,6 +175,12 @@ export abstract class ReleaseFamily { * @param files - every path inside its tarball. */ abstract validatePayload(member: ReleaseMember, files: readonly string[]): void + + /** + * The executable that proves this family's artifacts install and run, or + * `undefined` for a family that publishes no executable. + */ + abstract readonly installedEntry: InstalledEntry | undefined } /** `packages/*` and `apps/*`: one shared version across the whole family. */ @@ -206,6 +220,8 @@ class DshFamily extends ReleaseFamily { typeRTRemoteNavigation: hasTypeRTRemoteNavigation(member.manifest), }) } + + readonly installedEntry = { packageName: '@deepseek-ai/dsh', binPath: 'lib/bin.js' } } /** `vendor/*`: every package keeps its own version line, so every package has its own tag. */ @@ -250,6 +266,9 @@ class VendorFamily extends ReleaseFamily { validatePayload(member: ReleaseMember, files: readonly string[]): void { if (files.length === 0) throw new Error(`${member.name} packed an empty tarball`) } + + /** No installed-entry probe: these are libraries a consumer imports, with no executable. */ + readonly installedEntry = undefined } /** Every release family this module owns, in workflow order. */ diff --git a/scripts/release/verify-packed-install.ts b/scripts/release/verify-packed-install.ts new file mode 100644 index 0000000000..d50e876f06 --- /dev/null +++ b/scripts/release/verify-packed-install.ts @@ -0,0 +1,105 @@ +/** + * Install a packed release family into a throwaway consumer outside the + * repository and drive its installed executable with plain Node. + * + * Everything the packed tarballs need comes from the tarballs themselves: the + * consumer declares every member as a `file:` dependency, so the only registry + * traffic is for external dependencies. What this proves is that `files` + * selected a complete payload and that the published dependency ranges resolve + * — a workspace link or a stale `lib/` in the checkout cannot stand in for a + * missing file here + * ([rationale](../../.agents/notes/proposed/process/2026-08-10-npm-release-sequences.md)). + */ + +import { spawnSync } from 'node:child_process' +import { mkdtempSync, rmSync, writeFileSync } from 'node:fs' +import { tmpdir } from 'node:os' +import { join, resolve } from 'node:path' +import { pathToFileURL } from 'node:url' +import { parseArgs } from 'node:util' +import { releaseFamily, tarballName, type ReleaseMember } from './families.ts' + +/** + * Environment for the installed artifact: no host Node hooks, no host DeepSeek + * Harness home, and no ambient npm user agent that would confuse npm. + * @param consumerRoot - the throwaway consumer directory. + * @returns The child environment. + */ +function consumerEnvironment(consumerRoot: string): NodeJS.ProcessEnv { + const environment = { ...process.env } + delete environment.npm_config_user_agent + delete environment.NPM_CONFIG_USER_AGENT + delete environment.NODE_OPTIONS + delete environment.NODE_PATH + environment.DSH_HOME = resolve(consumerRoot, '.dsh') + environment.DSH_AGENTS_HOME = resolve(consumerRoot, '.agents') + environment.DSH_TELEMETRY_DISABLED = '1' + return environment +} + +/** + * Run a command in the consumer and fail the process on a non-zero exit. + * @param command - executable name. + * @param args - command arguments. + * @param cwd - working directory. + * @param env - child environment. + * @returns The captured stdout, trimmed. + */ +function run(command: string, args: readonly string[], cwd: string, env: NodeJS.ProcessEnv): string { + const result = spawnSync(command, [...args], { cwd, env, encoding: 'utf8' }) + if (result.error !== undefined) throw result.error + if (result.status !== 0) { + throw new Error(`${command} ${args.join(' ')} exited with ${String(result.status)}:\n${result.stdout}\n${result.stderr}`) + } + return result.stdout.trim() +} + +/** Install the family named by `--family` from `--from` and drive its entry. */ +function main(): void { + const { values } = parseArgs({ + options: { family: { type: 'string' }, from: { type: 'string' } }, + allowPositionals: false, + }) + if (values.family === undefined || values.from === undefined) { + throw new Error('usage: verify-packed-install.ts --family --from ') + } + + const family = releaseFamily(values.family) + const entry = family.installedEntry + const root = process.cwd() + const packed = resolve(root, values.from) + const members: ReleaseMember[] = family.members(root) + + if (entry === undefined) { + console.log(`release verify-packed-install: family ${family.id} publishes no executable, nothing to drive`) + return + } + + const consumerRoot = mkdtempSync(join(tmpdir(), `dsh-packed-${family.id}-`)) + try { + const dependencies = Object.fromEntries(members.map(member => + [member.name, pathToFileURL(join(packed, tarballName(member))).href])) + writeFileSync(join(consumerRoot, 'package.json'), `${JSON.stringify({ + name: `dsh-packed-install-${family.id}`, + version: '0.0.0', + private: true, + dependencies, + }, null, 2)}\n`) + + const environment = consumerEnvironment(consumerRoot) + console.log(`release verify-packed-install: installing ${String(members.length)} tarball(s) into ${consumerRoot}`) + run('npm', ['install', '--no-audit', '--no-fund', '--package-lock=false'], consumerRoot, environment) + + const bin = join(consumerRoot, 'node_modules', ...entry.packageName.split('/'), entry.binPath) + const version = run(process.execPath, [bin, '--version'], consumerRoot, environment) + const expected = members.find(member => member.name === entry.packageName)?.version + if (version !== expected) { + throw new Error(`installed ${entry.packageName} --version reported ${JSON.stringify(version)}, expected ${String(expected)}`) + } + console.log(`release verify-packed-install: installed ${entry.packageName} reports ${version}`) + } finally { + rmSync(consumerRoot, { recursive: true, force: true }) + } +} + +main() From a943e67798d7cd8c7d72c788e9184ab75174d605 Mon Sep 17 00:00:00 2001 From: imccyu <276526105+imccyu@users.noreply.github.com> Date: Tue, 11 Aug 2026 00:36:39 +0800 Subject: [PATCH 09/36] feat(release): bump and commit a release family in one command release:dsh takes major, minor, patch, or an explicit version and writes one version across the family; release:vendor takes none and increments each package's own patch, but only for packages whose published payload changed since their vendor--v* tag. That tag is the record of the commit a package last published from, so the change judgement needs no state file, and the diff is filtered through the manifest's files rules - editing a vendored comment does not trigger a release. Both refresh the lockfile, commit, and print the tag to create after the commit merges. --dry-run reports the plan and writes nothing. Incrementing the release numbers is also what drops an upstream prerelease segment: cordis 4.0.0-rc.7 publishes as 4.0.1, because a prerelease version would not satisfy a consumer's plain range. --- package.json | 2 + scripts/release/bump.ts | 199 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 201 insertions(+) create mode 100644 scripts/release/bump.ts diff --git a/package.json b/package.json index 0d17549909..277bd7fe85 100644 --- a/package.json +++ b/package.json @@ -121,6 +121,8 @@ "doc-sync": "tsx scripts/run-gates.ts doc-sync", "hygiene": "pnpm run rescope-vendor:check && pnpm run knip && pnpm run publint && pnpm run constraints && pnpm run verify-package-invariants && pnpm run verify-built-package-invariants && pnpm run verify-cordis-config && pnpm run verify-node-next-types && pnpm run verify-runtime-closure && pnpm run verify-vendored-links", "publish:npm-baseline": "tsx scripts/publish-npm-baseline.ts", + "release:dsh": "tsx scripts/release/bump.ts --family dsh", + "release:vendor": "tsx scripts/release/bump.ts --family vendor", "release:verify": "tsx scripts/release/verify.ts", "release:pack": "tsx scripts/release/pack.ts", "release:verify-packed-install": "tsx scripts/release/verify-packed-install.ts", diff --git a/scripts/release/bump.ts b/scripts/release/bump.ts new file mode 100644 index 0000000000..83e1b3a2da --- /dev/null +++ b/scripts/release/bump.ts @@ -0,0 +1,199 @@ +/** + * Bump one release family's version and commit it, so the published version is + * readable from the repository rather than derived inside CI + * ([rationale](../../.agents/notes/proposed/process/2026-08-10-npm-release-sequences.md)). + * + * The dsh family shares one version: `major`, `minor`, `patch`, or an explicit + * `x.y.z` (including a prerelease such as `0.0.1-rc.1`). The vendored family + * has one version line per package and publishes only what changed since that + * package's own `vendor--v*` tag, which is the record of the commit it + * last published from. + * + * The version lands in the manifests, the lockfile follows, and a human creates + * the tag after the commit merges. CI never writes to the repository. + */ + +import { spawnSync } from 'node:child_process' +import { readFileSync, writeFileSync } from 'node:fs' +import { join, matchesGlob } from 'node:path' +import { parseArgs } from 'node:util' +import { releaseFamily, type ReleaseFamily, type ReleaseMember } from './families.ts' + +/** Files npm publishes whether or not `files` lists them. */ +const ALWAYS_PUBLISHED = ['package.json', 'README*', 'LICENSE*', 'LICENCE*'] as const + +/** Release types the dsh family accepts besides an explicit version. */ +const RELEASE_TYPES = ['major', 'minor', 'patch'] as const + +/** + * Run a command and fail the process on a non-zero exit. + * @param command - executable name. + * @param args - command arguments. + * @returns The captured stdout, trimmed. + */ +function run(command: string, args: readonly string[]): string { + const result = spawnSync(command, [...args], { encoding: 'utf8' }) + if (result.error !== undefined) throw result.error + if (result.status !== 0) { + throw new Error(`${command} ${args.join(' ')} exited with ${String(result.status)}:\n${result.stdout}\n${result.stderr}`) + } + return result.stdout.trim() +} + +/** + * Split a version into its release numbers, discarding any prerelease segment. + * @param version - the current version. + * @returns Major, minor, and patch. + */ +function releaseNumbers(version: string): [number, number, number] { + const match = /^(\d+)\.(\d+)\.(\d+)(?:-[0-9A-Za-z.-]+)?$/.exec(version) + if (match === null) throw new Error(`cannot read release numbers from version ${version}`) + return [Number(match[1]), Number(match[2]), Number(match[3])] +} + +/** + * The next dsh version. + * @param current - the family's current shared version. + * @param request - `major`, `minor`, `patch`, or an explicit version. + * @returns The target version. + */ +function nextSharedVersion(current: string, request: string): string { + if (!RELEASE_TYPES.includes(request as typeof RELEASE_TYPES[number])) { + if (!/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(request)) { + throw new Error(`usage: release:dsh , got ${request}`) + } + return request + } + const [major, minor, patch] = releaseNumbers(current) + if (request === 'major') return `${String(major + 1)}.0.0` + if (request === 'minor') return `${String(major)}.${String(minor + 1)}.0` + return `${String(major)}.${String(minor)}.${String(patch + 1)}` +} + +/** + * The version a vendored package publishes next: its release numbers with the + * patch incremented, which also drops an upstream prerelease segment. + * @param current - the package's current version. + * @returns The target version. + */ +function nextVendorVersion(current: string): string { + const [major, minor, patch] = releaseNumbers(current) + return `${String(major)}.${String(minor)}.${String(patch + 1)}` +} + +/** + * Whether a repository-relative path reaches the member's published payload. + * @param member - the member the path belongs to. + * @param path - repository-relative path. + * @returns True when `files` (or npm's always-published set) selects it. + */ +function reachesPayload(member: ReleaseMember, path: string): boolean { + const relative = path.slice(member.directory.length + 1) + const files = member.manifest.files + const patterns = [ + ...ALWAYS_PUBLISHED, + ...Array.isArray(files) ? files.filter((entry): entry is string => typeof entry === 'string') : [], + ] + return patterns.some(pattern => + matchesGlob(relative, pattern) || matchesGlob(relative, `${pattern}/**`) || relative === pattern) +} + +/** + * The newest tag a member published from, or undefined when it never published. + * @param family - the member's family. + * @param member - the member. + * @returns The tag name. + */ +function lastPublishedTag(family: ReleaseFamily, member: ReleaseMember): string | undefined { + const prefix = family.tagFor(member).replace(/-v[^-]*$/, '-v') + const tags = run('git', ['tag', '--list', `${prefix}*`, '--sort=-v:refname']).split('\n').filter(line => line !== '') + return tags[0] +} + +/** + * Whether a member's published payload changed since it last published. + * @param family - the member's family. + * @param member - the member. + * @returns True when the member needs a new version. + */ +function changedSincePublication(family: ReleaseFamily, member: ReleaseMember): boolean { + const tag = lastPublishedTag(family, member) + if (tag === undefined) return true + const changed = run('git', ['diff', '--name-only', `${tag}..HEAD`, '--', member.directory]) + .split('\n').filter(line => line !== '') + return changed.some(path => reachesPayload(member, path)) +} + +/** + * Write a version into a member's manifest, preserving formatting and key order. + * @param root - repository root. + * @param member - the member to rewrite. + * @param version - the target version. + */ +function writeVersion(root: string, member: ReleaseMember, version: string): void { + const path = join(root, member.directory, 'package.json') + const text = readFileSync(path, 'utf8') + const line = `"version": "${member.version}"` + if (!text.includes(line)) throw new Error(`${member.directory}: cannot locate ${line}`) + writeFileSync(path, text.replace(line, `"version": "${version}"`)) +} + +/** Bump the family named by `--family` and commit; `--dry-run` only reports the plan. */ +function main(): void { + const { values, positionals } = parseArgs({ + options: { family: { type: 'string' }, 'dry-run': { type: 'boolean', default: false } }, + allowPositionals: true, + }) + if (values.family === undefined) throw new Error('usage: bump.ts --family [version]') + + const family = releaseFamily(values.family) + const root = process.cwd() + const members = family.members(root) + family.verifyVersions(members) + + const planned: { member: ReleaseMember; version: string }[] = [] + let sharedVersion: string | undefined + if (family.id === 'dsh') { + const request = positionals[0] + if (request === undefined) throw new Error('usage: release:dsh ') + const [first] = members + if (first === undefined) throw new Error(`release family ${family.id} has no members`) + sharedVersion = nextSharedVersion(first.version, request) + for (const member of members) planned.push({ member, version: sharedVersion }) + } else { + if (positionals.length > 0) throw new Error('release:vendor takes no version: each package increments its own patch') + for (const member of members) { + if (!changedSincePublication(family, member)) continue + planned.push({ member, version: nextVendorVersion(member.version) }) + } + } + + if (planned.length === 0) { + console.log(`release bump: family ${family.id}, nothing changed since publication`) + return + } + + const dryRun = values['dry-run'] + if (!dryRun) { + for (const { member, version } of planned) writeVersion(root, member, version) + run('pnpm', ['install', '--lockfile-only']) + } + + const summary = sharedVersion + ?? planned.map(entry => `${entry.member.name.replace('@deepseek-ai/', '')} ${entry.version}`).join(', ') + console.log(`release bump: family ${family.id} -> ${summary}`) + for (const { member, version } of planned) console.log(` ${member.directory}: ${member.version} -> ${version}`) + + if (dryRun) { + console.log('release bump: dry run, nothing written') + return + } + run('git', ['add', 'pnpm-lock.yaml', ...planned.map(entry => join(entry.member.directory, 'package.json'))]) + run('git', ['commit', '-m', `release(${family.id}): ${summary}`]) + // The dsh family tags once for its shared version; vendor tags each package. + const tags = [...new Set(planned.map(entry => family.tagFor({ ...entry.member, version: entry.version })))] + console.log('release bump: committed. After this merges to master, tag it:') + for (const tag of tags) console.log(` git tag ${tag} && git push origin ${tag}`) +} + +main() From bb489d13251f0aeb5b934e2a39dff68f5364eb9d Mon Sep 17 00:00:00 2001 From: imccyu <276526105+imccyu@users.noreply.github.com> Date: Tue, 11 Aug 2026 00:46:04 +0800 Subject: [PATCH 10/36] fix(release): align the package-invariant and public-link gates The invariant companion rule pinned @deepseek-ai/dsh-invariants to a ^0.0.1 peerDependency, which the workspace protocol replaces; it now requires workspace:^ like every other workspace-internal reference. The release note stated the provenance risk by naming the internal repository, which the public-link gate rejects in tracked files. It now states the same constraint without naming it. --- .../process/2026-08-10-npm-release-sequences.i18n.yaml | 4 ++-- .../proposed/process/2026-08-10-npm-release-sequences.md | 2 +- .../proposed/process/2026-08-10-npm-release-sequences.zh.md | 2 +- scripts/package-invariants.ts | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.agents/notes/proposed/process/2026-08-10-npm-release-sequences.i18n.yaml b/.agents/notes/proposed/process/2026-08-10-npm-release-sequences.i18n.yaml index df41fb5816..76798fc636 100644 --- a/.agents/notes/proposed/process/2026-08-10-npm-release-sequences.i18n.yaml +++ b/.agents/notes/proposed/process/2026-08-10-npm-release-sequences.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/proposed/process/2026-08-10-npm-release-sequences.md -2026-08-10-npm-release-sequences.md: 700d922495c539145dd470fbff84e3e211f6ba4e -2026-08-10-npm-release-sequences.zh.md: 59761eacb1c65d4a38e721a319924bf58c5b423e +2026-08-10-npm-release-sequences.md: bfe4ccaeddee3713445a3ffb77d575e4af207ae2 +2026-08-10-npm-release-sequences.zh.md: 3df42748429ac62e8131bfe22e4ebaafb4943b32 diff --git a/.agents/notes/proposed/process/2026-08-10-npm-release-sequences.md b/.agents/notes/proposed/process/2026-08-10-npm-release-sequences.md index 700d922495..bfe4ccaedd 100644 --- a/.agents/notes/proposed/process/2026-08-10-npm-release-sequences.md +++ b/.agents/notes/proposed/process/2026-08-10-npm-release-sequences.md @@ -180,6 +180,6 @@ This Agent Note replaces the version scheme and the release-set boundary in [art **The visibility cost of private packages.** After `--access restricted`, every consumer — CI, sandbox e2e, and outside users — needs scope credentials to install. The three native packages move to `restricted` as well; they have never been published, so no existing anonymous install path is cut off. -**The `repository` organization differs from the one running the workflow.** The release set names `github.com/deepseek-ai/deepseek-harness` while the workflow runs in `deepseek-harness/deepseek-harness`. Token-based publication is unaffected; npm provenance (OIDC) requires the two to agree, so adopting it means either changing `repository` or publishing from the public repository. +**The `repository` field names a different organization than the one running the workflow.** The release set points consumers at `github.com/deepseek-ai/deepseek-harness`, which is not where these workflows run. Token-based publication is unaffected; npm provenance (OIDC) requires the two to agree, so adopting it means either repointing `repository` or publishing from the organization it names. **The first publication is one large step.** Nine vendored packages and the whole dsh set publish at once, so any payload defect surfaces in a single release. Driving the complete path with `0.0.1-rc.1` first is the only mitigation, which is why numbered versions wait for that to pass. diff --git a/.agents/notes/proposed/process/2026-08-10-npm-release-sequences.zh.md b/.agents/notes/proposed/process/2026-08-10-npm-release-sequences.zh.md index 59761eacb1..3df4274842 100644 --- a/.agents/notes/proposed/process/2026-08-10-npm-release-sequences.zh.md +++ b/.agents/notes/proposed/process/2026-08-10-npm-release-sequences.zh.md @@ -183,6 +183,6 @@ publish 不读 tag、不读任何清单,对发布集里每个包比较 manifes **私有包的可见性代价。** `--access restricted` 之后,任何消费方(含 CI、沙箱 e2e、外部使用者)都必须持有 scope 凭据才能安装。native 三包一并转 `restricted`;它们尚未发布过,因此没有既有的匿名安装路径被切断。 -**`repository` 指向的组织与运行 workflow 的组织不一致。** 发布集写的是 `github.com/deepseek-ai/deepseek-harness`,而 workflow 跑在 `deepseek-harness/deepseek-harness`。用 token 发布不受影响;一旦改用 npm provenance(OIDC),npm 会要求二者一致,届时要么改 `repository`,要么从公开仓库发布。 +**`repository` 指向的组织与运行 workflow 的组织不一致。** 发布集让消费方指向 `github.com/deepseek-ai/deepseek-harness`,而这些 workflow 并不跑在那里。用 token 发布不受影响;一旦改用 npm provenance(OIDC),npm 会要求二者一致,届时要么把 `repository` 改指过去,要么从它指向的组织发布。 **首发一次性放大。** vendor 首发九包、dsh 首发全闭包,任何 payload 缺陷都会在同一次发布里暴露。用 `0.0.1-rc.1` 先跑一遍完整链路是唯一的缓解手段,正式版本号留给验证通过之后。 diff --git a/scripts/package-invariants.ts b/scripts/package-invariants.ts index eeae171a0b..98ade09aa6 100644 --- a/scripts/package-invariants.ts +++ b/scripts/package-invariants.ts @@ -96,11 +96,11 @@ function checkManifest( addViolation(violations, owner.manifestPath, 'files must publish lib/invariant.js') } if (owner.packageName === '@deepseek-ai/dsh-invariants') return - if (manifest.peerDependencies?.['@deepseek-ai/dsh-invariants'] !== '^0.0.1') { + if (manifest.peerDependencies?.['@deepseek-ai/dsh-invariants'] !== 'workspace:^') { addViolation( violations, owner.manifestPath, - '@deepseek-ai/dsh-invariants must be a ^0.0.1 peerDependency', + '@deepseek-ai/dsh-invariants must be a workspace:^ peerDependency', ) } if (manifest.devDependencies?.['@deepseek-ai/dsh-invariants'] !== 'workspace:^') { From 787443b13f55d3daa3b8e1a57dac29214759ffbc Mon Sep 17 00:00:00 2001 From: imccyu <276526105+imccyu@users.noreply.github.com> Date: Tue, 11 Aug 2026 00:51:02 +0800 Subject: [PATCH 11/36] fix(release): verify the packed install against the framework it peers on The harness packages declare the vendored framework as a peer, so installing only the dsh tarballs left npm resolving @deepseek-ai/cordis from a private registry the credential-free pack job cannot reach. The verification now takes several pack directories and installs every tarball in them, and the dsh workflow packs the vendored family for that purpose while still publishing only its own set. The verification also reads what each tarball declares instead of what the checkout says, which is what let the process and tarball helpers become one home each - the three copies of a spawn wrapper were a duplication finding. --- .github/workflows/release.yml | 8 ++- scripts/release/bump.ts | 27 ++------ scripts/release/pack.ts | 29 +-------- scripts/release/process.ts | 65 +++++++++++++++++++ scripts/release/publish.ts | 43 ++----------- scripts/release/tarball.ts | 53 ++++++++++++++++ scripts/release/verify-packed-install.ts | 81 ++++++++++++------------ 7 files changed, 182 insertions(+), 124 deletions(-) create mode 100644 scripts/release/process.ts create mode 100644 scripts/release/tarball.ts diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index affdd3c900..6c7a7489f3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -79,8 +79,14 @@ jobs: - name: Pack release tarballs run: pnpm run release:pack --family dsh --out dist/npm + # The harness packages declare the vendored framework as a peer, and this + # job has no credentials for the private registry, so the verification + # installs that family's pack output too. Only dist/npm is published. + - name: Pack the vendored framework for verification + run: pnpm run release:pack --family vendor --out dist/npm-vendor + - name: Verify packed install - run: pnpm run release:verify-packed-install --family dsh --from dist/npm + run: pnpm run release:verify-packed-install --family dsh --from dist/npm --from dist/npm-vendor - uses: actions/upload-artifact@v4 with: diff --git a/scripts/release/bump.ts b/scripts/release/bump.ts index 83e1b3a2da..9755fd00c4 100644 --- a/scripts/release/bump.ts +++ b/scripts/release/bump.ts @@ -13,11 +13,11 @@ * the tag after the commit merges. CI never writes to the repository. */ -import { spawnSync } from 'node:child_process' import { readFileSync, writeFileSync } from 'node:fs' import { join, matchesGlob } from 'node:path' import { parseArgs } from 'node:util' import { releaseFamily, type ReleaseFamily, type ReleaseMember } from './families.ts' +import { capture } from './process.ts' /** Files npm publishes whether or not `files` lists them. */ const ALWAYS_PUBLISHED = ['package.json', 'README*', 'LICENSE*', 'LICENCE*'] as const @@ -25,21 +25,6 @@ const ALWAYS_PUBLISHED = ['package.json', 'README*', 'LICENSE*', 'LICENCE*'] as /** Release types the dsh family accepts besides an explicit version. */ const RELEASE_TYPES = ['major', 'minor', 'patch'] as const -/** - * Run a command and fail the process on a non-zero exit. - * @param command - executable name. - * @param args - command arguments. - * @returns The captured stdout, trimmed. - */ -function run(command: string, args: readonly string[]): string { - const result = spawnSync(command, [...args], { encoding: 'utf8' }) - if (result.error !== undefined) throw result.error - if (result.status !== 0) { - throw new Error(`${command} ${args.join(' ')} exited with ${String(result.status)}:\n${result.stdout}\n${result.stderr}`) - } - return result.stdout.trim() -} - /** * Split a version into its release numbers, discarding any prerelease segment. * @param version - the current version. @@ -106,7 +91,7 @@ function reachesPayload(member: ReleaseMember, path: string): boolean { */ function lastPublishedTag(family: ReleaseFamily, member: ReleaseMember): string | undefined { const prefix = family.tagFor(member).replace(/-v[^-]*$/, '-v') - const tags = run('git', ['tag', '--list', `${prefix}*`, '--sort=-v:refname']).split('\n').filter(line => line !== '') + const tags = capture('git', ['tag', '--list', `${prefix}*`, '--sort=-v:refname']).split('\n').filter(line => line !== '') return tags[0] } @@ -119,7 +104,7 @@ function lastPublishedTag(family: ReleaseFamily, member: ReleaseMember): string function changedSincePublication(family: ReleaseFamily, member: ReleaseMember): boolean { const tag = lastPublishedTag(family, member) if (tag === undefined) return true - const changed = run('git', ['diff', '--name-only', `${tag}..HEAD`, '--', member.directory]) + const changed = capture('git', ['diff', '--name-only', `${tag}..HEAD`, '--', member.directory]) .split('\n').filter(line => line !== '') return changed.some(path => reachesPayload(member, path)) } @@ -176,7 +161,7 @@ function main(): void { const dryRun = values['dry-run'] if (!dryRun) { for (const { member, version } of planned) writeVersion(root, member, version) - run('pnpm', ['install', '--lockfile-only']) + capture('pnpm', ['install', '--lockfile-only']) } const summary = sharedVersion @@ -188,8 +173,8 @@ function main(): void { console.log('release bump: dry run, nothing written') return } - run('git', ['add', 'pnpm-lock.yaml', ...planned.map(entry => join(entry.member.directory, 'package.json'))]) - run('git', ['commit', '-m', `release(${family.id}): ${summary}`]) + capture('git', ['add', 'pnpm-lock.yaml', ...planned.map(entry => join(entry.member.directory, 'package.json'))]) + capture('git', ['commit', '-m', `release(${family.id}): ${summary}`]) // The dsh family tags once for its shared version; vendor tags each package. const tags = [...new Set(planned.map(entry => family.tagFor({ ...entry.member, version: entry.version })))] console.log('release bump: committed. After this merges to master, tag it:') diff --git a/scripts/release/pack.ts b/scripts/release/pack.ts index 1b128817b9..5c50ebca4b 100644 --- a/scripts/release/pack.ts +++ b/scripts/release/pack.ts @@ -7,41 +7,16 @@ * ([rationale](../../.agents/notes/proposed/process/2026-08-10-npm-release-sequences.md)). */ -import { spawnSync } from 'node:child_process' import { existsSync, mkdirSync, rmSync, writeFileSync } from 'node:fs' import { join, resolve } from 'node:path' import { parseArgs } from 'node:util' import { releaseFamily, tarballName, type ReleaseFamily, type ReleaseMember } from './families.ts' +import { run } from './process.ts' +import { PUBLISH_ORDER_FILE, tarballFiles } from './tarball.ts' /** Where pack output lands when `--out` is omitted. */ const DEFAULT_OUTPUT = 'dist/npm' -/** Name of the file the publish step reads to learn the upload order. */ -export const PUBLISH_ORDER_FILE = 'publish-order.txt' - -/** - * Run a command, inheriting stdio, and fail the process on a non-zero exit. - * @param command - executable name. - * @param args - command arguments. - */ -function run(command: string, args: readonly string[]): void { - const result = spawnSync(command, [...args], { stdio: 'inherit' }) - if (result.error !== undefined) throw result.error - if (result.status !== 0) throw new Error(`${command} ${args.join(' ')} exited with ${String(result.status)}`) -} - -/** - * List a tarball's members. - * @param tarball - absolute tarball path. - * @returns Every path inside the archive. - */ -function tarballFiles(tarball: string): string[] { - const result = spawnSync('tar', ['-tzf', tarball], { encoding: 'utf8' }) - if (result.error !== undefined) throw result.error - if (result.status !== 0) throw new Error(`tar -tzf ${tarball} exited with ${String(result.status)}:\n${result.stderr}`) - return result.stdout.split('\n').filter(line => line !== '') -} - /** * Pack one member and check what its tarball carries. * @param family - the release family being packed. diff --git a/scripts/release/process.ts b/scripts/release/process.ts new file mode 100644 index 0000000000..3e8c6943bd --- /dev/null +++ b/scripts/release/process.ts @@ -0,0 +1,65 @@ +/** + * Process helpers shared by the release scripts: the release steps drive `git`, + * `pnpm`, `npm`, and `tar`, and each needs one of three failure behaviours. + */ + +import { spawnSync } from 'node:child_process' + +/** Where and with what environment a release step runs a command. */ +export interface RunOptions { + /** Working directory; defaults to the current one. */ + readonly cwd?: string + /** Child environment; defaults to this process's. */ + readonly env?: NodeJS.ProcessEnv +} + +/** What a command produced, for a caller that decides what a failure means. */ +export interface CommandResult { + /** Exit status, or null when a signal ended the process. */ + readonly status: number | null + /** Captured standard output. */ + readonly stdout: string + /** Captured standard error. */ + readonly stderr: string +} + +/** + * Run a command and capture its output without judging the exit status. + * @param command - executable name. + * @param args - command arguments. + * @param options - working directory and environment. + * @returns The exit status and captured streams. + */ +export function attempt(command: string, args: readonly string[], options: RunOptions = {}): CommandResult { + const result = spawnSync(command, [...args], { cwd: options.cwd, env: options.env, encoding: 'utf8' }) + if (result.error !== undefined) throw result.error + return { status: result.status, stdout: result.stdout, stderr: result.stderr } +} + +/** + * Run a command, capture its standard output, and fail on a non-zero exit. + * @param command - executable name. + * @param args - command arguments. + * @param options - working directory and environment. + * @returns The trimmed standard output. + */ +export function capture(command: string, args: readonly string[], options: RunOptions = {}): string { + const result = attempt(command, args, options) + if (result.status !== 0) { + throw new Error(`${command} ${args.join(' ')} exited with ${String(result.status)}:\n${result.stdout}\n${result.stderr}`) + } + return result.stdout.trim() +} + +/** + * Run a command with inherited streams, so its progress reaches the log, and + * fail on a non-zero exit. + * @param command - executable name. + * @param args - command arguments. + * @param options - working directory and environment. + */ +export function run(command: string, args: readonly string[], options: RunOptions = {}): void { + const result = spawnSync(command, [...args], { cwd: options.cwd, env: options.env, stdio: 'inherit' }) + if (result.error !== undefined) throw result.error + if (result.status !== 0) throw new Error(`${command} ${args.join(' ')} exited with ${String(result.status)}`) +} diff --git a/scripts/release/publish.ts b/scripts/release/publish.ts index 68dae1701a..bd0b2d8552 100644 --- a/scripts/release/publish.ts +++ b/scripts/release/publish.ts @@ -12,13 +12,13 @@ * the same artifact safe. */ -import { spawnSync } from 'node:child_process' import { createHash } from 'node:crypto' import { readFileSync } from 'node:fs' import { join, resolve } from 'node:path' import { parseArgs } from 'node:util' import { releaseFamily } from './families.ts' -import { PUBLISH_ORDER_FILE } from './pack.ts' +import { attempt, run } from './process.ts' +import { packedIdentity, readPublishOrder } from './tarball.ts' /** npm access level for every package this repository publishes. */ const ACCESS = 'restricted' @@ -28,22 +28,6 @@ type RegistryState = | { readonly kind: 'absent' } | { readonly kind: 'present'; readonly integrity: string } -/** - * Read a packed tarball's own manifest. - * @param tarball - absolute tarball path. - * @returns The packed `package.json` name and version. - */ -function packedIdentity(tarball: string): { name: string; version: string } { - const result = spawnSync('tar', ['-xOzf', tarball, 'package/package.json'], { encoding: 'utf8' }) - if (result.error !== undefined) throw result.error - if (result.status !== 0) throw new Error(`cannot read ${tarball}:\n${result.stderr}`) - const manifest: unknown = JSON.parse(result.stdout) - if (manifest === null || typeof manifest !== 'object') throw new Error(`${tarball} has no manifest`) - const { name, version } = manifest as Record - if (typeof name !== 'string' || typeof version !== 'string') throw new Error(`${tarball} manifest lacks name/version`) - return { name, version } -} - /** * The subresource integrity string npm records for a tarball. * @param tarball - absolute tarball path. @@ -60,8 +44,7 @@ function integrityOf(tarball: string): string { * @returns The registry state for that version. */ function registryState(name: string, version: string): RegistryState { - const result = spawnSync('npm', ['view', `${name}@${version}`, 'dist.integrity', '--json'], { encoding: 'utf8' }) - if (result.error !== undefined) throw result.error + const result = attempt('npm', ['view', `${name}@${version}`, 'dist.integrity', '--json']) if (result.status !== 0) { const output = `${result.stdout}${result.stderr}` if (output.includes('E404') || output.includes('404 Not Found')) return { kind: 'absent' } @@ -74,19 +57,6 @@ function registryState(name: string, version: string): RegistryState { return { kind: 'present', integrity: parsed } } -/** - * Publish one tarball. - * @param tarball - absolute tarball path. - * @param version - the version being published; a prerelease never takes `latest`. - */ -function publish(tarball: string, version: string): void { - const args = ['publish', tarball, '--access', ACCESS] - if (version.includes('-')) args.push('--tag', 'next') - const result = spawnSync('npm', args, { stdio: 'inherit' }) - if (result.error !== undefined) throw result.error - if (result.status !== 0) throw new Error(`npm publish ${tarball} exited with ${String(result.status)}`) -} - /** Publish the family named by `--family` from the directory named by `--from`. */ function main(): void { const { values } = parseArgs({ @@ -99,11 +69,10 @@ function main(): void { const family = releaseFamily(values.family) const directory = resolve(process.cwd(), values.from) - const order = readFileSync(join(directory, PUBLISH_ORDER_FILE), 'utf8').split('\n').filter(line => line !== '') let published = 0 let skipped = 0 - for (const filename of order) { + for (const filename of readPublishOrder(directory)) { const tarball = join(directory, filename) const { name, version } = packedIdentity(tarball) const state = registryState(name, version) @@ -120,7 +89,9 @@ function main(): void { skipped += 1 continue } - publish(tarball, version) + // A prerelease version never takes the latest dist-tag. + const tagArgs = version.includes('-') ? ['--tag', 'next'] : [] + run('npm', ['publish', tarball, '--access', ACCESS, ...tagArgs]) published += 1 } diff --git a/scripts/release/tarball.ts b/scripts/release/tarball.ts new file mode 100644 index 0000000000..568c24e877 --- /dev/null +++ b/scripts/release/tarball.ts @@ -0,0 +1,53 @@ +/** + * Reading packed npm tarballs and the order file that accompanies them. + * + * The release steps after pack treat a directory of tarballs as the unit of + * work, so they read what a tarball declares rather than what the checkout + * currently says. + */ + +import { readFileSync } from 'node:fs' +import { join } from 'node:path' +import { capture } from './process.ts' + +/** Name of the file recording the order in which a packed family uploads. */ +export const PUBLISH_ORDER_FILE = 'publish-order.txt' + +/** What a packed tarball calls itself. */ +export interface PackedIdentity { + /** Package name from the packed manifest. */ + readonly name: string + /** Package version from the packed manifest. */ + readonly version: string +} + +/** + * List a tarball's members. + * @param tarball - absolute tarball path. + * @returns Every path inside the archive. + */ +export function tarballFiles(tarball: string): string[] { + return capture('tar', ['-tzf', tarball]).split('\n').filter(line => line !== '') +} + +/** + * Read a packed tarball's own manifest. + * @param tarball - absolute tarball path. + * @returns The name and version the tarball declares. + */ +export function packedIdentity(tarball: string): PackedIdentity { + const manifest: unknown = JSON.parse(capture('tar', ['-xOzf', tarball, 'package/package.json'])) + if (manifest === null || typeof manifest !== 'object') throw new Error(`${tarball} has no manifest`) + const { name, version } = manifest as Record + if (typeof name !== 'string' || typeof version !== 'string') throw new Error(`${tarball} manifest lacks name/version`) + return { name, version } +} + +/** + * Read a packed directory's upload order. + * @param directory - absolute path of a pack output directory. + * @returns Tarball filenames in upload order. + */ +export function readPublishOrder(directory: string): string[] { + return readFileSync(join(directory, PUBLISH_ORDER_FILE), 'utf8').split('\n').filter(line => line !== '') +} diff --git a/scripts/release/verify-packed-install.ts b/scripts/release/verify-packed-install.ts index d50e876f06..7b970212ab 100644 --- a/scripts/release/verify-packed-install.ts +++ b/scripts/release/verify-packed-install.ts @@ -1,23 +1,28 @@ /** - * Install a packed release family into a throwaway consumer outside the - * repository and drive its installed executable with plain Node. + * Install packed tarballs into a throwaway consumer outside the repository and + * drive the installed executable with plain Node. * - * Everything the packed tarballs need comes from the tarballs themselves: the - * consumer declares every member as a `file:` dependency, so the only registry - * traffic is for external dependencies. What this proves is that `files` - * selected a complete payload and that the published dependency ranges resolve - * — a workspace link or a stale `lib/` in the checkout cannot stand in for a - * missing file here + * Every tarball the installed tree needs comes from `--from`, so the only + * registry traffic is for external dependencies. That matters beyond hermetic + * verification: the harness packages declare the vendored framework as a peer, + * and those packages live in another release sequence that this credential-free + * job cannot fetch from a private registry — so a dsh verification passes the + * vendored family's pack output too, while publishing only its own * ([rationale](../../.agents/notes/proposed/process/2026-08-10-npm-release-sequences.md)). + * + * What this proves is that `files` selected a complete payload and that the + * published dependency ranges resolve. A workspace link or a stale `lib/` in the + * checkout cannot stand in for a missing file here. */ -import { spawnSync } from 'node:child_process' import { mkdtempSync, rmSync, writeFileSync } from 'node:fs' import { tmpdir } from 'node:os' import { join, resolve } from 'node:path' import { pathToFileURL } from 'node:url' import { parseArgs } from 'node:util' -import { releaseFamily, tarballName, type ReleaseMember } from './families.ts' +import { releaseFamily } from './families.ts' +import { capture } from './process.ts' +import { packedIdentity, readPublishOrder } from './tarball.ts' /** * Environment for the installed artifact: no host Node hooks, no host DeepSeek @@ -38,63 +43,61 @@ function consumerEnvironment(consumerRoot: string): NodeJS.ProcessEnv { } /** - * Run a command in the consumer and fail the process on a non-zero exit. - * @param command - executable name. - * @param args - command arguments. - * @param cwd - working directory. - * @param env - child environment. - * @returns The captured stdout, trimmed. + * Every packed tarball in the given directories, as `file:` dependency entries. + * @param directories - absolute pack output directories. + * @returns Package name to tarball file URL, and the version each carries. */ -function run(command: string, args: readonly string[], cwd: string, env: NodeJS.ProcessEnv): string { - const result = spawnSync(command, [...args], { cwd, env, encoding: 'utf8' }) - if (result.error !== undefined) throw result.error - if (result.status !== 0) { - throw new Error(`${command} ${args.join(' ')} exited with ${String(result.status)}:\n${result.stdout}\n${result.stderr}`) +function packedDependencies(directories: readonly string[]): Map { + const dependencies = new Map() + for (const directory of directories) { + for (const filename of readPublishOrder(directory)) { + const tarball = join(directory, filename) + const { name, version } = packedIdentity(tarball) + dependencies.set(name, { url: pathToFileURL(tarball).href, version }) + } } - return result.stdout.trim() + return dependencies } -/** Install the family named by `--family` from `--from` and drive its entry. */ +/** Install every tarball under `--from` and drive the `--family` entry. */ function main(): void { const { values } = parseArgs({ - options: { family: { type: 'string' }, from: { type: 'string' } }, + options: { family: { type: 'string' }, from: { type: 'string', multiple: true } }, allowPositionals: false, }) - if (values.family === undefined || values.from === undefined) { - throw new Error('usage: verify-packed-install.ts --family --from ') + if (values.family === undefined || values.from === undefined || values.from.length === 0) { + throw new Error('usage: verify-packed-install.ts --family --from [--from ...]') } const family = releaseFamily(values.family) const entry = family.installedEntry - const root = process.cwd() - const packed = resolve(root, values.from) - const members: ReleaseMember[] = family.members(root) - if (entry === undefined) { console.log(`release verify-packed-install: family ${family.id} publishes no executable, nothing to drive`) return } + const root = process.cwd() + const packed = packedDependencies(values.from.map(directory => resolve(root, directory))) + const expected = packed.get(entry.packageName) + if (expected === undefined) throw new Error(`${entry.packageName} is not among the packed tarballs`) + const consumerRoot = mkdtempSync(join(tmpdir(), `dsh-packed-${family.id}-`)) try { - const dependencies = Object.fromEntries(members.map(member => - [member.name, pathToFileURL(join(packed, tarballName(member))).href])) writeFileSync(join(consumerRoot, 'package.json'), `${JSON.stringify({ name: `dsh-packed-install-${family.id}`, version: '0.0.0', private: true, - dependencies, + dependencies: Object.fromEntries([...packed].map(([name, entryPacked]) => [name, entryPacked.url])), }, null, 2)}\n`) const environment = consumerEnvironment(consumerRoot) - console.log(`release verify-packed-install: installing ${String(members.length)} tarball(s) into ${consumerRoot}`) - run('npm', ['install', '--no-audit', '--no-fund', '--package-lock=false'], consumerRoot, environment) + console.log(`release verify-packed-install: installing ${String(packed.size)} tarball(s) into ${consumerRoot}`) + capture('npm', ['install', '--no-audit', '--no-fund', '--package-lock=false'], { cwd: consumerRoot, env: environment }) const bin = join(consumerRoot, 'node_modules', ...entry.packageName.split('/'), entry.binPath) - const version = run(process.execPath, [bin, '--version'], consumerRoot, environment) - const expected = members.find(member => member.name === entry.packageName)?.version - if (version !== expected) { - throw new Error(`installed ${entry.packageName} --version reported ${JSON.stringify(version)}, expected ${String(expected)}`) + const version = capture(process.execPath, [bin, '--version'], { cwd: consumerRoot, env: environment }) + if (version !== expected.version) { + throw new Error(`installed ${entry.packageName} --version reported ${JSON.stringify(version)}, expected ${expected.version}`) } console.log(`release verify-packed-install: installed ${entry.packageName} reports ${version}`) } finally { From bcc4890038eaa13db84b0ce23ec00ffa6f2ba6ba Mon Sep 17 00:00:00 2001 From: imccyu <276526105+imccyu@users.noreply.github.com> Date: Tue, 11 Aug 2026 01:01:40 +0800 Subject: [PATCH 12/36] fix(release): follow the workspace protocol in the invariant fixture and knip config The package-invariant spec built its fixture with the range the rule no longer accepts. knip stopped needing the tar ignore entry once the tarball helpers became the one place that spawns it. --- knip.json | 1 - scripts/package-invariants.spec.ts | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/knip.json b/knip.json index 44f45da1ad..2f755dbb5f 100644 --- a/knip.json +++ b/knip.json @@ -9,7 +9,6 @@ "musl-gcc", "python3", "sandbox-exec", - "tar", "taskkill", "where.exe" ], diff --git a/scripts/package-invariants.spec.ts b/scripts/package-invariants.spec.ts index 59e56976e6..2763341b9e 100644 --- a/scripts/package-invariants.spec.ts +++ b/scripts/package-invariants.spec.ts @@ -49,7 +49,7 @@ function fixture(options: { }, files: ['lib/index.js', 'lib/invariant.js'], peerDependencies: options.invariantDependency === false ? {} : { - '@deepseek-ai/dsh-invariants': '^0.0.1', + '@deepseek-ai/dsh-invariants': 'workspace:^', }, devDependencies: options.invariantDependency === false ? {} : { '@deepseek-ai/dsh-invariants': 'workspace:^', From d9dcf5a48481b807050cd5b51b87aa8c3c1f6e22 Mon Sep 17 00:00:00 2001 From: imccyu <276526105+imccyu@users.noreply.github.com> Date: Tue, 11 Aug 2026 01:26:36 +0800 Subject: [PATCH 13/36] fix(release): close the review findings on the release sequences The root manifest carries the dsh family version. bump writes it with the members, because the workspace constraint requires them to match, and that constraint now accepts a prerelease segment: without both, release:dsh 0.0.2 left the root behind and 0.0.1-rc.1 could satisfy neither check. The Landlock workflow no longer passes --access public, which overrode the restricted publishConfig this repository just adopted for those packages. Vendored change detection reads build inputs when a package publishes build output, and vendor/cordis publishes the src its export map already pointed at: its lib/ is untracked, so a real source edit read as 'nothing changed' and the next publish would fail on a version whose bytes moved. The next version also takes the last published version as its baseline, so a re-sync that restores a lower upstream version cannot recompute a version already on the registry, and bump confirms the registry carries what the newest tag names. Tag prefixes are constructed rather than recovered from a full tag, which a hyphenated version defeated. Pack runs group per ref so concurrent pull requests stop displacing each other, the publish job carries the global group, and the unused id-token permission is gone. Every release script sits behind an entry guard, which is what lets the pure judgements carry tests: tag naming, publish order and cycle reporting, version arithmetic, payload policy, and the change judgement. The Agent Note moves to implemented and states what shipped: one probe command, the registry confirmation that now exists, and byte reproducibility recorded as assumed rather than measured. --- ...2026-08-10-npm-release-sequences.i18n.yaml | 6 + .../2026-08-10-npm-release-sequences.md | 160 +++++++++++ .../2026-08-10-npm-release-sequences.zh.md | 160 +++++++++++ ...2026-08-10-npm-release-sequences.i18n.yaml | 6 - .../2026-08-10-npm-release-sequences.md | 185 ------------- .../2026-08-10-npm-release-sequences.zh.md | 188 ------------- .github/workflows/landlock-run-release.yml | 4 +- .github/workflows/release-vendor.yml | 8 +- .github/workflows/release.yml | 9 +- apps/cli/package.json | 8 +- packages/bundle/base/package.json | 4 +- pnpm-lock.yaml | 12 +- scripts/check-workspace-constraints.ts | 6 +- scripts/release/bump.ts | 255 +++++++++++++----- scripts/release/families.spec.ts | 146 ++++++++++ scripts/release/families.ts | 31 ++- scripts/release/pack.ts | 6 +- scripts/release/process.ts | 17 ++ scripts/release/publish.ts | 6 +- scripts/release/verify-packed-install.ts | 6 +- scripts/release/verify.ts | 5 +- vendor/README.md | 1 + vendor/cordis/package.json | 3 +- 23 files changed, 747 insertions(+), 485 deletions(-) create mode 100644 .agents/notes/implemented/process/2026-08-10-npm-release-sequences.i18n.yaml create mode 100644 .agents/notes/implemented/process/2026-08-10-npm-release-sequences.md create mode 100644 .agents/notes/implemented/process/2026-08-10-npm-release-sequences.zh.md delete mode 100644 .agents/notes/proposed/process/2026-08-10-npm-release-sequences.i18n.yaml delete mode 100644 .agents/notes/proposed/process/2026-08-10-npm-release-sequences.md delete mode 100644 .agents/notes/proposed/process/2026-08-10-npm-release-sequences.zh.md create mode 100644 scripts/release/families.spec.ts diff --git a/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.i18n.yaml b/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.i18n.yaml new file mode 100644 index 0000000000..4246b4c62a --- /dev/null +++ b/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.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/process/2026-08-10-npm-release-sequences.md +2026-08-10-npm-release-sequences.md: 23c5f26c7be2b87d1ef2edffdd3f79a87cf1f9a1 +2026-08-10-npm-release-sequences.zh.md: 77b772460d0bf6b66ae6924c7bab1dfe0860b401 diff --git a/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.md b/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.md new file mode 100644 index 0000000000..23c5f26c7b --- /dev/null +++ b/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.md @@ -0,0 +1,160 @@ +# Agent Note: Private npm publication as three independent sequences + +Status: implemented + +English | [中文](2026-08-10-npm-release-sequences.zh.md) + +## Problem + +This repository held three unrelated groups of publishable packages and no channel that sent any of them to a registry. + +`packages/*/*` and `apps/*` form the runtime surface of `@deepseek-ai/dsh`; `vendor/*` holds nine rescoped Cordis framework packages, each carrying its upstream version; `native/landlock-run/packages/*` holds Linux platform packages with their own workflow. The three differ in version baseline, change rate, and build requirements: dsh moves with the product, vendor moves only when upstream is re-synced or a local modification changes, and native needs a musl toolchain and one build per architecture. Forcing them through one pipeline means every product release republishes the framework and the native binaries. + +Two hard blockers sat in the way. All 217 workspace manifests set `private: true`, which npm refuses to publish. The subtler one was 933 hand-written `peerDependencies: "^0.0.1"` entries between sibling dsh packages: `pnpm pack` substitutes the `workspace:` protocol but leaves semver ranges alone, and `^0.0.1` means `>=0.0.1 <0.0.2` — it excludes `0.0.2`, and semver excludes prereleases from a range without a prerelease of its own, so it excluded `0.0.1-rc.1` too. Those entries never failed only because the version never left `0.0.1`. + +`scripts/publish-npm-baseline.ts` is a local publication script: it packs and publishes in one process, needs a human to authenticate and retry on their own machine, and excludes vendor from its release set. It cannot be the basis for CI publication, though its tarball payload validation and installed-artifact probes are verified parts. + +## Decision + +### Three independent sequences + +`packages/`, `vendor/`, and `native/` each have one bump sequence and one publication, sharing no version, no trigger, and no waiting. Releasing dsh does not republish vendor; releasing vendor does not republish native. + +| Sequence | Members | Version baseline | Tag | Workflow | +|---|---|---|---|---| +| dsh | `packages/*/*` + `apps/*` (`@deepseek-ai/dsh` and `@deepseek-ai/dsh-frontend`) | one version for the family and the workspace root, `0.0.x` | `dsh-v` | `release.yml` | +| vendored framework | the nine `vendor/*` packages | each package on its own version line | `vendor--v` (one per package) | `release-vendor.yml` | +| native | `native/landlock-run/packages/*` | its own `0.0.x` | `landlock-run-v` | `landlock-run-release.yml` | + +All three publish privately to the `@deepseek-ai` scope on npmjs.com. `publishConfig.access` in each manifest is `restricted` and no workflow passes `--access`, because a command-line flag overrides the manifest. + +### Versions land in the repository from a local command; CI only checks and uploads + +Each sequence has one bump-and-commit command: it derives the target version, writes it into the relevant manifests, runs `pnpm install --lockfile-only`, and commits the manifests with the lockfile. The published version is therefore readable from the repository. A human creates the tag after the commit merges to master; CI never writes to the repository and needs no write permission. + +`release:dsh` accepts `major`, `minor`, `patch`, or an explicit version, and writes one version across the family **and the workspace root** — the workspace constraint requires every member's version to equal the root's, so the root carries the family version, and the root check accepts a prerelease segment. A prerelease such as `0.0.1-rc.1` drives pack, the installed-artifact probe, and one real private publication before numbered versions follow. The dist-tag decision is the one `landlock-run-release.yml` already made: a version with a prerelease segment publishes under `--tag next`, anything else takes `latest`. + +### vendor: publish what changed, and let tags be the ledger + +The vendored packages are decoupled from upstream by their scope but keep their own version lines. The published version is the higher of the manifest version and the last published version, with the patch incremented — which also drops an upstream prerelease segment. The first published versions: + +| Package | Upstream version | First published version | +|---|---|---| +| `@deepseek-ai/cordis` | 4.0.0-rc.7 | 4.0.1 | +| `@deepseek-ai/cordis-plugin-loader` | 1.0.0-rc.5 | 1.0.1 | +| `@deepseek-ai/cosmokit` | 1.8.1 | 1.8.2 | +| `@deepseek-ai/schemastery` | 3.18.0 | 3.18.1 | +| `@deepseek-ai/cordis-plugin-hmr` | 1.0.15 | 1.0.16 | +| `@deepseek-ai/cordis-plugin-include` | 1.0.4 | 1.0.5 | +| `@deepseek-ai/cordis-plugin-timer` | 1.1.2 | 1.1.3 | +| `@deepseek-ai/cordis-plugin-group` | 1.0.0 | 1.0.1 | +| `@deepseek-ai/cordis-plugin-logger-console` | 1.0.0 | 1.0.1 | + +Taking the last published version as the baseline is what survives a re-sync: upstream restoring `4.0.0-rc.8` after this repository published `4.0.1` would otherwise compute `4.0.1` again and collide. + +Only changed packages publish, and the change judgement adds no state file: **each package has its own tag, and that tag records the commit it last published from**. For each package, bump reads the newest `vendor--v*` tag and diffs the package directory against it. A path counts when the manifest's `files` selects it, when npm publishes it regardless (`package.json`, `README*`, `LICENSE*`), or — for a package whose `files` selects `lib/` — when it is a build input (`src/**`, `tsconfig*.json`, a build config). That last rule exists because a built payload is not tracked by git: without it, a real source change reads as "nothing changed" and the next publication fails on a version whose bytes moved. + +A tag is a commit pointer, not proof of publication. Bump asks the registry whether the version its newest tag names exists and fails for a human to resolve when it does not, because a tag pushed for a publication that then failed would otherwise read as "already published" and skip the package indefinitely. Querying a private package needs credentials, so an unauthenticated machine reports the gap instead of failing. + +`vendor/cordis` publishes `src` as well. Its export map declares `"./src/*"`, so a tarball without those files points consumers at absent paths, and `files` selecting only build output left the change judgement with no tracked path to match. + +### Publication runs only on GitHub, and the registry decides what goes out + +Publication runs only from GitHub Actions; there is no local publication path. Publish reads no tag and no manifest of "what this release includes". For each packed tarball it compares the version against the registry, in three states: + +| State | Action | +|---|---| +| the registry does not have that version | publish | +| the registry has it, and the tarball's sha512 equals the recorded `dist.integrity` | skip: this is a re-run over one artifact | +| the registry has it, and the integrity differs | fail, reporting content changed without a version bump | + +The third state catches code that changed without a version bump. The first two provide idempotence — re-running publish over one artifact republishes nothing and needs no manual selection of packages. The same rule resolves the tension between one vendor release carrying several tags and a workflow that can only run from one ref: the workflow never infers which packages to publish from the tag it ran from. + +### Workspace-internal references use the `workspace:` protocol + +Every reference to a workspace member uses `workspace:^`, so `pnpm pack` substitutes a range matching the target version: sibling `peerDependencies` follow the family version, and a reference to a vendored package follows that package's own line. The Landlock platform packages keep `workspace:*`, which publishes the exact version, because a platform package and its entry must agree exactly. + +`scripts/check-workspace-constraints.ts` requires the protocol, so a new package cannot reintroduce a hand-written range; the invariant-companion rule requires `workspace:^` for `@deepseek-ai/dsh-invariants` for the same reason. + +### Release family objects + +The entity in this domain is a **release family**: a set of packages sharing one version baseline and tag naming that publishes as a unit. Adding a family means adding a subclass and a workflow lane, not changing the core. + +| Object | Responsibility | +|---|---| +| `ReleaseFamily` | a family's identity: member discovery, version baseline, tag prefix, packed-payload rule, installed entry | +| `ReleaseMember` | one publishable package: directory, name, version, manifest | +| `publishOrder` | topological order over runtime dependencies, ties broken by package name; a cycle is reported rather than resolved arbitrarily | +| `pack` | packs a whole family into one directory and records the upload order | +| `verify` | the family's version baseline, and — when publishing — that the run comes from that family's tag and its members are publishable | +| `verify-packed-install` | installs the tarballs of one or more pack directories into a throwaway consumer and drives the installed executable | +| `publish` | the three registry states above | +| `process` / `tarball` | the one home for spawning commands and for reading a packed tarball, including the entry guard that keeps every script importable | + +The dsh family applies the repository's publication payload policy, which rejects sources and declaration maps. The vendored family keeps upstream's payload, because those manifests export `./src/*` and dropping `src` would publish an export map pointing at absent files. + +### Workflow shape: pack everything at once, then publish as one set + +The `pack` job walks the whole release set once, packing each member into one directory, writes the upload order, and uploads that directory as one artifact; the `publish` job downloads that artifact and publishes each entry in order. The release set is one unit — half the packages can never reach the registry while the other half is still building. + +`pack` carries no credentials and runs on every pull request and master push, so a pull request proves the release set still packs. `publish` is a manual dispatch, sits behind the `npm-publish` environment for human approval, and neither builds nor rebuilds — it uploads the bytes pack produced. Pack runs are grouped per ref so concurrent pull requests do not displace each other; the publish job carries the global group, because dist-tags are shared registry state. + +A dsh verification installs the vendored family's pack output too. The harness packages declare the vendored framework as a peer, those packages live in another sequence, and the credential-free job cannot fetch them from a private registry — so `release.yml` packs the vendored family for verification while publishing only its own set. + +### Repository changes this carried + +| Item | Content | +|---|---| +| release-set manifests | `private: true` removed; `publishConfig.access: restricted` and `repository` with each package's `directory` added | +| release-set boundary | every member of `packages/*/*`, `apps/*`, and `vendor/*` | +| dependency protocol | workspace-internal references are `workspace:^`, with `check-workspace-constraints.ts` and the invariant-companion rule requiring it | +| root `AGENTS.md` | the convention that vendored packages are `private: true` no longer holds | +| `vendor/README.md` | records `src` joining `cordis`'s `files` as a local modification | +| the three native packages | `publishConfig.access: restricted`, and their workflow no longer passes `--access` | + +### Relationship to the earlier proposal + +This Agent Note replaces the version scheme and the release-set boundary in [artifact-first npm baseline publication](../../proposed/process/2026-08-04-artifact-first-npm-baseline-publication.md): its `--` prerelease versions and `dev-` dist-tag are not adopted, and vendor is not excluded from the release set. What both agree on stands: pack and publish are separate, publish consumes only verified tarballs, and the payload and installed-artifact probes are release gates. + +## Alternatives considered + +**A `--` version.** Planned for continuous dev publication. It conflicts with keeping the published version in the repository: the version embeds a commit SHA, and writing the version back produces a new commit, so the SHA can only name the parent commit that was published and the link needs a convention to explain it. With numbered versions, a prerelease such as `0.0.1-rc.1` already covers "verify first, then release". + +**A `vendor/published.json` ledger recording each package's published version and commit.** This preceded the tag design. It adds a state file that must not drift from the registry. A per-package tag gives the same commit pointer, and the tag has to exist anyway, so it introduces no second copy of the state. + +**Event-level tags (`vendor-r1`, `vendor-r2`).** Prepared for one release event carrying several package versions. Once the registry decides what publishes, the workflow no longer infers the set from the tag, so per-package tags suffice — and each one names its own package's real version. + +**Putting the nine vendored packages on one `4.0.x` line.** It removes change detection, but cosmokit would jump from `1.8.1` to `4.0.1` and lose its upstream lineage; the upstream ranges inside the nine (`^1.8.1` and friends) would stop matching immediately, forcing a rewrite of the vendored manifests. + +**Incrementing every vendored package on every vendor release, with no change detection.** The least machinery, at the cost of new version numbers for packages whose content is byte-identical to the previous release. Tags reduce change detection to reading one tag and running one diff, which is not worth trading for inflated version numbers. + +**Deciding "already published" from the version alone, without comparing content.** The reference flow queries no registry: publish uploads each tarball and npm rejects a duplicate version. Skipping on the version alone misses code that changed without a bump, which is the only failure that quietly leaves stale bytes on the registry. The cost is a registry query and a dependency on reproducible builds. + +**Verifying only the packed install, with no local registry.** The reference flow unpacks tarballs into a tree and drives it with plain Node, which bypasses version-range resolution. Running a local registry in CI to cover that layer was rejected: artifact correctness is covered by existing tests, the publication path is exercised by the master rehearsal, and a pull request only needs to prove the release set packs. Installing from `file:` specifiers still exercises range resolution for every internal dependency. + +**Selecting a subset by entry closure.** Crawling `dependencies` from `@deepseek-ai/dsh` and `@deepseek-ai/dsh-frontend` yields 156 packages, 61 fewer than the whole set. But this repository's plugins are mounted by name from `cordis.yml` rather than imported: `vendor/cordis-plugin-group` and `vendor/cordis-plugin-logger-console` fall outside the dependency closure while being required at runtime. Selecting by code dependency fails as "the consumer installs it and it will not start", and it would need a standing proof that no mounted package was missed. Under a private scope the extra packages are invisible outside the organization. `python/`, the root `examples/`, `docs/`, and `website/` are not members. + +**Extending `scripts/publish-npm-baseline.ts`.** It is a local publication script that packs and publishes in one process, the opposite of separating credential-free packing from protected publication. Its verified parts — payload validation and installed-artifact probes — are reused so `pnpm run duplication` does not report clones. + +**One workflow with a `family` input.** Two version models in one file forks the concurrency group, the tag prefix, and the rehearsal triggers into conditional expressions. One file per family is both shorter and easier to read. + +**Rewriting dependency ranges at publication time.** Compared with the protocol, the rewrite runs only in CI, a local `pnpm install` cannot show whether it is correct, and it repeats on every release. + +**Running bump in CI and pushing the version back.** It needs repository write permission for the workflow, and a version commit on the release branch races human commits. Bump and commit stay local; CI checks and uploads. + +## Consequences + +The release scripts are importable modules behind a guarded entry point, and their judgements carry unit tests: tag naming, publish order and cycle reporting, version-baseline arithmetic, the payload change judgement, and each family's payload policy. Two defects the first draft carried — a publish command that ran the pack command on import, and a change judgement blind to `vendor/cordis` source edits — are exactly what a test at that seam catches. + +A pull request runs the full pack for both sequences without credentials and installs the packed dsh tarballs into a throwaway consumer, where plain Node drives `dsh --version`. That probe is deliberately one command: it proves `files` selected a complete payload and that the published ranges resolve, and says nothing about interactive behavior. + +What this costs: + +- **Tags can drift from the registry.** A tag pushed for a publication that then failed is caught by bump's registry check, but only where credentials exist; an unauthenticated machine reports the gap and continues. +- **The change judgement depends on visible tags.** A shallow clone, or a checkout without tags, degrades the vendored judgement to "publish everything for the first time". `fetch-depth: 0` is a precondition, not an optimization. +- **The protocol rewrite touched 1504 dependency declarations.** It does not change local resolution — pnpm already resolves from the workspace — but it changes the ranges that go out. +- **Private packages need credentials to install.** Every consumer — CI, sandbox e2e, outside users — needs scope credentials, including for the Landlock packages, which have never been published and so cut off no existing anonymous path. +- **`repository` names a different organization than the one running the workflows.** Token-based publication is unaffected; npm provenance (OIDC) requires the two to agree, so adopting it means either repointing `repository` or publishing from the organization it names. +- **Byte reproducibility is assumed, not measured.** The skip-on-identical-integrity state rests on packing the same commit twice producing the same bytes. Nothing measures that yet: if the build embeds absolute paths or timestamps, a re-run reports a false failure. Measure it before the first publication a re-run might follow, and fall back to comparing per-file content hashes if it does not hold. +- **Re-running publish over an older artifact can move `latest` backwards.** Publication is decided per version, so an older set republished after a newer one takes the stable dist-tag again. The rehearsals run from a prerelease version, which never takes `latest`. +- **The first publication is one large step.** Nine vendored packages and the whole dsh set publish at once, so any payload defect surfaces in a single release, which is why a prerelease version drives the complete path first. diff --git a/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.zh.md b/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.zh.md new file mode 100644 index 0000000000..77b772460d --- /dev/null +++ b/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.zh.md @@ -0,0 +1,160 @@ +# Agent Note: 三条独立序列的私有 NPM 发布 + +Status: implemented + +[English](2026-08-10-npm-release-sequences.md) | 中文 + +## 问题 + +这个仓库有三组互不相干的可发布包,却没有任何发布通道把它们送上 registry。 + +`packages/*/*` 与 `apps/*` 组成 `@deepseek-ai/dsh` 的运行面;`vendor/*` 是九个 rescope 过的 Cordis 框架包,各自带着上游的版本号;`native/landlock-run/packages/*` 是 Linux 平台包,有自己的 workflow。三组的版本基线、变更节奏和构建要求都不同:dsh 随产品迭代,vendor 只在同步上游或改动本地修改时才动,native 需要 musl 工具链和逐架构构建。把它们塞进一条发布流水线,等于每次产品发版都要重发框架和原生二进制。 + +挡路的还有两处硬门。全部 217 个 workspace manifest 都是 `private: true`,`npm publish` 直接拒绝。更隐蔽的是 933 条 dsh 兄弟包之间硬写的 `peerDependencies: "^0.0.1"`:`pnpm pack` 只替换 `workspace:` 协议,不动语义范围,而 `^0.0.1` 等于 `>=0.0.1 <0.0.2`——发 `0.0.2` 落不进去,发 `0.0.1-rc.1` 也落不进去(semver 规定不带预发布段的范围排除预发布版本)。这些条目至今没出事,只因为版本一直停在 `0.0.1`。 + +`scripts/publish-npm-baseline.ts` 是本机发布脚本:它把 pack 与 publish 放进同一个进程,需要人工在本机完成认证与重试,且把 vendor 排除在发布集之外。它不能作为 CI 发布的基础,但其中的 tarball payload 校验与已安装产物探针是验证过的零件。 + +## 决策 + +### 三条独立序列 + +`packages/`、`vendor/`、`native/` 各自一条 bump 序列、各自一次发布,不共享版本号、不共享触发、不互相等待。发 dsh 不重发 vendor,发 vendor 不重发 native。 + +| 序列 | 成员 | 版本基线 | tag | workflow | +|---|---|---|---|---| +| dsh | `packages/*/*` + `apps/*`(`@deepseek-ai/dsh` 与 `@deepseek-ai/dsh-frontend`) | 全族与 workspace 根共用一个 `0.0.x` | `dsh-v<版本>` | `release.yml` | +| vendored framework | `vendor/*` 九个包 | 每包各自一条版本线 | `vendor-<包名>-v<版本>`(每包一个) | `release-vendor.yml` | +| native | `native/landlock-run/packages/*` | 自己的 `0.0.x` | `landlock-run-v<版本>` | `landlock-run-release.yml` | + +三组一律发到 npmjs.com 的 `@deepseek-ai` scope 下的私有包。每个 manifest 的 `publishConfig.access` 都是 `restricted`,且没有任何 workflow 传 `--access`——命令行选项会覆盖 manifest。 + +### 版本由本地命令写进仓库,CI 只核对与上传 + +每条序列有一条 bump-and-commit 命令:算出目标版本,写进相关 manifest,跑 `pnpm install --lockfile-only`,再把 manifest 连 lockfile 一起 commit。发布版本因此在仓库里查得到。tag 由人工在 commit 合入 master 后打;CI 不写仓库,也不需要写权限。 + +`release:dsh` 接受 `major`、`minor`、`patch` 或显式版本号,把同一个版本写进全族**以及 workspace 根**——workspace 约束要求每个成员的版本等于根版本,所以根承载族版本,而根的检查接受预发布段。像 `0.0.1-rc.1` 这样的预发布号先把 pack、已安装产物探针和一次真实私有发布跑通,数字版本随后。dist-tag 沿用 `landlock-run-release.yml` 已有的判定:版本带预发布段就 `--tag next`,否则进 `latest`。 + +### vendor:谁改了谁发版,tag 就是账本 + +vendor 九包加了 scope 之后与上游脱钩,但保留各自的版本线。发布版本取「manifest 版本」与「上次发布版本」中较高的那个,再递增 patch——这一步同时去掉上游的预发布段。首发版本: + +| 包 | 上游版本 | 首发版本 | +|---|---|---| +| `@deepseek-ai/cordis` | 4.0.0-rc.7 | 4.0.1 | +| `@deepseek-ai/cordis-plugin-loader` | 1.0.0-rc.5 | 1.0.1 | +| `@deepseek-ai/cosmokit` | 1.8.1 | 1.8.2 | +| `@deepseek-ai/schemastery` | 3.18.0 | 3.18.1 | +| `@deepseek-ai/cordis-plugin-hmr` | 1.0.15 | 1.0.16 | +| `@deepseek-ai/cordis-plugin-include` | 1.0.4 | 1.0.5 | +| `@deepseek-ai/cordis-plugin-timer` | 1.1.2 | 1.1.3 | +| `@deepseek-ai/cordis-plugin-group` | 1.0.0 | 1.0.1 | +| `@deepseek-ai/cordis-plugin-logger-console` | 1.0.0 | 1.0.1 | + +以「上次发布版本」为基线才扛得住重同步:本仓发过 `4.0.1` 之后上游把版本恢复成 `4.0.0-rc.8`,只看 manifest 会再算出 `4.0.1` 并撞上已发版本。 + +只发改动过的包,而变更判据不引入新的状态文件:**每包一个 tag,tag 就是「上次发布到哪个 commit」的记录**。bump 对每个包取最新的 `vendor-<包名>-v*` tag,拿包目录与它做 diff。一条路径算命中的条件是:manifest 的 `files` 选中它,或 npm 无论如何都会发布它(`package.json`、`README*`、`LICENSE*`),或者——当该包的 `files` 选中 `lib/` 时——它是构建输入(`src/**`、`tsconfig*.json`、构建配置)。最后那条规则的存在理由是构建产物不在 git 里:没有它,真实的源码改动会读成「没变化」,而下一次发布会在一个字节已变的版本上失败。 + +tag 只是 commit 指针,不是发布成功的证明。bump 会向 registry 核对「最新 tag 指向的版本是否真的存在」,不存在就明确失败交人处理——否则一个为失败发布而推的 tag 会被读成「已发布」,从此永远跳过该包。查询私有包需要凭据,因此未鉴权的机器只报告这道核对被跳过,不失败。 + +`vendor/cordis` 现在也发布 `src`。它的 exports 声明了 `"./src/*"`,tarball 里没有这些文件就等于把消费方指向不存在的路径;而 `files` 只选构建产物,也让变更判据没有任何受 git 跟踪的路径可匹配。 + +### 发布只在 GitHub 执行,由 registry 状态决定发什么 + +发布只从 GitHub Actions 执行,没有本机发布路径。publish 不读 tag、不读任何「本次发布包含什么」的清单,而是对每个打包好的 tarball 拿版本与 registry 比对,分三态: + +| 状态 | 处置 | +|---|---| +| registry 上没有该版本 | 发布 | +| 已有该版本,且 tarball 的 sha512 等于记录的 `dist.integrity` | 跳过:这是同一批产物的重跑 | +| 已有该版本,但 integrity 不同 | 失败退出,报「内容已变但版本未 bump」 | + +第三态拦住「改了代码却没 bump 版本」。前两态给出幂等——同一个 artifact 重跑 publish 不会重复发布,也不需要人工挑拣包。同一条规则还解决了「一次 vendor 发布携带多个 tag,而 workflow 只能从一个 ref 触发」的矛盾:workflow 从不从触发它的 tag 去推断该发哪些包。 + +### workspace 内部引用走 `workspace:` 协议 + +所有指向 workspace 成员的引用都用 `workspace:^`,由 `pnpm pack` 替换成匹配目标版本的范围:兄弟包的 `peerDependencies` 跟随族版本,指向 vendored 包的引用跟随那个包自己的版本线。Landlock 平台包保留 `workspace:*`(发布成精确版本),因为平台包与它的入口必须版本完全一致。 + +`scripts/check-workspace-constraints.ts` 要求这个协议,所以新包无法再引入硬写的范围;同理,invariant companion 规则要求 `@deepseek-ai/dsh-invariants` 用 `workspace:^`。 + +### 发布族对象 + +这个领域里的实体是**发布族**:一组共享版本基线与 tag 命名、可整体发布的包。新增一族等于加一个子类和一条 workflow lane,不改核心。 + +| 对象 | 职责 | +|---|---| +| `ReleaseFamily` | 一族的身份:成员发现、版本基线、tag 前缀、打包 payload 规则、已安装入口 | +| `ReleaseMember` | 一个可发布包:目录、包名、版本、manifest | +| `publishOrder` | 按运行时依赖的拓扑序,同层按包名排;遇到环是报错而不是随意定序 | +| `pack` | 把整族打进一个目录并记录上传顺序 | +| `verify` | 族的版本基线;发布时还要求本次运行来自该族的 tag、且成员可发布 | +| `verify-packed-install` | 把一个或多个 pack 目录的 tarball 装进一次性 consumer,并驱动已安装的可执行入口 | +| `publish` | 上面那三态 | +| `process` / `tarball` | 启动命令、读取打包 tarball 的唯一正家,其中的入口守卫让每个脚本都可被 import | + +dsh 族套用仓库的发布 payload 策略(拒绝源码与声明映射)。vendored 族保留上游 payload,因为那些 manifest 导出 `./src/*`,去掉 `src` 会发出一个导出映射指向不存在文件的包。 + +### workflow 形状:一次性 pack 全部,再统一 publish + +`pack` job 一趟遍历整个发布集,把每个成员打进同一个目录,写出上传顺序,整个目录作为一份 artifact 上传;`publish` job 下载那一份 artifact,按顺序逐个发布。发布集是一个整体——绝不会出现一半的包已经上了 registry、另一半还在构建。 + +`pack` 无凭据,在每个 pull request 和每次 master push 上跑,所以一个 pull request 就能证明发布集仍能完整打出来。`publish` 是手动 dispatch,挂在 `npm-publish` environment 后面等人工审批,且既不构建也不重建——它上传的就是 pack 产出的字节。pack 的 run 按 ref 分组,并发的 pull request 不会互相顶掉;全局分组落在 publish job 上,因为 dist-tag 是共享的 registry 状态。 + +dsh 的验证会一并安装 vendored 族的 pack 产物。harness 的包把 vendored 框架声明成 peer,而那些包属于另一条序列,无凭据的 job 无法从私有 registry 取到——所以 `release.yml` 为验证而打包 vendored 族,发布的仍只有自己那一份。 + +### 本次带出的仓库改动 + +| 项 | 内容 | +|---|---| +| 发布集 manifest | 去掉 `private: true`;补 `publishConfig.access: restricted` 与带各自 `directory` 的 `repository` | +| 发布集边界 | `packages/*/*`、`apps/*`、`vendor/*` 的全部成员 | +| 依赖协议 | workspace 内部引用为 `workspace:^`,由 `check-workspace-constraints.ts` 与 invariant companion 规则强制 | +| 根 `AGENTS.md` | 「vendored 包是 `private: true`」这条约定不再成立 | +| `vendor/README.md` | 记录「`src` 加入 `cordis` 的 `files`」这条本地修改 | +| native 三包 | `publishConfig.access: restricted`,且其 workflow 不再传 `--access` | + +### 与先前提案的关系 + +本 Note 取代 [以产物为先的 NPM 基线发布](../../proposed/process/2026-08-04-artifact-first-npm-baseline-publication.md) 中的版本方案与发布集边界:那篇的 `-<时间戳>-<短 SHA>` 预发布版本与 `dev-` dist-tag 不再采用,vendor 也不排除在发布集之外。两篇一致的部分保留:pack 与 publish 分离、publish 只消费已验证的 tarball、payload 与安装后探针作为发布门。 + +## 曾考虑的替代方案 + +**`-<时间戳>-<短 SHA>` 版本号。** 曾计划用于持续 dev 发布。它与「把发布版本留在仓库里」冲突:版本内嵌 commit SHA,而把版本写回会产生新的 commit,于是 SHA 只能指向被发布的父 commit,这条链要靠约定解释。改用数字版本后,`0.0.1-rc.1` 这类预发布号已经覆盖「先验证再正式发」。 + +**用 `vendor/published.json` 账本记录每包的已发版本与 commit。** 这是 tag 方案之前的设计。它新增一份必须与 registry 不漂移的状态文件;per-package tag 提供同样的 commit 指针,而 tag 本来就要打,不引入第二处状态。 + +**事件级 tag(`vendor-r1`、`vendor-r2`)。** 为「一次发布事件携带多个包版本」准备。既然由 registry 决定发什么,workflow 就不再从 tag 推断集合,per-package tag 够用,而且每个 tag 携带的是它自己那个包的真实版本。 + +**把九个 vendored 包统一到一条 `4.0.x` 版本线。** 省掉变更检测,但 cosmokit 会从 `1.8.1` 跳到 `4.0.1`、丢失上游血缘;九包内部的上游范围(`^1.8.1` 之类)会立刻失配,必须改写 vendored manifest。 + +**每次 vendor 发布把九包全部 patch+1,不做变更检测。** 机制最少,代价是内容与上一版逐字节相同的包也拿到新版本号。tag 把变更检测的成本压到「读一个 tag、跑一次 diff」,不值得为省这点让版本号虚涨。 + +**只按版本号判断「是否已发布」,不比对内容。** 参照流程根本不查 registry:publish 逐个上传,重复版本由 npm 拒绝。只按版本号跳过会漏掉「改了代码没 bump」,而这是唯一会安静地把旧字节留在 registry 上的错误。代价是引入一次 registry 查询和对构建可复现性的依赖。 + +**只做打包后安装验证,不起本地 registry。** 参照流程是把 tarball 解包成一棵树、用普通 Node 驱动,这绕过了版本范围解析。曾提议在 CI 里起本地 registry 补这一层,被否:产物正确性已由既有测试覆盖,发布路径由 master 的排练覆盖,而 pull request 只需证明发布集能打出来。用 `file:` 说明符安装依然会对每个内部依赖走一遍范围解析。 + +**按入口闭包挑一部分包发。** 从 `@deepseek-ai/dsh` 与 `@deepseek-ai/dsh-frontend` 沿 `dependencies` 爬得到 156 个包,比全量少 61 个。但本仓的插件是 `cordis.yml` 按名字挂载的、不是被 import 的:`vendor/cordis-plugin-group` 与 `vendor/cordis-plugin-logger-console` 落在依赖闭包之外,却是运行时必需。照代码依赖挑的失败形态是「消费方装完起不来」,而且要额外持续证明「没漏任何挂载项」。私有 scope 下多出来的包对组织外不可见。`python/`、根 `examples/`、`docs/` 与 `website/` 不是成员。 + +**在 `scripts/publish-npm-baseline.ts` 上扩展。** 它是本机发布脚本,把 pack 与 publish 放在同一进程,与「无凭据 pack、受保护 publish」的分离相反。它验证过的零件——payload 校验与已安装产物探针——被搬运复用,以免 `pnpm run duplication` 判重复。 + +**一个 workflow 用 `family` 输入选择序列。** 两套版本模型塞进一个文件,会让 concurrency 组、tag 前缀、排练触发条件全部分叉成条件表达式。一族一个文件更短也更好读。 + +**在发布期改写依赖范围。** 与协议相比,改写逻辑只在 CI 执行过,本机 `pnpm install` 看不出它是否正确,而且每次发布都要重来一遍。 + +**在 CI 里执行 bump 并把版本推回仓库。** 需要给 workflow 仓库写权限,且发布分支上的版本 commit 会与人的 commit 竞争。bump 与 commit 留在本地,CI 只核对与上传。 + +## 后果 + +发布脚本是带入口守卫的可 import 模块,其判断都有单测覆盖:tag 命名、发布顺序与环报告、版本基线运算、payload 变更判据,以及各族的 payload 策略。第一版带过的两个缺陷——publish 命令在 import 时执行了 pack 命令、变更判据对 `vendor/cordis` 的源码改动失明——正是这类测试在对应接缝上能抓住的。 + +一个 pull request 会为两条序列跑完整的 pack(无凭据),并把打包好的 dsh tarball 装进一次性 consumer,用普通 Node 驱动 `dsh --version`。这个探针刻意只有一条命令:它证明 `files` 选出了完整 payload、发布出去的范围可解析,不涉及任何交互行为。 + +代价: + +- **tag 可能与 registry 漂移。** 为失败发布而推的 tag 由 bump 的 registry 核对拦下,但只在有凭据的地方;未鉴权的机器只报告这道核对被跳过。 +- **变更判据依赖 tag 可见。** shallow clone 或未拉 tag 会把 vendored 族的判据退化成「全部首发」。`fetch-depth: 0` 是前提,不是优化。 +- **协议改写触及 1504 处依赖声明。** 它不改变本机解析(pnpm 本来就从 workspace 解析),但改变了发布出去的范围写法。 +- **私有包需要凭据才能安装。** 任何消费方——CI、沙箱 e2e、外部使用者——都要持有 scope 凭据,Landlock 三包也在其中;它们从未发布过,所以没有切断既有的匿名安装路径。 +- **`repository` 指向的组织与运行 workflow 的组织不同。** 用 token 发布不受影响;npm provenance(OIDC)要求二者一致,届时要么把 `repository` 改指过去,要么从它指向的组织发布。 +- **字节可复现性是假定的,没有实测。** 「integrity 相同则跳过」这一态建立在「同一 commit 两次 pack 得到相同字节」之上。目前没有任何东西测量过它:若构建嵌入了绝对路径或时间,重跑会误报失败。在第一次可能被重跑的发布之前实测,若不成立就退到比对 tarball 内逐文件内容哈希。 +- **用较旧的 artifact 重跑 publish 会把 `latest` 拉回旧版。** 发布是按版本决定的,所以在较新版本之后重发较旧的一批,会让稳定 dist-tag 再次指向旧版。排练用的是预发布版本,它永远不占 `latest`。 +- **首发是一次大步。** 九个 vendored 包与整个 dsh 集一次发出,任何 payload 缺陷都会集中在同一次发布里暴露——这正是先用预发布版本把完整链路走一遍的理由。 diff --git a/.agents/notes/proposed/process/2026-08-10-npm-release-sequences.i18n.yaml b/.agents/notes/proposed/process/2026-08-10-npm-release-sequences.i18n.yaml deleted file mode 100644 index 76798fc636..0000000000 --- a/.agents/notes/proposed/process/2026-08-10-npm-release-sequences.i18n.yaml +++ /dev/null @@ -1,6 +0,0 @@ -# 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/proposed/process/2026-08-10-npm-release-sequences.md -2026-08-10-npm-release-sequences.md: bfe4ccaeddee3713445a3ffb77d575e4af207ae2 -2026-08-10-npm-release-sequences.zh.md: 3df42748429ac62e8131bfe22e4ebaafb4943b32 diff --git a/.agents/notes/proposed/process/2026-08-10-npm-release-sequences.md b/.agents/notes/proposed/process/2026-08-10-npm-release-sequences.md deleted file mode 100644 index bfe4ccaedd..0000000000 --- a/.agents/notes/proposed/process/2026-08-10-npm-release-sequences.md +++ /dev/null @@ -1,185 +0,0 @@ -# Agent Note: Private npm publication as three independent sequences - -Status: proposed - -English | [中文](2026-08-10-npm-release-sequences.zh.md) - -## Problem - -This repository holds three unrelated groups of publishable packages and no channel that sends any of them to a registry. - -`packages/*/*` and `apps/*` form the runtime surface of `@deepseek-ai/dsh`; `vendor/*` holds nine rescoped Cordis framework packages, each carrying its upstream version; `native/landlock-run/packages/*` holds Linux platform packages that already have `landlock-run-release.yml`. The three differ in version baseline, change rate, and build requirements: dsh moves with the product, vendor moves only when upstream is re-synced or a local modification changes, and native needs a musl toolchain and one build per architecture. Forcing them through one pipeline means every product release republishes the framework and the native binaries. - -Two hard blockers sit in the current state. All 217 workspace manifests set `private: true`, which npm refuses to publish. The subtler one is 933 hard-written `peerDependencies: "^0.0.1"` entries between sibling dsh packages: `pnpm pack` substitutes the `workspace:` protocol but leaves semver ranges alone, and `^0.0.1` means `>=0.0.1 <0.0.2` — it excludes `0.0.2`, and semver excludes prereleases from a range without a prerelease of its own, so it excludes `0.0.1-rc.1` too. Those 933 entries have never failed only because the version has never left `0.0.1`. - -The existing `scripts/publish-npm-baseline.ts` is a local publication script: it packs and publishes in one process, needs a human to authenticate and retry on their own machine, and excludes vendor from its release set. It cannot be the basis for CI publication, but its tarball payload validation and installed-artifact probes are verified parts. - -## Proposal - -### Three independent sequences - -`packages/`, `vendor/`, and `native/` each get one bump sequence and one publication, sharing no version, no trigger, and no waiting. Releasing dsh does not republish vendor; releasing vendor does not republish native. - -| Sequence | Members | Version baseline | Tag | Workflow | -|---|---|---|---|---| -| dsh | `packages/*/*` + `apps/*` (`@deepseek-ai/dsh` and `@deepseek-ai/dsh-frontend`) | one version for the whole family, `0.0.x` | `dsh-v` | `release.yml` (new) | -| vendored framework | the nine `vendor/*` packages | each package on its own version line | `vendor--v` (one per package) | `release-vendor.yml` (new) | -| native | `native/landlock-run/packages/*` | its own `0.0.x` | `landlock-run-v` | `landlock-run-release.yml` (unchanged) | - -All three publish privately to the `@deepseek-ai` scope on npmjs.com (`npm publish --access restricted`). - -### Versions land in the repository from a local command; CI only checks and uploads - -Each sequence has one `bump and commit` command: derive the target version, write it into the relevant manifests, run `pnpm install --lockfile-only`, self-check immediately, then `git add` the manifests and the lockfile and commit. The published version is therefore readable from the repository, and "which version went out" is never a question. A human creates the tag after the commit merges to master; CI never writes to the repository and needs no write permission. - -The dsh sequence shares one version across the family and accepts `major | minor | patch | x.y.z`. A prerelease version such as `0.0.1-rc.1` drives pack, the installed-artifact probes, and one real private publication end to end first; numbered versions like `0.0.1` and `0.0.2` follow once that passes. The dist-tag decision is the one this repository already makes in `landlock-run-release.yml`: a version with a prerelease segment publishes under `--tag next`, anything else takes `latest`. - -### vendor: publish what changed, and let tags be the ledger - -The vendored packages are decoupled from upstream by their scope but keep their own version lines. The published version is the upstream version with its prerelease segment dropped and its patch incremented: - -| Package | Upstream version | First published version | -|---|---|---| -| `@deepseek-ai/cordis` | 4.0.0-rc.7 | 4.0.1 | -| `@deepseek-ai/cordis-plugin-loader` | 1.0.0-rc.5 | 1.0.1 | -| `@deepseek-ai/cosmokit` | 1.8.1 | 1.8.2 | -| `@deepseek-ai/schemastery` | 3.18.0 | 3.18.1 | -| `@deepseek-ai/cordis-plugin-hmr` | 1.0.15 | 1.0.16 | -| `@deepseek-ai/cordis-plugin-include` | 1.0.4 | 1.0.5 | -| `@deepseek-ai/cordis-plugin-timer` | 1.1.2 | 1.1.3 | -| `@deepseek-ai/cordis-plugin-group` | 1.0.0 | 1.0.1 | -| `@deepseek-ai/cordis-plugin-logger-console` | 1.0.0 | 1.0.1 | - -Only changed packages publish, and the change judgement adds no state file: **each package has its own tag, and that tag records the commit it last published from**. For each package, bump reads the newest `vendor--v*` tag and runs `git diff ..HEAD -- vendor/`; a difference means patch+1, no difference means skip, and a missing tag means the first publication from the table above. The diff considers only paths that reach the tarball (the `files` rules in `scripts/publication-payload.ts`), so editing a comment inside a vendored package does not trigger a release. - -A tag is a commit pointer, not proof of publication — a tag created for a publication that then failed must be recognizable. So bump also asks the registry whether the version that tag names exists, and fails for a human to resolve when it does not, rather than guessing. Querying a private package needs authentication; the check is skipped on a machine that is not logged in and enforced in CI. - -The dependency ranges *inside* the nine vendored packages need no rewrite: `^1.8.1` admits `1.8.2` and `^1.0.0-rc.5` admits `1.0.1`, so patch+1 always lands inside the range. - -### Publication runs only on GitHub, and the registry decides what goes out - -Publication runs only from GitHub Actions; there is no local publication path. That makes the registry check a mandatory CI step instead of something with a bypass for an unauthenticated machine. - -Publish reads no tag and no manifest of "what this release includes". For each member it compares the manifest version against the registry, in three states: - -| State | Action | -|---|---| -| the registry does not have that version | publish | -| the registry has it, and the tarball's sha512 equals the recorded `dist.integrity` | skip: this is a re-run over one artifact | -| the registry has it, and the integrity differs | fail, reporting content changed without a version bump | - -The third state is the point of the rule: it catches code that changed without a version bump. The first two provide idempotence — re-running publish over one artifact republishes nothing and needs no manual selection of packages. - -The same rule resolves the tension between one vendor release carrying several tags and a workflow that can only run from one ref: the workflow never infers which packages to publish from the tag it ran from. The dsh sequence behaves identically with one version: the difference is either the whole set or nothing. - -The third state depends on a reproducible build — packing the same commit twice must produce the same bytes. That must be measured, not assumed: if `pnpm run build` embeds absolute paths or timestamps, integrity drifts while content is unchanged and the third state reports a false failure. Before this lands, pack the same commit twice in CI and compare integrity; if it is not reproducible, compare per-file content hashes inside the tarball instead and exclude the fields that drift. - -### Rewrite workspace-internal references to `workspace:^`, once - -Every reference to a workspace member becomes `workspace:^`, so `pnpm pack` substitutes a range that matches the target version: - -| Surface | Count | Effect | -|---|---|---| -| sibling dsh `peerDependencies` | 933 | `0.0.2` and `0.0.1-rc.1` both get a matching range | -| dep / peer / devDep pointing at vendor | 105 + 221 + 218 | no dsh-side rewrite after a vendor patch+1, and no range that goes stale as vendor increments | - -`scripts/check-workspace-constraints.ts` currently asserts that the vendor peer and dev ranges are equal; both become `workspace:^`, so the assertion still holds but its wording changes with it. - -This is what makes "no dependency rewriting at publication time" possible: publication does one thing, which is packing bytes. - -### Release family objects - -The entity in this domain is a **release family**: a set of packages sharing one version baseline and tag naming that publishes as a unit. Adding a family means adding a family description and one workflow lane, not changing the core. - -| Object | Responsibility | -|---|---| -| `ReleaseFamily` | a family's identity: member discovery, version policy, tag naming, publish target. A new release family lands here | -| `ReleaseMember` | one publishable package: directory, manifest, family, position in publish order | -| `VersionPolicy` | where the version comes from. `SharedSemver` (dsh: one version for the family) and `PerPackageChanged` (vendor: change judged by tag, prerelease dropped, patch incremented) | -| `ReleaseSet` | a family's members in topological order over `dependencies`, ties broken by package name for determinism | -| `PackedBundle` | the tarballs plus `publish-order.txt` and its metadata: the only handoff between pack and publish | -| `PublishTarget` | registry, access, dist-tag, credential source. The dist-tag derives from the version's shape | -| `VersionInvariant` | the family's versions agree; publication runs from the family's tag; the tag version equals the package version; the target version is absent from the registry | -| `PayloadInvariant` | tarball content validation, reusing `scripts/publication-payload.ts` | -| `InstalledProbe` | a throwaway consumer outside the repository installs from the tarballs and drives the installed entry with plain Node: `dsh --version`, `dsh --dump-default-config`, and one TUI startup to ready and exit. Moved over from `scripts/publish-npm-baseline.ts` | - -### Workflow shape: pack everything at once, then publish as one set - -The shape comes from the reference flow (`release.yml` and `scripts/pack-release.mjs` in node-addon-require-builtin): the `pack` job walks the whole release set once, running `pnpm --dir pack --pack-destination ` per member, writes `publish-order.txt`, and uploads that directory as **one** artifact; the `publish` job downloads that artifact and runs `npm publish` per entry in `publish-order.txt`. The release set is one unit — half the packages can never reach the registry while the other half is still building. - -The `pack` job carries no credentials: install, verify, build, pack, installed-artifact verification, upload-artifact. The `publish` job sits behind the `npm-publish` environment for human approval, runs `setup-node` and `download-artifact` only, and **neither checks out nor builds** — it uploads the bytes pack produced. Checkout uses `fetch-depth: 0`, because the vendor change judgement reads history and tags. - -The environment is the only brake in the flow: pack has no credentials and can be rehearsed freely, and only publish stops for approval. GitHub needs an `NPM_TOKEN` secret (an automation token with publish rights on the scope) and an `npm-publish` environment (required reviewers, allowed tags limited to `dsh-v*`, `vendor-*`, and `landlock-run-v*`). - -### Pull requests run as far as pack - -The reference flow only has `workflow_dispatch`, so it verifies nothing on a pull request. Here `pull_request` runs the full pack: install, verify, build, pack per member, upload the tarball artifact. What it proves is that this release set still packs completely; it uses no credentials, touches no registry, and runs for pull requests from forks. The artifacts' own correctness is covered by existing tests and is not repeated at this layer. - -The publication path is exercised from master: `push: master` runs the same pack rehearsal as a post-merge regression, and `workflow_dispatch` with `publish: true` performs a real publication from a tag. - -### Repository changes - -| Item | Content | -|---|---| -| release-set manifests | drop `private: true`; add `publishConfig.access: restricted` and `repository` (`git+https://github.com/deepseek-ai/deepseek-harness.git` plus each package's `directory`) | -| release-set boundary | every member of `packages/*/*`, `apps/*`, and `vendor/*`; no smaller selection | -| dependency protocol | workspace-internal references become `workspace:^`, with `check-workspace-constraints.ts` updated | -| root `AGENTS.md` | it states that vendored packages are rescoped and `private: true`; vendor now publishes, so that convention changes | -| `vendor/README.md` | its manifest table records the upstream version, kept distinct from the version we publish | -| the three native packages | `publishConfig.access` moves from `public` to `restricted`; they have never been published, so no anonymous install path exists to preserve | - -### Relationship to the existing proposal - -This Agent Note replaces the version scheme and the release-set boundary in [artifact-first npm baseline publication](2026-08-04-artifact-first-npm-baseline-publication.md): its `--` prerelease versions and `dev-` dist-tag are not adopted, and vendor is no longer excluded from the release set. What both agree on stays: pack and publish are separate, publish consumes only verified tarballs, and the payload and installed-artifact probes are release gates. - -## Alternatives considered - -**A `--` version.** Planned for continuous dev publication. It conflicts with keeping the published version in the repository: the version embeds a commit SHA, and writing the version back produces a new commit, so the SHA can only name the parent commit that was published and the link needs a convention to explain it. With numbered versions, a prerelease such as `0.0.1-rc.1` already covers "verify first, then release". - -**A `vendor/published.json` ledger recording each package's published version and commit.** This preceded the tag design. It adds a state file that must not drift from the registry. A per-package tag gives the same commit pointer, and the tag has to exist anyway, so it introduces no second copy of the state. - -**Event-level tags (`vendor-r1`, `vendor-r2`).** Prepared for one release event carrying several package versions. Once the registry decides what publishes, the workflow no longer infers the set from the tag, so per-package tags suffice — and each one names its own package's real version. - -**Putting the nine vendored packages on one `4.0.x` line.** It removes change detection, but cosmokit would jump from `1.8.1` to `4.0.1` and lose its upstream lineage; the upstream ranges inside the nine (`^1.8.1` and friends) would stop matching immediately, forcing a rewrite of the vendored manifests. - -**Incrementing every vendored package on every vendor release, with no change detection.** The least machinery, at the cost of new version numbers for packages whose content is byte-identical to the previous release. Tags reduce change detection to reading one tag and running one diff, which is not worth trading for inflated version numbers. - -**Deciding "already published" from the version alone, without comparing content.** The reference flow queries no registry at all: publish uploads each tarball and npm rejects a duplicate version. Skipping on the version alone misses code that changed without a bump, which is the only failure that quietly leaves stale bytes on the registry. The cost is a registry query and a dependency on reproducible builds. - -**Verifying only the packed install, with no local registry.** This is what the reference flow does: unpack the tarballs into a tree and drive it with plain Node. It bypasses version-range resolution, so in principle it cannot prove that 200-odd interdependent packages install from a registry. Running a local registry in CI to cover that layer was proposed and rejected: artifact correctness is already covered by existing tests, the publication path is exercised by the master rehearsal, and a pull request only needs to prove the release set packs. - -**Selecting a subset by entry closure.** Crawling `dependencies` from `@deepseek-ai/dsh` and `@deepseek-ai/dsh-frontend` yields 156 packages, 61 fewer than the whole set. But this repository's plugins are mounted by name from `cordis.yml` rather than imported: `vendor/cordis-plugin-group` and `vendor/cordis-plugin-logger-console` fall outside the dependency closure while being required at runtime. Selecting by code dependency fails as "the consumer installs it and it will not start", and it would need a standing proof that no mounted package was missed. The release set is therefore all of `packages/*/*`, `apps/*`, and `vendor/*`; under a private scope the extra packages are invisible outside the organization. `python/`, the root `examples/`, `docs/`, and `website/` are not members. - -**Extending `scripts/publish-npm-baseline.ts`.** It is a local publication script that packs and publishes in one process, the opposite of separating credential-free packing from protected publication. Its verified parts — payload validation and installed-artifact probes — are reused so `pnpm run duplication` does not report clones. - -**One workflow with a `family` input.** Two version models in one file forks the concurrency group, the tag prefix, and the rehearsal triggers into conditional expressions. One file per family is both shorter and easier to read. - -**Rewriting dependency ranges at publication time.** Compared with rewriting them to `workspace:^` once, the rewrite runs only in CI, a local `pnpm install` cannot show whether it is correct, and it repeats on every release. - -**Running bump in CI and pushing the version back.** It needs repository write permission for the workflow, and a version commit on the release branch races human commits. The reference flow leaves bump and commit to local commands and lets CI check and upload. - -## Acceptance criteria - -1. The three sequences release independently: releasing dsh modifies no vendor or native manifest, and the converse holds. -2. `pnpm release:dsh ` performs bump and commit in one command, and the resulting commit carries the family's manifests and the lockfile and self-checks immediately. -3. `pnpm release:vendor` increments the patch only for packages whose tarball content changed since their `vendor--v*` tag, and leaves the manifests of unchanged packages alone. -4. `pull_request` runs the full pack and produces the tarball artifact, with no credentials and no access to a real registry, including for pull requests from forks. -5. `push: master` runs the same pack rehearsal; a real publication can only come from `workflow_dispatch` with `publish: true` from that family's tag. -6. Re-running publish over one artifact republishes no existing version, and when a version exists whose tarball integrity differs, publish fails and names the package. -7. A throwaway consumer outside the repository installs `@deepseek-ai/dsh@0.0.1-rc.1` and drives `--version`, `--dump-default-config`, and one TUI startup with plain Node. -8. Every workspace-internal reference is `workspace:^`, the packed tarballs carry no `workspace:` remnant, and no range points at a version that does not exist. -9. No release-set member sets `private: true`, and each one sets `publishConfig.access: restricted`. - -## Risks - -**Tags drifting from the registry.** A tag created for a publication that then failed makes the next bump treat the package as published. Bump asks the registry whether the version the tag names exists and fails when it does not; on a machine that is not logged in to the private registry that check is skipped, and only the same check in CI catches it. - -**The change judgement depends on visible tags.** A shallow clone, or a checkout without tags, breaks the vendor judgement and degrades it to "publish everything for the first time". `fetch-depth: 0` is a precondition of the judgement, not an optimization. - -**`workspace:^` touches a large surface.** It rewrites 1477 dependency declarations at once. It does not change local resolution — pnpm already resolves from the workspace — but it changes the ranges that go out, and the workspace constraint gate changes with it. - -**The visibility cost of private packages.** After `--access restricted`, every consumer — CI, sandbox e2e, and outside users — needs scope credentials to install. The three native packages move to `restricted` as well; they have never been published, so no existing anonymous install path is cut off. - -**The `repository` field names a different organization than the one running the workflow.** The release set points consumers at `github.com/deepseek-ai/deepseek-harness`, which is not where these workflows run. Token-based publication is unaffected; npm provenance (OIDC) requires the two to agree, so adopting it means either repointing `repository` or publishing from the organization it names. - -**The first publication is one large step.** Nine vendored packages and the whole dsh set publish at once, so any payload defect surfaces in a single release. Driving the complete path with `0.0.1-rc.1` first is the only mitigation, which is why numbered versions wait for that to pass. diff --git a/.agents/notes/proposed/process/2026-08-10-npm-release-sequences.zh.md b/.agents/notes/proposed/process/2026-08-10-npm-release-sequences.zh.md deleted file mode 100644 index 3df4274842..0000000000 --- a/.agents/notes/proposed/process/2026-08-10-npm-release-sequences.zh.md +++ /dev/null @@ -1,188 +0,0 @@ -# Agent Note: 三条独立序列的私有 NPM 发布 - -Status: proposed - -[English](2026-08-10-npm-release-sequences.md) | 中文 - -## 问题 - -这个仓库有三组互不相干的可发布包,但没有任何发布通道把它们送上 registry。 - -`packages/*/*` 与 `apps/*` 组成 `@deepseek-ai/dsh` 的运行时闭包;`vendor/*` 是九个 rescope 过的 Cordis 框架包,各自带着上游的版本号;`native/landlock-run/packages/*` 是 Linux 平台包,已有自己的 `landlock-run-release.yml`。三组的版本基线、变更节奏和构建要求都不同:dsh 随产品迭代,vendor 只在同步上游或改动本地修改时才动,native 需要 musl 工具链和逐架构构建。把它们塞进一条发布流水线,等于每次产品发版都要重发框架和原生二进制。 - -当前状态还有两处硬门。全部 217 个 workspace manifest 都是 `private: true`,直接 `npm publish` 发不出去。更隐蔽的是 933 条 dsh 兄弟包之间硬写的 `peerDependencies: "^0.0.1"`:`pnpm pack` 只替换 `workspace:` 协议,不动语义范围,而 `^0.0.1` 等于 `>=0.0.1 <0.0.2`——发 `0.0.2` 落不进去,发 `0.0.1-rc.1` 也落不进去(semver 规定不带预发布段的范围排除预发布版本)。这 933 条至今没出事,只因为版本一直停在 `0.0.1`。 - -本仓已有的 `scripts/publish-npm-baseline.ts` 是本机发布脚本:它把 pack 与 publish 放进同一个进程,需要人工在本机完成认证与重试,且把 vendor 排除在发布集之外。它不能作为 CI 发布的基础,但其中的 tarball payload 校验与已安装产物探针是验证过的零件。 - -## 提案 - -### 三条独立序列 - -`packages/`、`vendor/`、`native/` 各自一条 bump 序列、各自一次发布,不共享版本号、不共享触发、不互相等待。发 dsh 不重发 vendor,发 vendor 不重发 native。 - -| 序列 | 成员 | 版本基线 | tag | workflow | -|---|---|---|---|---| -| dsh | `packages/*/*` + `apps/*`(`@deepseek-ai/dsh` 与 `@deepseek-ai/dsh-frontend`) | 全族一个 `0.0.x` | `dsh-v<版本>` | `release.yml`(新增) | -| vendored framework | `vendor/*` 九个包 | 每包各自的上游版本线 | `vendor-<包名>-v<版本>`(每包一个) | `release-vendor.yml`(新增) | -| native | `native/landlock-run/packages/*` | 自己的 `0.0.x` | `landlock-run-v<版本>` | `landlock-run-release.yml`(现状不动) | - -三组一律发到 npmjs.com 的 `@deepseek-ai` scope 下的**私有包**(`npm publish --access restricted`)。native 三个包现在写的是 `access: public`,要改成 `restricted`。 - -### 版本由本地命令写进仓库,CI 只核对与上传 - -每条序列有一条 `bump and commit` 命令:算出目标版本 → 写进相关 manifest → `pnpm install --lockfile-only` → 立刻自检 → `git add` manifest 与 lockfile → commit。发布版本因此在仓库里查得到,不存在「发出去的是哪个版本说不清楚」。tag 由人工在合入 master 后打,CI 不写仓库、不需要写权限。 - -dsh 序列全族共用一个版本,接受 `major | minor | patch | x.y.z` 三种入参与显式版本号。先用 `0.0.1-rc.1` 这类预发布号把 pack、仓外安装探针、真实私有发布跑通一遍,验证通过后再发 `0.0.1`、`0.0.2` 这样的数字版本。dist-tag 沿用本仓 `landlock-run-release.yml` 已有的判定:版本带预发布段就 `--tag next`,否则进 `latest`。 - -### vendor:谁改了谁发版,tag 就是账本 - -vendor 九包加了 scope 之后与上游脱钩,但保留各自的版本线。发布版本 = 去掉预发布段后 patch+1,首发目标: - -| 包 | 上游版本 | 首发版本 | -|---|---|---| -| `@deepseek-ai/cordis` | 4.0.0-rc.7 | 4.0.1 | -| `@deepseek-ai/cordis-plugin-loader` | 1.0.0-rc.5 | 1.0.1 | -| `@deepseek-ai/cosmokit` | 1.8.1 | 1.8.2 | -| `@deepseek-ai/schemastery` | 3.18.0 | 3.18.1 | -| `@deepseek-ai/cordis-plugin-hmr` | 1.0.15 | 1.0.16 | -| `@deepseek-ai/cordis-plugin-include` | 1.0.4 | 1.0.5 | -| `@deepseek-ai/cordis-plugin-timer` | 1.1.2 | 1.1.3 | -| `@deepseek-ai/cordis-plugin-group` | 1.0.0 | 1.0.1 | -| `@deepseek-ai/cordis-plugin-logger-console` | 1.0.0 | 1.0.1 | - -只发改动过的包。变更判据不引入新的状态文件:**每包一个 tag,tag 就是「上次发布到哪个 commit」的记录**。bump 对每个包取最新的 `vendor-<包名>-v*` tag,`git diff <该 tag>..HEAD -- vendor/<目录>` 有差异就 patch+1,没差异就跳过;查不到 tag 就按上表首发。差异只看会进 tarball 的路径(复用 `scripts/publication-payload.ts` 的 `files` 规则),改动 vendor 内的注释不触发发版。 - -tag 只是 commit 指针,不是「已发布」的证明——打了 tag 而 publish 失败的情况必须能识别。所以 bump 还要向 registry 核对「tag 所指版本确实存在」,不一致时明确失败交人处理,不让脚本猜。私有包查询需要鉴权,本机未登录时跳过这条核对,CI 里强制执行。 - -vendor 九包**内部**的依赖范围不用改:`^1.8.1` 容纳 `1.8.2`、`^1.0.0-rc.5` 容纳 `1.0.1`,patch+1 永远落在范围内。 - -### publish 只在 GitHub 执行,用 registry 状态决定发什么 - -发布只从 GitHub Actions 执行,没有本机发布路径。这让「向 registry 核对」成为 CI 里的强制步骤,不需要为本机未鉴权的情况留旁路。 - -publish 不读 tag、不读任何清单,对发布集里每个包比较 manifest 版本与 registry 上的已发布状态,按三态处置: - -| 状态 | 处置 | -|---|---| -| registry 上没有该版本 | 发布 | -| 已有该版本,且 tarball 的 sha512 与 registry 记录的 `dist.integrity` 相同 | 跳过,属于同一批产物的重跑 | -| 已有该版本,但 integrity 不同 | 失败退出,报「内容已变但版本未 bump」 | - -第三态是这条规则的目的:它拦住「改了代码却没 bump 版本」。前两态给出的是幂等——同一个 artifact 重跑 publish 不会重复发布,也不需要人工挑拣包。 - -这条规则同时解决了一次发布事件产生多个 vendor tag、而 workflow 只能从一个 ref 触发的矛盾:workflow 不需要从 tag 推断本次该发哪些包。dsh 序列同构处理,它只有一个版本,差集要么全发要么全跳。 - -第三态依赖同输入构建可复现(同一 commit 两次 pack 得到相同字节)。这一点必须实测确认,不能假定:`pnpm run build` 的产物若嵌入绝对路径或时间,integrity 就会在内容未变时漂移,第三态会误报。落地前先在 CI 上对同一 commit 连跑两次 pack 比对 integrity;若不可复现,则把比较下沉到 tarball 内的逐文件内容哈希,并明确排除导致漂移的字段。 - - -### 一次性把 workspace 内部引用改成 `workspace:^` - -仓库里所有指向 workspace 成员的引用统一成 `workspace:^`,由 `pnpm pack` 在发布时替换成匹配目标版本的范围。 - -| 面 | 数量 | 效果 | -|---|---|---| -| dsh 兄弟包 `peerDependencies` | 933 | 发 `0.0.2` 或 `0.0.1-rc.1` 都自动得到匹配的范围 | -| 指向 vendor 的 dep / peer / devDep | 105 + 221 + 218 | vendor patch+1 后不需要改写 dsh 侧引用,范围也不会随 vendor 递增而过期 | - -`scripts/check-workspace-constraints.ts` 现在断言 vendor peer 与 dev 的范围相等,改后两边都是 `workspace:^`,断言仍成立但语义要随之更新。 - -这条是「发布期不做任何依赖改写」的前提:发布期只做一件事——pack 出字节。 - -### 发布族对象 - -领域里的实体是**发布族**:一组共享版本基线与 tag 前缀、可整体发布的包。新增一族等于新增一份族描述加一条 workflow lane,不改核心。 - -| 对象 | 职责 | -|---|---| -| `ReleaseFamily` | 一族的身份:成员发现规则、版本策略、tag 命名、publish 目标。新增发布族在此落地 | -| `ReleaseMember` | 一个可发布包:目录、manifest、族归属、发布顺序位次 | -| `VersionPolicy` | 版本从哪来。`SharedSemver`(dsh:全族一个版本)与 `PerPackageChanged`(vendor:按 tag 判变更、去预发布段后 patch+1) | -| `ReleaseSet` | 一族成员的拓扑序,按 `dependencies` 排、同层按包名排,保证确定性 | -| `PackedBundle` | tarball 集合 + `publish-order.txt` + 元数据清单,是 pack 与 publish 之间唯一的交接物 | -| `PublishTarget` | registry、access、dist-tag、凭据来源。dist-tag 由版本形态派生 | -| `VersionInvariant` | 族内版本自洽;publish 必须从对应 tag 跑;tag 版本等于包版本;待发版本不得已存在于 registry | -| `PayloadInvariant` | tarball 内容校验,复用 `scripts/publication-payload.ts` | -| `InstalledProbe` | 仓外临时 consumer 从 tarball 安装后,用普通 Node 驱动已安装入口:`dsh --version`、`dsh --dump-default-config`、起一次 TUI 到就绪后退出。实现从 `scripts/publish-npm-baseline.ts` 搬运复用 | - -### workflow 形状:一次性 pack 全部,再统一 publish - -照参照流程(node-addon-require-builtin 的 `release.yml` 与 `scripts/pack-release.mjs`)的形状:`pack` job 一趟遍历整个发布集,逐包 `pnpm --dir <目录> pack --pack-destination <同一个目录>`,写出 `publish-order.txt`,整个目录作为**一份** artifact 上传;`publish` job 下载那一份 artifact,按 `publish-order.txt` 逐个 `npm publish`。发布集是一个整体,不存在「一半的包发出去了、另一半还在构建」。 - -`pack` job 无凭据:install → verify → build → pack → 打包后安装验证 → upload-artifact。`publish` job 挂 `environment: npm-publish` 人工审批,只 `setup-node` 加 `download-artifact`,**不 checkout、不 build**,上传的就是 pack 出来的同一份字节。checkout 用 `fetch-depth: 0`,vendor 的变更判据需要历史与 tag。 - -`environment` 是整条流程唯一的刹车:pack 无凭据、可随意排练;只有 publish 会停在审批上。GitHub 侧需要 `NPM_TOKEN` secret(对该 scope 有发布权限的 automation token)与 `npm-publish` environment(required reviewers,允许的 tag 限制为 `dsh-v*`、`vendor-*`、`landlock-run-v*`)。 - -### PR 阶段跑到 pack 为止 - -参照流程只有 `workflow_dispatch`,PR 上什么都验证不了。本仓在 `pull_request` 上跑完整的 pack:install → verify → build → 逐包 pack → 上传 tarball artifact。它证明的是「这个发布集现在能完整打出来」,无凭据、不碰任何 registry,fork 发来的 PR 也能跑。产物本身的正确性由既有测试覆盖,不在 PR 这一层重复。 - -发布路径的测试走 master:`push: master` 跑同一套 pack 排练作为合入后回归,`workflow_dispatch` 带 `publish: true` 从 tag 走真实发布。 - - - -### 仓库改造项 - -| 项 | 内容 | -|---|---| -| 发布集 manifest | 去掉 `private: true`,补 `publishConfig.access: restricted` 与 `repository`(`git+https://github.com/deepseek-ai/deepseek-harness.git` + 各自 `directory`) | -| 发布集边界 | `packages/*/*` + `apps/*` + `vendor/*` 全部成员,不另挑子集 | -| 依赖协议 | workspace 内部引用统一 `workspace:^`,并更新 `check-workspace-constraints.ts` | -| 根 `AGENTS.md` | 现在写着 vendored 包是 rescope 过且 `private: true`,vendor 要发布,这条约定要改 | -| `vendor/README.md` | manifest 表补记上游版本,与我们发布的版本区分开 | -| native 三包 | `publishConfig.access` 从 `public` 改 `restricted`;它们尚未发布过,所以没有匿名安装路径要保 | - -### 与既有提案的关系 - -本 Note 取代 [以产物为先的 NPM 基线发布](2026-08-04-artifact-first-npm-baseline-publication.md) 中的版本方案与发布集边界两部分:那篇的 `-<时间戳>-<短 SHA>` 预发布版本与 `dev-` dist-tag 不再采用,vendor 也不再排除在发布集之外。两篇一致的部分保留:pack 与 publish 分离、publish 只消费已验证的 tarball、payload 与安装后探针作为发布门。 - -## 考虑过的替代方案 - -**`-<时间戳>-<短 SHA>` 版本号。** 曾计划用它做持续 dev 发布。它与「版本必须落进代码库」冲突:版本内嵌 commit SHA,而把版本写回 manifest 会产生新的 commit,SHA 只能指向被发布的父 commit,链条要靠约定解释。改用数字版本递增后,`0.0.1-rc.1` 这类预发布号已经足够覆盖「先验证再正式发」的需求。 - -**用 `vendor/published.json` 账本记录每包的已发版本与 commit。** 这是 tag 方案之前的设计,需要新增一份状态文件并保证它与 registry 不漂移。per-package tag 提供同样的 commit 指针,且 tag 本来就要打,不引入第二处状态。 - -**事件级 tag(`vendor-r1`、`vendor-r2`)。** 为「一次发布事件多个包版本」准备的。改用 registry 差集决定发布集之后,workflow 不再需要从 tag 推断本次发布哪些包,per-package tag 就够用,而且每个 tag 携带的是它自己那个包的真实版本。 - -**vendor 九包统一到 `4.0.x` 一条线。** 省掉变更检测,但 cosmokit 会从 `1.8.1` 跳到 `4.0.1`,上游血缘全部丢失;且九包内部的上游依赖范围(`^1.8.1` 之类)会立刻失配,必须改写 vendored manifest。 - -**vendor 每次全部 patch+1,不做变更检测。** 最省事,代价是没有改动的包也拿到新版本号、内容与上一版逐字节相同。tag 方案让变更检测的成本降到「取一个 tag 加一次 diff」,不值得为省这点而让版本号虚涨。 - -**只按版本号判断是否已发布,不比对内容。** 参照流程根本不查 registry,publish 直接逐个上传,重复版本由 npm 报错拦下。只按版本号跳过则会漏掉「改了代码没 bump」这一类,而这是唯一会安静地把旧字节留在 registry 上的错误。代价是引入对 registry 的查询与对构建可复现性的依赖。 - -**只做打包后安装验证,不起本地 registry。** 参照流程就是这样:解包 tarball 组树、普通 Node 驱动。它绕过版本范围解析,理论上验证不了「200 多个互相依赖的包能不能从 registry 装起来」。曾提议在 CI 里起本地 registry 补这一层,被否:产物验证已由既有测试覆盖,发布路径的验证放在 master workflow 的排练里,PR 只需证明发布集能完整打出来。 - -**以 `scripts/publish-npm-baseline.ts` 为基础扩展。** 它是本机发布脚本,把 pack 与 publish 放在同一进程,与「无凭据 pack、受保护 publish」的分离相反。它验证过的零件(payload 校验、已安装产物探针)搬运复用,避免 `pnpm run duplication` 判重复。 - -**按入口闭包挑一部分包发。** 从 `@deepseek-ai/dsh` 与 `@deepseek-ai/dsh-frontend` 沿 `dependencies` 爬得到 156 个包,比全量少 61 个。但本仓的插件是 cordis.yml 按名字挂载的,不是被 import 的:`vendor/cordis-plugin-group` 与 `vendor/cordis-plugin-logger-console` 就落在依赖闭包之外,而它们是运行时必需。照代码依赖挑,漏掉的表现是消费方装完起不来,且要额外证明「没漏任何挂载项」。发布集因此取 `packages/*/*` + `apps/*` + `vendor/*` 全部;私有 scope 下多几个包不对外可见。`python/`、根 `examples/`、`docs/` 与 `website/` 不是发布集成员。 - -**一个 workflow 用 `family` 输入选择序列。** 两套版本模型塞进一个文件会让 concurrency group、tag 前缀、排练触发条件全部分叉成条件表达式。一族一个文件更短也更好读。 - -**在发布期改写依赖范围。** 与一次性改成 `workspace:^` 相比,改写逻辑只在 CI 执行过,本机 `pnpm install` 看不见它是否正确,且每次发布都要重跑一遍。 - -**CI 里执行 bump 并把版本推回仓库。** 需要给 workflow 仓库写权限,且发布分支上的版本提交会与人的提交竞争。参照流程把 bump 与 commit 留在本地命令,CI 只核对与上传。 - -## 验收标准 - -1. 三条序列各自可独立发布:发 dsh 不改动 vendor 与 native 的任何 manifest,反之亦然。 -2. `pnpm release:dsh <版本>` 一条命令完成 bump 与 commit,产出的 commit 含全族 manifest 与 lockfile,且立刻自检通过。 -3. `pnpm release:vendor` 只对「自其 `vendor-<包名>-v*` tag 以来 tarball 内容有变化」的包 patch+1,无变化的包 manifest 不被改动。 -4. `pull_request` 上跑完整 pack 并产出 tarball artifact,无凭据、不访问真实 registry,fork 的 PR 也能跑。 -5. `push: master` 跑同一套 pack 排练;真实发布只能由 `workflow_dispatch` 带 `publish: true` 从对应 tag 触发。 -6. publish 重跑同一 artifact 不重复发布已存在的版本;当某个版本已存在而 tarball integrity 不同时,publish 失败并指明是哪个包。 -7. 仓外临时 consumer 安装 `@deepseek-ai/dsh@0.0.1-rc.1` 后,用普通 Node 能跑通 `--version`、`--dump-default-config` 与一次 TUI 启动。 -8. 所有 workspace 内部引用为 `workspace:^`,且 pack 出的 tarball 里没有任何 `workspace:` 残留、没有指向不存在版本的范围。 -9. 发布集内没有 `private: true`,每个成员都有 `publishConfig.access: restricted`。 - -## 风险 - -**tag 与 registry 漂移。** 打了 tag 但 publish 失败,会让下一次 bump 误判该包已发布。缓解手段是 bump 向 registry 核对 tag 所指版本,不一致就失败退出;但本机未登录私有 registry 时这条核对被跳过,此时误判只能由 CI 的同一条核对拦下。 - -**变更判据依赖 tag 可见。** shallow clone 或未拉取 tag 会让 vendor 的判据失效并退化成「全部首发」。`fetch-depth: 0` 是这条判据的前提,不是优化。 - -**`workspace:^` 改动面大。** 一次触及 1477 处依赖声明。它不改变本机解析行为(pnpm 本来就从 workspace 解析),但会改变发布出去的范围写法,且要同步更新 workspace 约束门。 - -**私有包的可见性代价。** `--access restricted` 之后,任何消费方(含 CI、沙箱 e2e、外部使用者)都必须持有 scope 凭据才能安装。native 三包一并转 `restricted`;它们尚未发布过,因此没有既有的匿名安装路径被切断。 - -**`repository` 指向的组织与运行 workflow 的组织不一致。** 发布集让消费方指向 `github.com/deepseek-ai/deepseek-harness`,而这些 workflow 并不跑在那里。用 token 发布不受影响;一旦改用 npm provenance(OIDC),npm 会要求二者一致,届时要么把 `repository` 改指过去,要么从它指向的组织发布。 - -**首发一次性放大。** vendor 首发九包、dsh 首发全闭包,任何 payload 缺陷都会在同一次发布里暴露。用 `0.0.1-rc.1` 先跑一遍完整链路是唯一的缓解手段,正式版本号留给验证通过之后。 diff --git a/.github/workflows/landlock-run-release.yml b/.github/workflows/landlock-run-release.yml index 7d78e98bc6..8448af1ad1 100644 --- a/.github/workflows/landlock-run-release.yml +++ b/.github/workflows/landlock-run-release.yml @@ -172,5 +172,7 @@ jobs: tag_args=() case "$version" in *-*) tag_args=(--tag next);; esac while IFS= read -r tarball; do - npm publish "dist/npm/${tarball}" --access public "${tag_args[@]}" + # No --access: publishConfig.access in each manifest decides, and a + # command-line flag would override it. + npm publish "dist/npm/${tarball}" "${tag_args[@]}" done < dist/npm/publish-order.txt diff --git a/.github/workflows/release-vendor.yml b/.github/workflows/release-vendor.yml index dc778f3d21..c8af47251e 100644 --- a/.github/workflows/release-vendor.yml +++ b/.github/workflows/release-vendor.yml @@ -23,7 +23,9 @@ permissions: contents: read concurrency: - group: ${{ github.workflow }} + # Pack runs per ref so concurrent pull requests never displace each + # other; the publish job below serializes the shared dist-tag state. + group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: false env: @@ -96,9 +98,11 @@ jobs: needs: pack runs-on: ubuntu-24.04 environment: npm-publish + concurrency: + group: Release-publish + cancel-in-progress: false permissions: contents: read - id-token: write steps: # Checkout and install carry the release scripts only; no build step. - uses: actions/checkout@v6 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6c7a7489f3..7659b3b5a3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -23,8 +23,9 @@ permissions: contents: read concurrency: - # dist-tags are shared registry state; never race two release runs. - group: ${{ github.workflow }} + # Pack runs per ref so concurrent pull requests never displace each + # other; the publish job below serializes the shared dist-tag state. + group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: false env: @@ -103,9 +104,11 @@ jobs: # Required reviewers and the allowed tags live on the environment; this is # the only step in the sequence that can write to the registry. environment: npm-publish + concurrency: + group: Release-publish + cancel-in-progress: false permissions: contents: read - id-token: write steps: # Checkout and install carry the release scripts only. There is no build # step: publication uploads the bytes the pack job produced. diff --git a/apps/cli/package.json b/apps/cli/package.json index 71f64a0f41..b8f0887ac6 100644 --- a/apps/cli/package.json +++ b/apps/cli/package.json @@ -20,10 +20,10 @@ ], "license": "BSD-3-Clause", "dependencies": { - "@deepseek-ai/cordis-plugin-hmr": "workspace:*", - "@deepseek-ai/cordis-plugin-include": "workspace:*", - "@deepseek-ai/cordis-plugin-loader": "workspace:*", - "@deepseek-ai/cordis-plugin-timer": "workspace:*", + "@deepseek-ai/cordis-plugin-hmr": "workspace:^", + "@deepseek-ai/cordis-plugin-include": "workspace:^", + "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis-plugin-timer": "workspace:^", "@deepseek-ai/dsh-agent-tool-mode": "workspace:^", "@deepseek-ai/dsh-app-boot": "workspace:^", "@deepseek-ai/dsh-base": "workspace:^", diff --git a/packages/bundle/base/package.json b/packages/bundle/base/package.json index dc54c75012..9c5fc2a5a8 100644 --- a/packages/bundle/base/package.json +++ b/packages/bundle/base/package.json @@ -41,8 +41,8 @@ } }, "dependencies": { - "@deepseek-ai/cordis-plugin-hmr": "workspace:*", - "@deepseek-ai/cordis-plugin-timer": "workspace:*", + "@deepseek-ai/cordis-plugin-hmr": "workspace:^", + "@deepseek-ai/cordis-plugin-timer": "workspace:^", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-agent-default-model": "workspace:^", "@deepseek-ai/dsh-agent-loop": "workspace:^", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 16602cc946..646244da69 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -130,16 +130,16 @@ importers: specifier: workspace:^ version: link:../../vendor/cordis '@deepseek-ai/cordis-plugin-hmr': - specifier: workspace:* + specifier: workspace:^ version: link:../../vendor/hmr '@deepseek-ai/cordis-plugin-include': - specifier: workspace:* + specifier: workspace:^ version: link:../../vendor/include '@deepseek-ai/cordis-plugin-loader': - specifier: workspace:* + specifier: workspace:^ version: link:../../vendor/loader '@deepseek-ai/cordis-plugin-timer': - specifier: workspace:* + specifier: workspace:^ version: link:../../vendor/timer '@deepseek-ai/dsh-agent-tool-mode': specifier: workspace:^ @@ -1205,10 +1205,10 @@ importers: packages/bundle/base: dependencies: '@deepseek-ai/cordis-plugin-hmr': - specifier: workspace:* + specifier: workspace:^ version: link:../../../vendor/hmr '@deepseek-ai/cordis-plugin-timer': - specifier: workspace:* + specifier: workspace:^ version: link:../../../vendor/timer '@deepseek-ai/dsh-agent': specifier: workspace:^ diff --git a/scripts/check-workspace-constraints.ts b/scripts/check-workspace-constraints.ts index 30afce1e9f..cfc10fda49 100644 --- a/scripts/check-workspace-constraints.ts +++ b/scripts/check-workspace-constraints.ts @@ -378,8 +378,10 @@ function checkHierarchyShape(): string[] { } function checkRepositoryVersion(): string[] { - if (repositoryVersion && /^\d+\.\d+\.\d+$/.test(repositoryVersion)) return [] - return ['package.json: version must be stable X.Y.Z'] + // The root carries the dsh release family's version, so a prerelease such as + // 0.0.1-rc.1 is a valid state between `release:dsh` and its publication. + if (repositoryVersion && /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(repositoryVersion)) return [] + return ['package.json: version must be X.Y.Z with an optional prerelease segment'] } /** Dependency sections whose ranges reach a published tarball or a local install. */ diff --git a/scripts/release/bump.ts b/scripts/release/bump.ts index 9755fd00c4..0f50ea6a9c 100644 --- a/scripts/release/bump.ts +++ b/scripts/release/bump.ts @@ -1,13 +1,13 @@ /** * Bump one release family's version and commit it, so the published version is * readable from the repository rather than derived inside CI - * ([rationale](../../.agents/notes/proposed/process/2026-08-10-npm-release-sequences.md)). + * ([rationale](../../.agents/notes/implemented/process/2026-08-10-npm-release-sequences.md)). * - * The dsh family shares one version: `major`, `minor`, `patch`, or an explicit - * `x.y.z` (including a prerelease such as `0.0.1-rc.1`). The vendored family - * has one version line per package and publishes only what changed since that - * package's own `vendor--v*` tag, which is the record of the commit it - * last published from. + * The dsh family shares one version across its members and the workspace root: + * `major`, `minor`, `patch`, or an explicit `x.y.z` (including a prerelease such + * as `0.0.1-rc.1`). The vendored family has one version line per package and + * publishes only what changed since that package's own `vendor--v*` + * tag, which is the record of the commit it last published from. * * The version lands in the manifests, the lockfile follows, and a human creates * the tag after the commit merges. CI never writes to the repository. @@ -17,14 +17,39 @@ import { readFileSync, writeFileSync } from 'node:fs' import { join, matchesGlob } from 'node:path' import { parseArgs } from 'node:util' import { releaseFamily, type ReleaseFamily, type ReleaseMember } from './families.ts' -import { capture } from './process.ts' +import { attempt, capture, isEntry } from './process.ts' /** Files npm publishes whether or not `files` lists them. */ const ALWAYS_PUBLISHED = ['package.json', 'README*', 'LICENSE*', 'LICENCE*'] as const +/** + * Inputs that decide what a built payload contains. A package whose `files` + * selects `lib/` publishes build output that git does not track, so a change to + * the sources or the build configuration changes the tarball while no published + * path appears in the diff. + */ +const BUILD_INPUTS = ['src/**', 'tsconfig*.json', 'tsdown.config.*', 'build.config.*'] as const + /** Release types the dsh family accepts besides an explicit version. */ const RELEASE_TYPES = ['major', 'minor', 'patch'] as const +/** The workspace root manifest, which carries the dsh family's version. */ +const ROOT_MANIFEST = 'package.json' + +/** One manifest the bump rewrites, and the tag its new version will carry. */ +interface PlannedVersion { + /** Repository-relative manifest path. */ + readonly manifestPath: string + /** Label for the log line. */ + readonly label: string + /** The version the manifest currently carries. */ + readonly from: string + /** The version to write. */ + readonly to: string + /** The tag this version publishes from, or undefined for the workspace root. */ + readonly tag: string | undefined +} + /** * Split a version into its release numbers, discarding any prerelease segment. * @param version - the current version. @@ -36,6 +61,18 @@ function releaseNumbers(version: string): [number, number, number] { return [Number(match[1]), Number(match[2]), Number(match[3])] } +/** + * Order two versions by their release numbers alone. + * @param left - one version. + * @param right - the other version. + * @returns Negative when `left` is lower, positive when higher, zero when equal. + */ +function compareReleaseNumbers(left: string, right: string): number { + const [leftMajor, leftMinor, leftPatch] = releaseNumbers(left) + const [rightMajor, rightMinor, rightPatch] = releaseNumbers(right) + return leftMajor - rightMajor || leftMinor - rightMinor || leftPatch - rightPatch +} + /** * The next dsh version. * @param current - the family's current shared version. @@ -56,13 +93,19 @@ function nextSharedVersion(current: string, request: string): string { } /** - * The version a vendored package publishes next: its release numbers with the - * patch incremented, which also drops an upstream prerelease segment. - * @param current - the package's current version. + * The version a vendored package publishes next: the higher of its manifest + * version and its last published version, with the patch incremented. + * + * The manifest alone is not the baseline. A vendor re-sync restores upstream's + * version, which is lower than what this repository already published, and + * incrementing that would name a version the registry already carries. + * @param current - the package's manifest version. + * @param published - the version its newest tag names, when it has one. * @returns The target version. */ -function nextVendorVersion(current: string): string { - const [major, minor, patch] = releaseNumbers(current) +export function nextVendorVersion(current: string, published: string | undefined): string { + const baseline = published !== undefined && compareReleaseNumbers(published, current) > 0 ? published : current + const [major, minor, patch] = releaseNumbers(baseline) return `${String(major)}.${String(minor)}.${String(patch + 1)}` } @@ -70,57 +113,147 @@ function nextVendorVersion(current: string): string { * Whether a repository-relative path reaches the member's published payload. * @param member - the member the path belongs to. * @param path - repository-relative path. - * @returns True when `files` (or npm's always-published set) selects it. + * @returns True when `files`, npm's always-published set, or a build input selects it. */ -function reachesPayload(member: ReleaseMember, path: string): boolean { +export function reachesPayload(member: ReleaseMember, path: string): boolean { const relative = path.slice(member.directory.length + 1) const files = member.manifest.files - const patterns = [ - ...ALWAYS_PUBLISHED, - ...Array.isArray(files) ? files.filter((entry): entry is string => typeof entry === 'string') : [], - ] + const selected = Array.isArray(files) ? files.filter((entry): entry is string => typeof entry === 'string') : [] + const built = selected.some(pattern => pattern.startsWith('lib')) + const patterns = [...ALWAYS_PUBLISHED, ...selected, ...built ? BUILD_INPUTS : []] return patterns.some(pattern => matchesGlob(relative, pattern) || matchesGlob(relative, `${pattern}/**`) || relative === pattern) } /** - * The newest tag a member published from, or undefined when it never published. + * The newest version a member published, read from its tags. * @param family - the member's family. * @param member - the member. - * @returns The tag name. + * @returns The version, or undefined when the member never published. */ -function lastPublishedTag(family: ReleaseFamily, member: ReleaseMember): string | undefined { - const prefix = family.tagFor(member).replace(/-v[^-]*$/, '-v') - const tags = capture('git', ['tag', '--list', `${prefix}*`, '--sort=-v:refname']).split('\n').filter(line => line !== '') - return tags[0] -} - -/** - * Whether a member's published payload changed since it last published. - * @param family - the member's family. - * @param member - the member. - * @returns True when the member needs a new version. - */ -function changedSincePublication(family: ReleaseFamily, member: ReleaseMember): boolean { - const tag = lastPublishedTag(family, member) - if (tag === undefined) return true - const changed = capture('git', ['diff', '--name-only', `${tag}..HEAD`, '--', member.directory]) +function lastPublishedVersion(family: ReleaseFamily, member: ReleaseMember): string | undefined { + const prefix = family.tagPrefixFor(member) + const [newest] = capture('git', ['tag', '--list', `${prefix}*`, '--sort=-v:refname']) .split('\n').filter(line => line !== '') - return changed.some(path => reachesPayload(member, path)) + return newest === undefined ? undefined : newest.slice(prefix.length) } /** - * Write a version into a member's manifest, preserving formatting and key order. - * @param root - repository root. - * @param member - the member to rewrite. - * @param version - the target version. + * Confirm the registry carries the version a tag names. + * + * A tag is a commit pointer, not proof of publication: a tag pushed for a + * publication that then failed would otherwise read as "already published" and + * skip the package indefinitely. Querying a private package needs credentials, + * so an unauthenticated machine reports the gap instead of failing. + * @param name - package name. + * @param version - the version the tag names. */ -function writeVersion(root: string, member: ReleaseMember, version: string): void { - const path = join(root, member.directory, 'package.json') +function confirmPublished(name: string, version: string): void { + const result = attempt('npm', ['view', `${name}@${version}`, 'version']) + if (result.status === 0) return + const output = `${result.stdout}${result.stderr}` + if (output.includes('ENEEDAUTH') || output.includes('E401') || output.includes('E403')) { + console.log(`release bump: cannot reach the registry for ${name}@${version}; skipping the tag check`) + return + } + if (output.includes('E404') || output.includes('404 Not Found')) { + throw new Error( + `${name}@${version} is tagged but absent from the registry.` + + '\nThe tag was pushed for a publication that did not complete: re-run that publish, or delete the tag.', + ) + } + throw new Error(`npm view ${name}@${version} failed:\n${output}`) +} + +/** + * Write a version into a manifest, preserving formatting and key order. + * @param root - repository root. + * @param manifestPath - repository-relative manifest path. + * @param from - the version the manifest currently carries. + * @param to - the target version. + */ +function writeVersion(root: string, manifestPath: string, from: string, to: string): void { + const path = join(root, manifestPath) const text = readFileSync(path, 'utf8') - const line = `"version": "${member.version}"` - if (!text.includes(line)) throw new Error(`${member.directory}: cannot locate ${line}`) - writeFileSync(path, text.replace(line, `"version": "${version}"`)) + const line = `"version": "${from}"` + if (!text.includes(line)) throw new Error(`${manifestPath}: cannot locate ${line}`) + writeFileSync(path, text.replace(line, `"version": "${to}"`)) +} + +/** + * Read the workspace root version. + * @param root - repository root. + * @returns The root manifest version. + */ +function rootVersion(root: string): string { + const manifest: unknown = JSON.parse(readFileSync(join(root, ROOT_MANIFEST), 'utf8')) + const version = (manifest as Record).version + if (typeof version !== 'string') throw new Error('package.json must declare a string version') + return version +} + +/** + * Plan the dsh family's rewrite: one version for every member and the root. + * @param family - the dsh family. + * @param root - repository root. + * @param members - the family's members. + * @param request - `major`, `minor`, `patch`, or an explicit version. + * @returns The manifests to rewrite and the shared target version. + */ +function planShared( + family: ReleaseFamily, + root: string, + members: readonly ReleaseMember[], + request: string, +): { planned: PlannedVersion[]; version: string } { + const [first] = members + if (first === undefined) throw new Error(`release family ${family.id} has no members`) + const version = nextSharedVersion(first.version, request) + // The workspace root carries the family version too: the workspace constraint + // requires every member's version to equal the root's. + const planned: PlannedVersion[] = [ + { manifestPath: ROOT_MANIFEST, label: ROOT_MANIFEST, from: rootVersion(root), to: version, tag: undefined }, + ] + for (const member of members) { + planned.push({ + manifestPath: join(member.directory, 'package.json'), + label: member.directory, + from: member.version, + to: version, + tag: family.tagFor({ ...member, version }), + }) + } + return { planned, version } +} + +/** + * Plan the vendored family's rewrite: every package whose payload changed since + * it last published. + * @param family - the vendored family. + * @param members - the family's members. + * @returns The manifests to rewrite. + */ +function planPerPackage(family: ReleaseFamily, members: readonly ReleaseMember[]): PlannedVersion[] { + const planned: PlannedVersion[] = [] + for (const member of members) { + const published = lastPublishedVersion(family, member) + if (published !== undefined) { + confirmPublished(member.name, published) + const since = `${family.tagPrefixFor(member)}${published}` + const changed = capture('git', ['diff', '--name-only', `${since}..HEAD`, '--', member.directory]) + .split('\n').filter(line => line !== '') + if (!changed.some(path => reachesPayload(member, path))) continue + } + const to = nextVendorVersion(member.version, published) + planned.push({ + manifestPath: join(member.directory, 'package.json'), + label: member.directory, + from: member.version, + to, + tag: family.tagFor({ ...member, version: to }), + }) + } + return planned } /** Bump the family named by `--family` and commit; `--dry-run` only reports the plan. */ @@ -136,21 +269,17 @@ function main(): void { const members = family.members(root) family.verifyVersions(members) - const planned: { member: ReleaseMember; version: string }[] = [] + let planned: PlannedVersion[] let sharedVersion: string | undefined if (family.id === 'dsh') { const request = positionals[0] if (request === undefined) throw new Error('usage: release:dsh ') - const [first] = members - if (first === undefined) throw new Error(`release family ${family.id} has no members`) - sharedVersion = nextSharedVersion(first.version, request) - for (const member of members) planned.push({ member, version: sharedVersion }) + const shared = planShared(family, root, members, request) + planned = shared.planned + sharedVersion = shared.version } else { if (positionals.length > 0) throw new Error('release:vendor takes no version: each package increments its own patch') - for (const member of members) { - if (!changedSincePublication(family, member)) continue - planned.push({ member, version: nextVendorVersion(member.version) }) - } + planned = planPerPackage(family, members) } if (planned.length === 0) { @@ -160,25 +289,25 @@ function main(): void { const dryRun = values['dry-run'] if (!dryRun) { - for (const { member, version } of planned) writeVersion(root, member, version) + for (const entry of planned) writeVersion(root, entry.manifestPath, entry.from, entry.to) capture('pnpm', ['install', '--lockfile-only']) } const summary = sharedVersion - ?? planned.map(entry => `${entry.member.name.replace('@deepseek-ai/', '')} ${entry.version}`).join(', ') + ?? planned.map(entry => `${entry.label.replace('vendor/', '')} ${entry.to}`).join(', ') console.log(`release bump: family ${family.id} -> ${summary}`) - for (const { member, version } of planned) console.log(` ${member.directory}: ${member.version} -> ${version}`) + for (const entry of planned) console.log(` ${entry.label}: ${entry.from} -> ${entry.to}`) if (dryRun) { console.log('release bump: dry run, nothing written') return } - capture('git', ['add', 'pnpm-lock.yaml', ...planned.map(entry => join(entry.member.directory, 'package.json'))]) + capture('git', ['add', 'pnpm-lock.yaml', ...planned.map(entry => entry.manifestPath)]) capture('git', ['commit', '-m', `release(${family.id}): ${summary}`]) - // The dsh family tags once for its shared version; vendor tags each package. - const tags = [...new Set(planned.map(entry => family.tagFor({ ...entry.member, version: entry.version })))] console.log('release bump: committed. After this merges to master, tag it:') - for (const tag of tags) console.log(` git tag ${tag} && git push origin ${tag}`) + for (const tag of [...new Set(planned.map(entry => entry.tag).filter(tag => tag !== undefined))]) { + console.log(` git tag ${tag} && git push origin ${tag}`) + } } -main() +if (isEntry(import.meta.url)) main() diff --git a/scripts/release/families.spec.ts b/scripts/release/families.spec.ts new file mode 100644 index 0000000000..34faf36ddc --- /dev/null +++ b/scripts/release/families.spec.ts @@ -0,0 +1,146 @@ +/** Release family discovery, publish order, tag naming, and the bump judgements. */ + +import { describe, expect, it } from 'vitest' +import { releaseFamily, type ReleaseMember } from './families.ts' +import { nextVendorVersion, reachesPayload } from './bump.ts' + +/** + * A release member standing in for a manifest on disk. + * @param directory - repository-relative package directory. + * @param name - package name. + * @param manifest - manifest fields the subject reads. + * @returns The member. + */ +function member(directory: string, name: string, manifest: Record = {}): ReleaseMember { + return { directory, name, version: '0.0.1', manifest } +} + +describe('release families', () => { + it('names one tag for the whole dsh family and one per vendored package', () => { + const dsh = releaseFamily('dsh') + const vendor = releaseFamily('vendor') + const cli = member('apps/cli', '@deepseek-ai/dsh') + const cordis = { ...member('vendor/cordis', '@deepseek-ai/cordis'), version: '4.0.1' } + + expect(dsh.tagFor(cli)).toBe('dsh-v0.0.1') + expect(vendor.tagFor(cordis)).toBe('vendor-cordis-v4.0.1') + // The prefix is constructed, not recovered from a tag: a version with a + // hyphen would defeat any suffix-stripping. + expect(vendor.tagPrefixFor({ ...cordis, version: '4.0.0-rc.7' })).toBe('vendor-cordis-v') + expect(vendor.tagFor({ ...cordis, version: '4.0.0-rc.7' })).toBe('vendor-cordis-v4.0.0-rc.7') + }) + + it('rejects a family whose members disagree on the shared version', () => { + const dsh = releaseFamily('dsh') + const members = [member('apps/cli', '@deepseek-ai/dsh'), { ...member('apps/web', '@deepseek-ai/dsh-frontend'), version: '0.0.2' }] + + expect(() => dsh.verifyVersions(members)).toThrow(/must share one version/) + expect(() => dsh.verifyVersions([members[0]!])).not.toThrow() + }) + + it('accepts independent vendored versions and rejects an unpublishable one', () => { + const vendor = releaseFamily('vendor') + const members = [ + { ...member('vendor/cordis', '@deepseek-ai/cordis'), version: '4.0.1' }, + { ...member('vendor/cosmokit', '@deepseek-ai/cosmokit'), version: '1.8.2' }, + ] + + expect(() => vendor.verifyVersions(members)).not.toThrow() + expect(() => vendor.verifyVersions([{ ...members[0]!, version: 'latest' }])).toThrow(/unpublishable version/) + }) + + it('publishes a dependency before its consumer, and orders ties by name', () => { + const dsh = releaseFamily('dsh') + const members = [ + member('packages/a/consumer', '@deepseek-ai/dsh-consumer', { dependencies: { '@deepseek-ai/dsh-library': 'workspace:^' } }), + member('packages/a/library', '@deepseek-ai/dsh-library'), + member('packages/a/zebra', '@deepseek-ai/dsh-zebra'), + ] + + expect(dsh.publishOrder(members).map(entry => entry.name)).toEqual([ + '@deepseek-ai/dsh-library', + '@deepseek-ai/dsh-consumer', + '@deepseek-ai/dsh-zebra', + ]) + }) + + it('reports a runtime dependency cycle instead of emitting an arbitrary order', () => { + const dsh = releaseFamily('dsh') + const members = [ + member('packages/a/left', '@deepseek-ai/dsh-left', { dependencies: { '@deepseek-ai/dsh-right': 'workspace:^' } }), + member('packages/a/right', '@deepseek-ai/dsh-right', { dependencies: { '@deepseek-ai/dsh-left': 'workspace:^' } }), + ] + + expect(() => dsh.publishOrder(members)).toThrow(/dependency cycle/) + }) + + it('applies the harness payload policy to dsh and keeps upstream payloads for vendored packages', () => { + const dsh = releaseFamily('dsh') + const vendor = releaseFamily('vendor') + const harness = member('packages/a/library', '@deepseek-ai/dsh-library') + const vendored = member('vendor/cordis', '@deepseek-ai/cordis') + + expect(() => dsh.validatePayload(harness, ['package/lib/index.js', 'package/src/index.ts'])) + .toThrow(/publishes source file/) + expect(() => vendor.validatePayload(vendored, ['package/lib/index.js', 'package/src/index.ts'])).not.toThrow() + expect(() => vendor.validatePayload(vendored, [])).toThrow(/empty tarball/) + }) + + it('drives the installed entry only for the family that publishes one', () => { + expect(releaseFamily('dsh').installedEntry).toEqual({ packageName: '@deepseek-ai/dsh', binPath: 'lib/bin.js' }) + expect(releaseFamily('vendor').installedEntry).toBeUndefined() + }) + + it('rejects an unknown family identifier', () => { + expect(() => releaseFamily('native')).toThrow(/unknown release family/) + }) +}) + +describe('vendored version baseline', () => { + it('drops an upstream prerelease segment and increments the patch', () => { + expect(nextVendorVersion('4.0.0-rc.7', undefined)).toBe('4.0.1') + expect(nextVendorVersion('1.0.0-rc.5', undefined)).toBe('1.0.1') + expect(nextVendorVersion('1.8.1', undefined)).toBe('1.8.2') + }) + + it('increments from the last published version when a re-sync restored a lower one', () => { + // Upstream moved rc.7 -> rc.8 after this repository published 4.0.1; + // incrementing the manifest alone would name 4.0.1 a second time. + expect(nextVendorVersion('4.0.0-rc.8', '4.0.1')).toBe('4.0.2') + expect(nextVendorVersion('4.1.0', '4.0.1')).toBe('4.1.1') + }) +}) + +describe('payload change judgement', () => { + const sourceShipping = member('vendor/cosmokit', '@deepseek-ai/cosmokit', { + files: ['lib/index.js', 'lib/types/**/*.d.ts', 'src'], + }) + const buildOutputOnly = member('vendor/cordis', '@deepseek-ai/cordis', { + files: ['lib/index.js', 'lib/types/**/*.d.ts', 'bin.js'], + }) + + it('counts the manifest and the files npm always publishes', () => { + expect(reachesPayload(sourceShipping, 'vendor/cosmokit/package.json')).toBe(true) + expect(reachesPayload(sourceShipping, 'vendor/cosmokit/README.md')).toBe(true) + expect(reachesPayload(sourceShipping, 'vendor/cosmokit/src/index.ts')).toBe(true) + }) + + it('counts build inputs for a package whose payload is build output', () => { + // cordis publishes lib/ only, and lib/ is not tracked: without this, a real + // source change reads as "nothing changed" and the next publish fails on a + // version whose bytes moved. + expect(reachesPayload(buildOutputOnly, 'vendor/cordis/src/context.ts')).toBe(true) + expect(reachesPayload(buildOutputOnly, 'vendor/cordis/tsconfig.json')).toBe(true) + }) + + it('ignores paths no tarball carries', () => { + expect(reachesPayload(sourceShipping, 'vendor/cosmokit/tests/unit.spec.ts')).toBe(false) + expect(reachesPayload(sourceShipping, 'vendor/cosmokit/CHANGELOG.md')).toBe(false) + // The README pattern is deliberately loose: over-reporting a change costs one + // unnecessary patch bump, while under-reporting fails the next publish on a + // version whose bytes moved. + expect(reachesPayload(sourceShipping, 'vendor/cosmokit/README.i18n.yaml')).toBe(true) + expect(reachesPayload(member('packages/a/library', '@deepseek-ai/dsh-library', { files: ['lib/index.js'] }), + 'packages/a/library/tests/library.spec.ts')).toBe(false) + }) +}) diff --git a/scripts/release/families.ts b/scripts/release/families.ts index 78f5de1951..e4c5fda5be 100644 --- a/scripts/release/families.ts +++ b/scripts/release/families.ts @@ -3,7 +3,7 @@ * (`packages/` + `apps/`, `vendor/`, and `native/`) and the two this module * owns: `dsh` and `vendor`. Each family carries its own version baseline, tag * naming, and publish set, so releasing one never republishes another - * ([rationale](../../.agents/notes/proposed/process/2026-08-10-npm-release-sequences.md)). + * ([rationale](../../.agents/notes/implemented/process/2026-08-10-npm-release-sequences.md)). * * The family dimension lives here only. A new sequence adds a subclass and a * `releaseFamilies()` entry; nothing else in the release scripts branches on it. @@ -162,12 +162,22 @@ export abstract class ReleaseFamily { */ abstract verifyVersions(members: readonly ReleaseMember[]): void + /** + * The tag prefix a member's versions are tagged under. Every tag for that + * member starts with it, which is how the last published version is found. + * @param member - the member being published. + * @returns The prefix, ending in `-v`. + */ + abstract tagPrefixFor(member: ReleaseMember): string + /** * The tag a member publishes from. * @param member - the member being published. * @returns The full tag name, without `refs/tags/`. */ - abstract tagFor(member: ReleaseMember): string + tagFor(member: ReleaseMember): string { + return `${this.tagPrefixFor(member)}${member.version}` + } /** * Check what a member's packed tarball carries. @@ -202,12 +212,11 @@ class DshFamily extends ReleaseFamily { } /** - * The single family tag. - * @param member - any family member; all carry the same version. - * @returns `dsh-v`. + * The single family prefix: every member shares one version, so one tag names it. + * @returns `dsh-v`. */ - tagFor(member: ReleaseMember): string { - return `${this.tagPrefix}${member.version}` + tagPrefixFor(): string { + return this.tagPrefix } /** @@ -243,12 +252,12 @@ class VendorFamily extends ReleaseFamily { } /** - * The member's own tag, because one vendor release can carry several versions. + * A prefix per member, because one vendor release can carry several versions. * @param member - the member being published. - * @returns `vendor--v`. + * @returns `vendor--v`. */ - tagFor(member: ReleaseMember): string { - return `${this.tagPrefix}${member.name.replace('@deepseek-ai/', '')}-v${member.version}` + tagPrefixFor(member: ReleaseMember): string { + return `${this.tagPrefix}${member.name.replace('@deepseek-ai/', '')}-v` } /** diff --git a/scripts/release/pack.ts b/scripts/release/pack.ts index 5c50ebca4b..47a33a26ac 100644 --- a/scripts/release/pack.ts +++ b/scripts/release/pack.ts @@ -4,14 +4,14 @@ * * The pack step is the release boundary: it runs without credentials, produces * every tarball from one commit, and hands the publish step exactly those bytes - * ([rationale](../../.agents/notes/proposed/process/2026-08-10-npm-release-sequences.md)). + * ([rationale](../../.agents/notes/implemented/process/2026-08-10-npm-release-sequences.md)). */ import { existsSync, mkdirSync, rmSync, writeFileSync } from 'node:fs' import { join, resolve } from 'node:path' import { parseArgs } from 'node:util' import { releaseFamily, tarballName, type ReleaseFamily, type ReleaseMember } from './families.ts' -import { run } from './process.ts' +import { isEntry, run } from './process.ts' import { PUBLISH_ORDER_FILE, tarballFiles } from './tarball.ts' /** Where pack output lands when `--out` is omitted. */ @@ -58,4 +58,4 @@ function main(): void { console.log(`release pack: family ${family.id}, ${String(order.length)} tarball(s) in ${values.out ?? DEFAULT_OUTPUT}`) } -main() +if (isEntry(import.meta.url)) main() diff --git a/scripts/release/process.ts b/scripts/release/process.ts index 3e8c6943bd..746f24ac36 100644 --- a/scripts/release/process.ts +++ b/scripts/release/process.ts @@ -4,6 +4,8 @@ */ import { spawnSync } from 'node:child_process' +import { realpathSync } from 'node:fs' +import { fileURLToPath } from 'node:url' /** Where and with what environment a release step runs a command. */ export interface RunOptions { @@ -63,3 +65,18 @@ export function run(command: string, args: readonly string[], options: RunOption if (result.error !== undefined) throw result.error if (result.status !== 0) throw new Error(`${command} ${args.join(' ')} exited with ${String(result.status)}`) } + +/** + * Whether this module is the process entry point. + * + * The release scripts are both commands and modules: a test imports their pure + * logic, and importing a module runs its body, so an unguarded `main()` would + * run the wrong command with the wrong arguments. + * @param moduleUrl - the caller's `import.meta.url`. + * @returns True when Node started this module. + */ +export function isEntry(moduleUrl: string): boolean { + const invoked = process.argv[1] + if (invoked === undefined) return false + return realpathSync(invoked) === realpathSync(fileURLToPath(moduleUrl)) +} diff --git a/scripts/release/publish.ts b/scripts/release/publish.ts index bd0b2d8552..b180ce1aba 100644 --- a/scripts/release/publish.ts +++ b/scripts/release/publish.ts @@ -6,7 +6,7 @@ * version whose published tarball has the same integrity is skipped, and a * version whose published tarball differs fails the run — that last case means * the content changed without a version bump - * ([rationale](../../.agents/notes/proposed/process/2026-08-10-npm-release-sequences.md)). + * ([rationale](../../.agents/notes/implemented/process/2026-08-10-npm-release-sequences.md)). * * Skipping on identical integrity is what makes re-running the publish step over * the same artifact safe. @@ -17,7 +17,7 @@ import { readFileSync } from 'node:fs' import { join, resolve } from 'node:path' import { parseArgs } from 'node:util' import { releaseFamily } from './families.ts' -import { attempt, run } from './process.ts' +import { attempt, isEntry, run } from './process.ts' import { packedIdentity, readPublishOrder } from './tarball.ts' /** npm access level for every package this repository publishes. */ @@ -98,4 +98,4 @@ function main(): void { console.log(`release publish: family ${family.id}, ${String(published)} published, ${String(skipped)} already present`) } -main() +if (isEntry(import.meta.url)) main() diff --git a/scripts/release/verify-packed-install.ts b/scripts/release/verify-packed-install.ts index 7b970212ab..10fb824147 100644 --- a/scripts/release/verify-packed-install.ts +++ b/scripts/release/verify-packed-install.ts @@ -8,7 +8,7 @@ * and those packages live in another release sequence that this credential-free * job cannot fetch from a private registry — so a dsh verification passes the * vendored family's pack output too, while publishing only its own - * ([rationale](../../.agents/notes/proposed/process/2026-08-10-npm-release-sequences.md)). + * ([rationale](../../.agents/notes/implemented/process/2026-08-10-npm-release-sequences.md)). * * What this proves is that `files` selected a complete payload and that the * published dependency ranges resolve. A workspace link or a stale `lib/` in the @@ -21,7 +21,7 @@ import { join, resolve } from 'node:path' import { pathToFileURL } from 'node:url' import { parseArgs } from 'node:util' import { releaseFamily } from './families.ts' -import { capture } from './process.ts' +import { capture, isEntry } from './process.ts' import { packedIdentity, readPublishOrder } from './tarball.ts' /** @@ -105,4 +105,4 @@ function main(): void { } } -main() +if (isEntry(import.meta.url)) main() diff --git a/scripts/release/verify.ts b/scripts/release/verify.ts index 98988de18d..1bd74c84d6 100644 --- a/scripts/release/verify.ts +++ b/scripts/release/verify.ts @@ -4,10 +4,11 @@ * * Publication happens only from GitHub Actions, so the tag and publishability * checks are gates on the workflow, not advisory local warnings - * ([rationale](../../.agents/notes/proposed/process/2026-08-10-npm-release-sequences.md)). + * ([rationale](../../.agents/notes/implemented/process/2026-08-10-npm-release-sequences.md)). */ import { parseArgs } from 'node:util' +import { isEntry } from './process.ts' import { releaseFamily, type ReleaseFamily, type ReleaseMember } from './families.ts' /** @@ -66,4 +67,4 @@ function main(): void { console.log(`release verify: family ${family.id}, ${String(members.length)} member(s), ${summary}${publishing ? ', publish gates passed' : ''}`) } -main() +if (isEntry(import.meta.url)) main() diff --git a/vendor/README.md b/vendor/README.md index e83f9b4140..0d889e87fd 100644 --- a/vendor/README.md +++ b/vendor/README.md @@ -47,6 +47,7 @@ Keep this log exhaustive — every divergence from upstream must be listed. 15. **Lazy Loader config resolution across `cordis/src/{events,fiber}.ts`, `loader/src/{index,config/entry}.ts`, `include/src/index.ts`, and `hmr/src/index.ts`**: ports [cordiverse/cordis#41](https://github.com/cordiverse/cordis/pull/41), retaining raw fiber config and resolving it through `internal/config` only after declared injections are active. Provider replacement re-resolves the raw expression, pending updates retain it, and HMR transfers it. Resolution applies only to the entry root, so child plugins mounted by a row keep caller-owned config identity. Include adds a static entry-config resolver so its own options interpolate while nested row `!!js` nodes remain deferred. Deferred failures retain the owning row diagnostic, and tree teardown does not persist failure-driven self-disposal. Covered by `packages/boot/app-boot/tests/{app-boot,user-patches}.spec.ts`, `packages/boot/cmdline/tests/cmdline.spec.ts`, `apps/cli/tests/web-agent-presets.e2e.ts`, and the built custom-profile cases in `apps/cli/tests/built-bin.e2e.ts`. 16. **In-memory Loader entry activation in `loader/src/config/entry.ts`**: an invocation can activate a row shipped with `disabled: true` without mutating its serialized options. The override belongs to the mounted entry object, survives Include config reapplication, respects disabled ancestors, and disappears with the entry. Covered by `packages/boot/cmdline/tests/cmdline.spec.ts` and `apps/web/tests/hmr-live.e2e.ts`. 17. **`@deepseek-ai` rescope**: every vendored manifest `name`, every internal dependency entry among the vendored set, and every module specifier that reaches them use the scoped names in the manifest table's `npm name` column. Directory names, version numbers, and dependency ranges are unchanged, and no upstream runtime identifier is renamed — `Symbol.for('schemastery')` and Schemastery's `vendor:` metadata field keep their upstream values. Re-apply with `pnpm run rescope-vendor --apply` after a sync; the table's two name columns are the mapping, restated for consumers in [docs/rescope.md](../docs/rescope.md). +18. **`cordis/package.json` publishes `src`**: added `src` to the `files` list, joining the other eight vendored packages. Cordis declares `"./src/*": "./src/*"` in its exports, so a tarball without `src` publishes an export map pointing at absent files; the release change judgement also reads `files` to decide whether a diff reaches the payload, and a package whose only published paths are build output has no tracked path to match. ## Sync procedure diff --git a/vendor/cordis/package.json b/vendor/cordis/package.json index 576ea209a7..ef4df3eb1d 100644 --- a/vendor/cordis/package.json +++ b/vendor/cordis/package.json @@ -27,7 +27,8 @@ "lib/index.js", "lib/types/**/*.d.ts", "lib/types/**/*.d.ts.map", - "bin.js" + "bin.js", + "src" ], "author": "Shigma ", "license": "MIT", From 21db3220d681628581a91ca23ea0fe595f73d482 Mon Sep 17 00:00:00 2001 From: imccyu <276526105+imccyu@users.noreply.github.com> Date: Tue, 11 Aug 2026 01:39:01 +0800 Subject: [PATCH 14/36] fix(release): omit optional dependencies from the packed install The Landlock platform packages sit behind optionalDependencies, and npm fails the install on their 404 rather than skipping them: they belong to the native sequence, whose pack needs a musl toolchain and one build per architecture, so this job cannot produce them and holds no credentials to fetch them. A consumer that cannot install them must still start, which is what optional means here. The release spec also gains block bodies where the lint rule rejects returning a void expression from an arrow shorthand. --- .../2026-08-10-npm-release-sequences.i18n.yaml | 4 ++-- .../2026-08-10-npm-release-sequences.md | 2 ++ .../2026-08-10-npm-release-sequences.zh.md | 2 ++ scripts/release/families.spec.ts | 18 +++++++++--------- scripts/release/verify-packed-install.ts | 7 ++++++- 5 files changed, 21 insertions(+), 12 deletions(-) diff --git a/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.i18n.yaml b/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.i18n.yaml index 4246b4c62a..632b8b3d0d 100644 --- a/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.i18n.yaml +++ b/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.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/process/2026-08-10-npm-release-sequences.md -2026-08-10-npm-release-sequences.md: 23c5f26c7be2b87d1ef2edffdd3f79a87cf1f9a1 -2026-08-10-npm-release-sequences.zh.md: 77b772460d0bf6b66ae6924c7bab1dfe0860b401 +2026-08-10-npm-release-sequences.md: 7efe5c9a1c3aa30d4c0a52aa5983b61a01f514cd +2026-08-10-npm-release-sequences.zh.md: cca853bae3f0b19dbf50aca0f2cf32aa573293ef diff --git a/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.md b/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.md index 23c5f26c7b..7efe5c9a1c 100644 --- a/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.md +++ b/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.md @@ -101,6 +101,8 @@ The `pack` job walks the whole release set once, packing each member into one di A dsh verification installs the vendored family's pack output too. The harness packages declare the vendored framework as a peer, those packages live in another sequence, and the credential-free job cannot fetch them from a private registry — so `release.yml` packs the vendored family for verification while publishing only its own set. +The verification omits optional dependencies. The Landlock platform packages behind them belong to the native sequence, whose pack needs a musl toolchain and one build per architecture, so a job on one runner cannot produce them; a consumer that cannot install them must still start, which is what optional means here. + ### Repository changes this carried | Item | Content | diff --git a/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.zh.md b/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.zh.md index 77b772460d..cca853bae3 100644 --- a/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.zh.md +++ b/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.zh.md @@ -101,6 +101,8 @@ dsh 族套用仓库的发布 payload 策略(拒绝源码与声明映射)。v dsh 的验证会一并安装 vendored 族的 pack 产物。harness 的包把 vendored 框架声明成 peer,而那些包属于另一条序列,无凭据的 job 无法从私有 registry 取到——所以 `release.yml` 为验证而打包 vendored 族,发布的仍只有自己那一份。 +验证会略去可选依赖。它们背后的 Landlock 平台包属于 native 序列,那条序列的 pack 需要 musl 工具链且每个架构各构建一次,单台 runner 产不出来;而装不到它们的消费方也必须能起——这正是「可选」在这里的含义。 + ### 本次带出的仓库改动 | 项 | 内容 | diff --git a/scripts/release/families.spec.ts b/scripts/release/families.spec.ts index 34faf36ddc..054fd900ac 100644 --- a/scripts/release/families.spec.ts +++ b/scripts/release/families.spec.ts @@ -34,8 +34,8 @@ describe('release families', () => { const dsh = releaseFamily('dsh') const members = [member('apps/cli', '@deepseek-ai/dsh'), { ...member('apps/web', '@deepseek-ai/dsh-frontend'), version: '0.0.2' }] - expect(() => dsh.verifyVersions(members)).toThrow(/must share one version/) - expect(() => dsh.verifyVersions([members[0]!])).not.toThrow() + expect(() => { dsh.verifyVersions(members) }).toThrow(/must share one version/) + expect(() => { dsh.verifyVersions([members[0]!]) }).not.toThrow() }) it('accepts independent vendored versions and rejects an unpublishable one', () => { @@ -45,8 +45,8 @@ describe('release families', () => { { ...member('vendor/cosmokit', '@deepseek-ai/cosmokit'), version: '1.8.2' }, ] - expect(() => vendor.verifyVersions(members)).not.toThrow() - expect(() => vendor.verifyVersions([{ ...members[0]!, version: 'latest' }])).toThrow(/unpublishable version/) + expect(() => { vendor.verifyVersions(members) }).not.toThrow() + expect(() => { vendor.verifyVersions([{ ...members[0]!, version: 'latest' }]) }).toThrow(/unpublishable version/) }) it('publishes a dependency before its consumer, and orders ties by name', () => { @@ -71,7 +71,7 @@ describe('release families', () => { member('packages/a/right', '@deepseek-ai/dsh-right', { dependencies: { '@deepseek-ai/dsh-left': 'workspace:^' } }), ] - expect(() => dsh.publishOrder(members)).toThrow(/dependency cycle/) + expect(() => { dsh.publishOrder(members) }).toThrow(/dependency cycle/) }) it('applies the harness payload policy to dsh and keeps upstream payloads for vendored packages', () => { @@ -80,10 +80,10 @@ describe('release families', () => { const harness = member('packages/a/library', '@deepseek-ai/dsh-library') const vendored = member('vendor/cordis', '@deepseek-ai/cordis') - expect(() => dsh.validatePayload(harness, ['package/lib/index.js', 'package/src/index.ts'])) + expect(() => { dsh.validatePayload(harness, ['package/lib/index.js', 'package/src/index.ts']) }) .toThrow(/publishes source file/) - expect(() => vendor.validatePayload(vendored, ['package/lib/index.js', 'package/src/index.ts'])).not.toThrow() - expect(() => vendor.validatePayload(vendored, [])).toThrow(/empty tarball/) + expect(() => { vendor.validatePayload(vendored, ['package/lib/index.js', 'package/src/index.ts']) }).not.toThrow() + expect(() => { vendor.validatePayload(vendored, []) }).toThrow(/empty tarball/) }) it('drives the installed entry only for the family that publishes one', () => { @@ -92,7 +92,7 @@ describe('release families', () => { }) it('rejects an unknown family identifier', () => { - expect(() => releaseFamily('native')).toThrow(/unknown release family/) + expect(() => { releaseFamily('native') }).toThrow(/unknown release family/) }) }) diff --git a/scripts/release/verify-packed-install.ts b/scripts/release/verify-packed-install.ts index 10fb824147..f4e5c4b07f 100644 --- a/scripts/release/verify-packed-install.ts +++ b/scripts/release/verify-packed-install.ts @@ -92,7 +92,12 @@ function main(): void { const environment = consumerEnvironment(consumerRoot) console.log(`release verify-packed-install: installing ${String(packed.size)} tarball(s) into ${consumerRoot}`) - capture('npm', ['install', '--no-audit', '--no-fund', '--package-lock=false'], { cwd: consumerRoot, env: environment }) + // Optional dependencies are omitted: the platform packages behind them + // belong to the native release sequence, this job holds no credentials for + // the private scope, and a consumer that cannot install them must still + // start — which is what optional means here. + capture('npm', ['install', '--no-audit', '--no-fund', '--package-lock=false', '--omit=optional'], + { cwd: consumerRoot, env: environment }) const bin = join(consumerRoot, 'node_modules', ...entry.packageName.split('/'), entry.binPath) const version = capture(process.execPath, [bin, '--version'], { cwd: consumerRoot, env: environment }) From ae75aca77608533760dbe88c190b1f198b556825 Mon Sep 17 00:00:00 2001 From: imccyu <276526105+imccyu@users.noreply.github.com> Date: Tue, 11 Aug 2026 01:48:56 +0800 Subject: [PATCH 15/36] fix(release): supply the Landlock entry tarball to the packed install dsh-sandbox-local declares @deepseek-ai/node-addon-landlock-run in dependencies, not optionalDependencies, so omitting optional dependencies left npm resolving it from a registry that does not carry it. The dsh pack job now packs that entry for verification; its own platform packages stay out, being optional and needing a musl toolchain per architecture. The verification reads each directory by its contents rather than a pack order file, because a directory packed only to satisfy a cross-sequence dependency has no release order to describe. --- ...2026-08-10-npm-release-sequences.i18n.yaml | 4 ++-- .../2026-08-10-npm-release-sequences.md | 2 +- .../2026-08-10-npm-release-sequences.zh.md | 2 +- .github/workflows/release.yml | 10 +++++++- scripts/release/verify-packed-install.ts | 23 ++++++++++++------- 5 files changed, 28 insertions(+), 13 deletions(-) diff --git a/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.i18n.yaml b/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.i18n.yaml index 632b8b3d0d..61728f400d 100644 --- a/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.i18n.yaml +++ b/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.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/process/2026-08-10-npm-release-sequences.md -2026-08-10-npm-release-sequences.md: 7efe5c9a1c3aa30d4c0a52aa5983b61a01f514cd -2026-08-10-npm-release-sequences.zh.md: cca853bae3f0b19dbf50aca0f2cf32aa573293ef +2026-08-10-npm-release-sequences.md: d51054b90aa0acd82d252cdb6e97dc1f3c0e51b5 +2026-08-10-npm-release-sequences.zh.md: 8c2b7b048af407a79f62c5842f0bd04790a61c9a diff --git a/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.md b/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.md index 7efe5c9a1c..d51054b90a 100644 --- a/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.md +++ b/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.md @@ -101,7 +101,7 @@ The `pack` job walks the whole release set once, packing each member into one di A dsh verification installs the vendored family's pack output too. The harness packages declare the vendored framework as a peer, those packages live in another sequence, and the credential-free job cannot fetch them from a private registry — so `release.yml` packs the vendored family for verification while publishing only its own set. -The verification omits optional dependencies. The Landlock platform packages behind them belong to the native sequence, whose pack needs a musl toolchain and one build per architecture, so a job on one runner cannot produce them; a consumer that cannot install them must still start, which is what optional means here. +The verification also packs the Landlock entry, which `dsh-sandbox-local` declares as a plain dependency, and omits optional dependencies. The platform packages behind those optional entries need a musl toolchain and one build per architecture, so a job on one runner cannot produce them; a consumer that cannot install them must still start, which is what optional means here. The verification therefore reads a directory by its contents rather than a pack order, because a directory can hold tarballs packed only to satisfy a cross-sequence dependency. ### Repository changes this carried diff --git a/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.zh.md b/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.zh.md index cca853bae3..8c2b7b048a 100644 --- a/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.zh.md +++ b/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.zh.md @@ -101,7 +101,7 @@ dsh 族套用仓库的发布 payload 策略(拒绝源码与声明映射)。v dsh 的验证会一并安装 vendored 族的 pack 产物。harness 的包把 vendored 框架声明成 peer,而那些包属于另一条序列,无凭据的 job 无法从私有 registry 取到——所以 `release.yml` 为验证而打包 vendored 族,发布的仍只有自己那一份。 -验证会略去可选依赖。它们背后的 Landlock 平台包属于 native 序列,那条序列的 pack 需要 musl 工具链且每个架构各构建一次,单台 runner 产不出来;而装不到它们的消费方也必须能起——这正是「可选」在这里的含义。 +验证还会打一份 Landlock entry 的 tarball——`dsh-sandbox-local` 把它声明为普通 `dependencies`——同时略去可选依赖。那些可选项背后的平台包需要 musl 工具链且每个架构各构建一次,单台 runner 产不出来;而装不到它们的消费方也必须能起,这正是「可选」在这里的含义。因此验证按目录内容读取 tarball,而不是读发布顺序:一个目录可能只装着为满足跨序列依赖而打出来的包,任何发布顺序都不描述它。 ### 本次带出的仓库改动 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7659b3b5a3..cab178a3d2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -86,8 +86,16 @@ jobs: - name: Pack the vendored framework for verification run: pnpm run release:pack --family vendor --out dist/npm-vendor + # dsh-sandbox-local declares the Landlock entry as a runtime dependency, so + # the verification needs its tarball. Its platform packages stay out: they + # are optional, and building them needs a musl toolchain per architecture. + - name: Pack the Landlock entry for verification + run: | + pnpm --dir native/landlock-run run build:ts + pnpm --dir native/landlock-run/packages/entry pack --pack-destination "$PWD/dist/npm-landlock" + - name: Verify packed install - run: pnpm run release:verify-packed-install --family dsh --from dist/npm --from dist/npm-vendor + run: pnpm run release:verify-packed-install --family dsh --from dist/npm --from dist/npm-vendor --from dist/npm-landlock - uses: actions/upload-artifact@v4 with: diff --git a/scripts/release/verify-packed-install.ts b/scripts/release/verify-packed-install.ts index f4e5c4b07f..29ec7b851e 100644 --- a/scripts/release/verify-packed-install.ts +++ b/scripts/release/verify-packed-install.ts @@ -15,14 +15,14 @@ * checkout cannot stand in for a missing file here. */ -import { mkdtempSync, rmSync, writeFileSync } from 'node:fs' +import { mkdtempSync, readdirSync, rmSync, writeFileSync } from 'node:fs' import { tmpdir } from 'node:os' import { join, resolve } from 'node:path' import { pathToFileURL } from 'node:url' import { parseArgs } from 'node:util' import { releaseFamily } from './families.ts' import { capture, isEntry } from './process.ts' -import { packedIdentity, readPublishOrder } from './tarball.ts' +import { packedIdentity } from './tarball.ts' /** * Environment for the installed artifact: no host Node hooks, no host DeepSeek @@ -44,13 +44,19 @@ function consumerEnvironment(consumerRoot: string): NodeJS.ProcessEnv { /** * Every packed tarball in the given directories, as `file:` dependency entries. - * @param directories - absolute pack output directories. + * + * The directories are read by their contents rather than a pack order file: a + * directory here can hold tarballs packed only to satisfy a cross-sequence + * dependency, which no release order describes. + * @param directories - absolute directories holding packed tarballs. * @returns Package name to tarball file URL, and the version each carries. */ function packedDependencies(directories: readonly string[]): Map { const dependencies = new Map() for (const directory of directories) { - for (const filename of readPublishOrder(directory)) { + const tarballs = readdirSync(directory).filter(name => name.endsWith('.tgz')).sort() + if (tarballs.length === 0) throw new Error(`${directory} holds no packed tarball`) + for (const filename of tarballs) { const tarball = join(directory, filename) const { name, version } = packedIdentity(tarball) dependencies.set(name, { url: pathToFileURL(tarball).href, version }) @@ -92,10 +98,11 @@ function main(): void { const environment = consumerEnvironment(consumerRoot) console.log(`release verify-packed-install: installing ${String(packed.size)} tarball(s) into ${consumerRoot}`) - // Optional dependencies are omitted: the platform packages behind them - // belong to the native release sequence, this job holds no credentials for - // the private scope, and a consumer that cannot install them must still - // start — which is what optional means here. + // Optional dependencies are omitted: the Landlock platform packages behind + // them need a musl toolchain and one build per architecture, and a consumer + // that cannot install them must still start — which is what optional means + // here. Their entry package is a plain dependency of dsh-sandbox-local, so + // its tarball is supplied through --from. capture('npm', ['install', '--no-audit', '--no-fund', '--package-lock=false', '--omit=optional'], { cwd: consumerRoot, env: environment }) From 9840d39ba00729e2634a5093f9d11ea3c4b21555 Mon Sep 17 00:00:00 2001 From: imccyu <276526105+imccyu@users.noreply.github.com> Date: Tue, 11 Aug 2026 02:36:28 +0800 Subject: [PATCH 16/36] feat(release): rehearse a vendored publication with a prerelease MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit release:vendor --prerelease rc.1 appends the identifier to the version each package would take, so a first publication can be thrown away instead of holding the stable dist-tag: publish already routes any version with a prerelease segment to --tag next. A prerelease does not consume its release numbers, so the stable release that follows takes the same ones rather than skipping a patch. Deciding that needs semver precedence, which git's version sort does not provide — it places 4.0.1-rc.1 above 4.0.1 — so the newest published version is chosen by comparing versions here, numeric prerelease fields numerically. --- ...2026-08-10-npm-release-sequences.i18n.yaml | 4 +- .../2026-08-10-npm-release-sequences.md | 2 +- .../2026-08-10-npm-release-sequences.zh.md | 2 +- scripts/release/bump.ts | 117 +++++++++++++++--- scripts/release/families.spec.ts | 32 ++++- 5 files changed, 136 insertions(+), 21 deletions(-) diff --git a/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.i18n.yaml b/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.i18n.yaml index 61728f400d..52d911bb5f 100644 --- a/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.i18n.yaml +++ b/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.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/process/2026-08-10-npm-release-sequences.md -2026-08-10-npm-release-sequences.md: d51054b90aa0acd82d252cdb6e97dc1f3c0e51b5 -2026-08-10-npm-release-sequences.zh.md: 8c2b7b048af407a79f62c5842f0bd04790a61c9a +2026-08-10-npm-release-sequences.md: df81756ab84163b21996b5e2f12c5c8db994d9a5 +2026-08-10-npm-release-sequences.zh.md: 03269aeb987509034564bd0cac92f5d26c7f9b58 diff --git a/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.md b/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.md index d51054b90a..df81756ab8 100644 --- a/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.md +++ b/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.md @@ -50,7 +50,7 @@ The vendored packages are decoupled from upstream by their scope but keep their | `@deepseek-ai/cordis-plugin-group` | 1.0.0 | 1.0.1 | | `@deepseek-ai/cordis-plugin-logger-console` | 1.0.0 | 1.0.1 | -Taking the last published version as the baseline is what survives a re-sync: upstream restoring `4.0.0-rc.8` after this repository published `4.0.1` would otherwise compute `4.0.1` again and collide. +Taking the last published version as the baseline is what survives a re-sync: upstream restoring `4.0.0-rc.8` after this repository published `4.0.1` would otherwise compute `4.0.1` again and collide. `--prerelease rc.1` publishes a rehearsal instead, which takes `--tag next` and leaves the release numbers free: a prerelease has lower precedence than the release it precedes, so `4.0.1` still follows `4.0.1-rc.1`. That ordering is computed here rather than read from `git tag --sort=v:refname`, which places a prerelease above its release. Only changed packages publish, and the change judgement adds no state file: **each package has its own tag, and that tag records the commit it last published from**. For each package, bump reads the newest `vendor--v*` tag and diffs the package directory against it. A path counts when the manifest's `files` selects it, when npm publishes it regardless (`package.json`, `README*`, `LICENSE*`), or — for a package whose `files` selects `lib/` — when it is a build input (`src/**`, `tsconfig*.json`, a build config). That last rule exists because a built payload is not tracked by git: without it, a real source change reads as "nothing changed" and the next publication fails on a version whose bytes moved. diff --git a/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.zh.md b/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.zh.md index 8c2b7b048a..03269aeb98 100644 --- a/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.zh.md +++ b/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.zh.md @@ -50,7 +50,7 @@ vendor 九包加了 scope 之后与上游脱钩,但保留各自的版本线。 | `@deepseek-ai/cordis-plugin-group` | 1.0.0 | 1.0.1 | | `@deepseek-ai/cordis-plugin-logger-console` | 1.0.0 | 1.0.1 | -以「上次发布版本」为基线才扛得住重同步:本仓发过 `4.0.1` 之后上游把版本恢复成 `4.0.0-rc.8`,只看 manifest 会再算出 `4.0.1` 并撞上已发版本。 +以「上次发布版本」为基线才扛得住重同步:本仓发过 `4.0.1` 之后上游把版本恢复成 `4.0.0-rc.8`,只看 manifest 会再算出 `4.0.1` 并撞上已发版本。加 `--prerelease rc.1` 则发一次排练版:它进 `--tag next`,而且不占用那组数字——预发布的优先级低于它所先行的正式版,所以 `4.0.1` 仍然接在 `4.0.1-rc.1` 之后。这个次序由脚本自己算,不读 `git tag --sort=v:refname`——git 会把预发布排在正式版之前。 只发改动过的包,而变更判据不引入新的状态文件:**每包一个 tag,tag 就是「上次发布到哪个 commit」的记录**。bump 对每个包取最新的 `vendor-<包名>-v*` tag,拿包目录与它做 diff。一条路径算命中的条件是:manifest 的 `files` 选中它,或 npm 无论如何都会发布它(`package.json`、`README*`、`LICENSE*`),或者——当该包的 `files` 选中 `lib/` 时——它是构建输入(`src/**`、`tsconfig*.json`、构建配置)。最后那条规则的存在理由是构建产物不在 git 里:没有它,真实的源码改动会读成「没变化」,而下一次发布会在一个字节已变的版本上失败。 diff --git a/scripts/release/bump.ts b/scripts/release/bump.ts index 0f50ea6a9c..e79b7a0e9c 100644 --- a/scripts/release/bump.ts +++ b/scripts/release/bump.ts @@ -73,6 +73,55 @@ function compareReleaseNumbers(left: string, right: string): number { return leftMajor - rightMajor || leftMinor - rightMinor || leftPatch - rightPatch } +/** + * The prerelease segment of a version, or undefined when it has none. + * @param version - the version to read. + * @returns The segment after the first `-`. + */ +function prereleaseOf(version: string): string | undefined { + const index = version.indexOf('-') + return index === -1 ? undefined : version.slice(index + 1) +} + +/** + * Order two versions by semver precedence. + * + * Git's version sort cannot stand in for this: `--sort=v:refname` places + * `4.0.1-rc.1` above `4.0.1`, while semver gives a prerelease lower precedence + * than the release it precedes. Prerelease identifiers compare field by field, + * numeric fields numerically, so `rc.10` outranks `rc.1`. + * @param left - one version. + * @param right - the other version. + * @returns Negative when `left` is lower, positive when higher, zero when equal. + */ +export function compareVersions(left: string, right: string): number { + const numbers = compareReleaseNumbers(left, right) + if (numbers !== 0) return numbers + const leftPre = prereleaseOf(left) + const rightPre = prereleaseOf(right) + if (leftPre === undefined || rightPre === undefined) { + if (leftPre === rightPre) return 0 + return leftPre === undefined ? 1 : -1 + } + const leftFields = leftPre.split('.') + const rightFields = rightPre.split('.') + for (let index = 0; index < Math.max(leftFields.length, rightFields.length); index += 1) { + const leftField = leftFields[index] + const rightField = rightFields[index] + // A shorter identifier list has lower precedence when all its fields match. + if (leftField === undefined) return -1 + if (rightField === undefined) return 1 + if (leftField === rightField) continue + const leftNumeric = /^\d+$/.test(leftField) + const rightNumeric = /^\d+$/.test(rightField) + if (leftNumeric && rightNumeric) return Number(leftField) - Number(rightField) + // Numeric fields have lower precedence than alphanumeric ones. + if (leftNumeric !== rightNumeric) return leftNumeric ? -1 : 1 + return leftField < rightField ? -1 : 1 + } + return 0 +} + /** * The next dsh version. * @param current - the family's current shared version. @@ -93,20 +142,36 @@ function nextSharedVersion(current: string, request: string): string { } /** - * The version a vendored package publishes next: the higher of its manifest - * version and its last published version, with the patch incremented. + * The version a vendored package publishes next. * - * The manifest alone is not the baseline. A vendor re-sync restores upstream's - * version, which is lower than what this repository already published, and - * incrementing that would name a version the registry already carries. + * The baseline is the higher of the manifest version and the last published + * version: a vendor re-sync restores upstream's version, which is lower than + * what this repository already published, and incrementing that would name a + * version the registry already carries. + * + * A prerelease does not consume its own release numbers. Publishing + * `4.0.1-rc.1` leaves `4.0.1` free, so the next stable version is `4.0.1` + * rather than `4.0.2`, and a second prerelease keeps those numbers too. * @param current - the package's manifest version. * @param published - the version its newest tag names, when it has one. + * @param prerelease - prerelease identifier to append, for a rehearsal publication. * @returns The target version. */ -export function nextVendorVersion(current: string, published: string | undefined): string { - const baseline = published !== undefined && compareReleaseNumbers(published, current) > 0 ? published : current +export function nextVendorVersion( + current: string, + published: string | undefined, + prerelease?: string, +): string { + const ahead = published !== undefined && compareReleaseNumbers(published, current) > 0 + const baseline = ahead ? published : current const [major, minor, patch] = releaseNumbers(baseline) - return `${String(major)}.${String(minor)}.${String(patch + 1)}` + // Reuse the numbers when the published version that set them is a prerelease + // of them; increment when a stable release already holds them. + const reuse = ahead && published.includes('-') + const numbers = reuse + ? `${String(major)}.${String(minor)}.${String(patch)}` + : `${String(major)}.${String(minor)}.${String(patch + 1)}` + return prerelease === undefined ? numbers : `${numbers}-${prerelease}` } /** @@ -133,9 +198,10 @@ export function reachesPayload(member: ReleaseMember, path: string): boolean { */ function lastPublishedVersion(family: ReleaseFamily, member: ReleaseMember): string | undefined { const prefix = family.tagPrefixFor(member) - const [newest] = capture('git', ['tag', '--list', `${prefix}*`, '--sort=-v:refname']) - .split('\n').filter(line => line !== '') - return newest === undefined ? undefined : newest.slice(prefix.length) + const versions = capture('git', ['tag', '--list', `${prefix}*`]) + .split('\n').filter(line => line !== '').map(tag => tag.slice(prefix.length)) + if (versions.length === 0) return undefined + return versions.reduce((newest, candidate) => compareVersions(candidate, newest) > 0 ? candidate : newest) } /** @@ -231,9 +297,14 @@ function planShared( * it last published. * @param family - the vendored family. * @param members - the family's members. + * @param prerelease - prerelease identifier to append, for a rehearsal publication. * @returns The manifests to rewrite. */ -function planPerPackage(family: ReleaseFamily, members: readonly ReleaseMember[]): PlannedVersion[] { +function planPerPackage( + family: ReleaseFamily, + members: readonly ReleaseMember[], + prerelease: string | undefined, +): PlannedVersion[] { const planned: PlannedVersion[] = [] for (const member of members) { const published = lastPublishedVersion(family, member) @@ -244,7 +315,7 @@ function planPerPackage(family: ReleaseFamily, members: readonly ReleaseMember[] .split('\n').filter(line => line !== '') if (!changed.some(path => reachesPayload(member, path))) continue } - const to = nextVendorVersion(member.version, published) + const to = nextVendorVersion(member.version, published, prerelease) planned.push({ manifestPath: join(member.directory, 'package.json'), label: member.directory, @@ -256,10 +327,18 @@ function planPerPackage(family: ReleaseFamily, members: readonly ReleaseMember[] return planned } -/** Bump the family named by `--family` and commit; `--dry-run` only reports the plan. */ +/** + * Bump the family named by `--family` and commit; `--dry-run` only reports the + * plan. `--prerelease rc.1` makes the vendored family publish a rehearsal + * version, which never takes the stable dist-tag. + */ function main(): void { const { values, positionals } = parseArgs({ - options: { family: { type: 'string' }, 'dry-run': { type: 'boolean', default: false } }, + options: { + family: { type: 'string' }, + prerelease: { type: 'string' }, + 'dry-run': { type: 'boolean', default: false }, + }, allowPositionals: true, }) if (values.family === undefined) throw new Error('usage: bump.ts --family [version]') @@ -274,12 +353,18 @@ function main(): void { if (family.id === 'dsh') { const request = positionals[0] if (request === undefined) throw new Error('usage: release:dsh ') + if (values.prerelease !== undefined) { + throw new Error('release:dsh takes the prerelease in its version argument, as in 0.0.1-rc.1') + } const shared = planShared(family, root, members, request) planned = shared.planned sharedVersion = shared.version } else { if (positionals.length > 0) throw new Error('release:vendor takes no version: each package increments its own patch') - planned = planPerPackage(family, members) + if (values.prerelease !== undefined && !/^[0-9A-Za-z.-]+$/.test(values.prerelease)) { + throw new Error(`--prerelease must be a semver prerelease identifier, got ${values.prerelease}`) + } + planned = planPerPackage(family, members, values.prerelease) } if (planned.length === 0) { diff --git a/scripts/release/families.spec.ts b/scripts/release/families.spec.ts index 054fd900ac..65ebd078ee 100644 --- a/scripts/release/families.spec.ts +++ b/scripts/release/families.spec.ts @@ -2,7 +2,7 @@ import { describe, expect, it } from 'vitest' import { releaseFamily, type ReleaseMember } from './families.ts' -import { nextVendorVersion, reachesPayload } from './bump.ts' +import { compareVersions, nextVendorVersion, reachesPayload } from './bump.ts' /** * A release member standing in for a manifest on disk. @@ -109,6 +109,36 @@ describe('vendored version baseline', () => { expect(nextVendorVersion('4.0.0-rc.8', '4.0.1')).toBe('4.0.2') expect(nextVendorVersion('4.1.0', '4.0.1')).toBe('4.1.1') }) + + it('appends a rehearsal prerelease without consuming its release numbers', () => { + // A rehearsal burns 4.0.1-rc.1 and leaves 4.0.1 free, so the stable release + // that follows takes those same numbers instead of skipping to 4.0.2. + expect(nextVendorVersion('4.0.0-rc.7', undefined, 'rc.1')).toBe('4.0.1-rc.1') + expect(nextVendorVersion('4.0.0-rc.7', '4.0.1-rc.1', 'rc.2')).toBe('4.0.1-rc.2') + expect(nextVendorVersion('4.0.0-rc.7', '4.0.1-rc.1')).toBe('4.0.1') + expect(nextVendorVersion('4.0.0-rc.7', '4.0.1')).toBe('4.0.2') + }) +}) + +describe('version precedence', () => { + it('ranks a release above the prerelease it follows', () => { + // git --sort=v:refname disagrees, placing 4.0.1-rc.1 above 4.0.1, which is + // why the newest published version is chosen here rather than by git. + expect(compareVersions('4.0.1', '4.0.1-rc.1')).toBeGreaterThan(0) + expect(compareVersions('4.0.1-rc.1', '4.0.1')).toBeLessThan(0) + }) + + it('compares numeric prerelease fields numerically', () => { + expect(compareVersions('4.0.1-rc.10', '4.0.1-rc.1')).toBeGreaterThan(0) + expect(compareVersions('4.0.1-rc.2', '4.0.1-rc.10')).toBeLessThan(0) + }) + + it('ranks a numeric field below an alphanumeric one, and a shorter list below a longer', () => { + expect(compareVersions('4.0.1-1', '4.0.1-alpha')).toBeLessThan(0) + expect(compareVersions('4.0.1-rc', '4.0.1-rc.1')).toBeLessThan(0) + expect(compareVersions('4.0.2', '4.0.1')).toBeGreaterThan(0) + expect(compareVersions('4.0.1-rc.1', '4.0.1-rc.1')).toBe(0) + }) }) describe('payload change judgement', () => { From 4cd77a5ad94bf9493203f896be141d0ff8391ab4 Mon Sep 17 00:00:00 2001 From: imccyu <276526105+imccyu@users.noreply.github.com> Date: Tue, 11 Aug 2026 02:46:10 +0800 Subject: [PATCH 17/36] release(vendor): cordis 4.0.1-rc.1, cosmokit 1.8.2-rc.1, group 1.0.1-rc.1, hmr 1.0.16-rc.1, include 1.0.5-rc.1, loader 1.0.1-rc.1, logger-console 1.0.1-rc.1, schemastery 3.18.1-rc.1, timer 1.1.3-rc.1 --- vendor/cordis/package.json | 2 +- vendor/cosmokit/package.json | 2 +- vendor/group/package.json | 2 +- vendor/hmr/package.json | 2 +- vendor/include/package.json | 2 +- vendor/loader/package.json | 2 +- vendor/logger-console/package.json | 2 +- vendor/schemastery/package.json | 2 +- vendor/timer/package.json | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/vendor/cordis/package.json b/vendor/cordis/package.json index ef4df3eb1d..66a5f1593d 100644 --- a/vendor/cordis/package.json +++ b/vendor/cordis/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/cordis", "description": "Meta-Framework for Modern JavaScript Applications", - "version": "4.0.0-rc.7", + "version": "4.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/vendor/cosmokit/package.json b/vendor/cosmokit/package.json index de1b3947bc..0016ec0bb4 100644 --- a/vendor/cosmokit/package.json +++ b/vendor/cosmokit/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/cosmokit", "description": "A collection of common utilities", - "version": "1.8.1", + "version": "1.8.2-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/vendor/group/package.json b/vendor/group/package.json index b5e07fdb66..03baae1394 100644 --- a/vendor/group/package.json +++ b/vendor/group/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/cordis-plugin-group", "description": "Nested plugin group for cordis", - "version": "1.0.0", + "version": "1.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/vendor/hmr/package.json b/vendor/hmr/package.json index 68617b430e..e231701881 100644 --- a/vendor/hmr/package.json +++ b/vendor/hmr/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/cordis-plugin-hmr", "description": "Hot Module Replacement Plugin for Cordis", - "version": "1.0.15", + "version": "1.0.16-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/vendor/include/package.json b/vendor/include/package.json index de1509c92b..1105e13404 100644 --- a/vendor/include/package.json +++ b/vendor/include/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/cordis-plugin-include", "description": "Include files in cordis configurations", - "version": "1.0.4", + "version": "1.0.5-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/vendor/loader/package.json b/vendor/loader/package.json index 62e88b2594..a40bebc668 100644 --- a/vendor/loader/package.json +++ b/vendor/loader/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/cordis-plugin-loader", "description": "Plugin loader for cordis", - "version": "1.0.0-rc.5", + "version": "1.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/vendor/logger-console/package.json b/vendor/logger-console/package.json index 29b4b423ab..ceb1c0bd75 100644 --- a/vendor/logger-console/package.json +++ b/vendor/logger-console/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/cordis-plugin-logger-console", "description": "Console logger exporter for cordis", - "version": "1.0.0", + "version": "1.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/vendor/schemastery/package.json b/vendor/schemastery/package.json index 26cfd9b937..76f3748a5b 100644 --- a/vendor/schemastery/package.json +++ b/vendor/schemastery/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/schemastery", "description": "Type driven schema validator", - "version": "3.18.0", + "version": "3.18.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/vendor/timer/package.json b/vendor/timer/package.json index a8138fae67..211dba0036 100644 --- a/vendor/timer/package.json +++ b/vendor/timer/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/cordis-plugin-timer", "description": "Timer service for cordis", - "version": "1.1.2", + "version": "1.1.3-rc.1", "publishConfig": { "access": "restricted" }, From a5c23dd36a8bb5b371a76197e460c9910712c202 Mon Sep 17 00:00:00 2001 From: imccyu <276526105+imccyu@users.noreply.github.com> Date: Tue, 11 Aug 2026 03:20:16 +0800 Subject: [PATCH 18/36] fix: prerelease version --- apps/cli/tests/built-bin.e2e.ts | 5 ++- .../scaffold/create-sdk/tests/create.spec.ts | 6 ++- python/sdk/tests/test_release_version.py | 24 ++++++++++-- scripts/build-python-release.py | 38 +++++++++++++++---- 4 files changed, 61 insertions(+), 12 deletions(-) diff --git a/apps/cli/tests/built-bin.e2e.ts b/apps/cli/tests/built-bin.e2e.ts index 015a729d5a..81acefadc5 100644 --- a/apps/cli/tests/built-bin.e2e.ts +++ b/apps/cli/tests/built-bin.e2e.ts @@ -8,6 +8,9 @@ import { afterEach, beforeEach, describe, expect, it } from 'vitest' /** Published-entry acceptance for argument errors, profile lifecycle, and boot-free config dumps. */ const repoRoot = fileURLToPath(new URL('../../../', import.meta.url)) +// The release version, including a prerelease such as 0.0.1-rc.1: `--version` +// prints what this manifest carries, so no test may pin it to a literal. +const cliVersion = (JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')) as { version: string }).version const dshBin = join(repoRoot, 'apps/cli/lib/bin.js') const invalidProvider = fileURLToPath(new URL('./fixtures/invalid-provider.cordis.yml', import.meta.url)) @@ -387,7 +390,7 @@ describe.skipIf(!existsSync(dshBin))('dsh BUILT bin (node lib/bin.js, no tsx)', writeFileSync(join(project, '.env'), 'PATH=/project-only-path\n') try { const result = await runBuiltBin(['--version'], {}, project) - expect(result).toEqual({ code: 0, stdout: '0.0.1', stderr: '' }) + expect(result).toEqual({ code: 0, stdout: cliVersion, stderr: '' }) } finally { rmSync(project, { recursive: true, force: true }) } diff --git a/packages/scaffold/create-sdk/tests/create.spec.ts b/packages/scaffold/create-sdk/tests/create.spec.ts index 6c2995ec7d..060f76b11d 100644 --- a/packages/scaffold/create-sdk/tests/create.spec.ts +++ b/packages/scaffold/create-sdk/tests/create.spec.ts @@ -461,7 +461,11 @@ describe('CreateWizard and scaffolder', () => { }) it('reads the release batch from the initializer package', async () => { - await expect(readCreateSdkVersion()).resolves.toBe('0.0.1') + // The version tracks the release, including a prerelease such as 0.0.1-rc.1, + // so the expectation comes from the manifest rather than a literal. + const manifest = JSON.parse(await readFile(new URL('../package.json', import.meta.url), 'utf8')) as { version: string } + + await expect(readCreateSdkVersion()).resolves.toBe(manifest.version) }) }) diff --git a/python/sdk/tests/test_release_version.py b/python/sdk/tests/test_release_version.py index cf5a6cf57b..c66de01a3e 100644 --- a/python/sdk/tests/test_release_version.py +++ b/python/sdk/tests/test_release_version.py @@ -32,13 +32,31 @@ def test_release_tag_must_match_repository_version() -> None: build_python_release.validate_release_tag("python-v1.2.4", "1.2.3") -def test_repository_version_rejects_non_stable_versions(tmp_path: Path) -> None: - (tmp_path / "package.json").write_text('{"version":"1.2.3-dev"}\n') +def test_repository_version_accepts_a_prerelease(tmp_path: Path) -> None: + (tmp_path / "package.json").write_text('{"version":"1.2.3-rc.1"}\n') - with pytest.raises(ValueError, match="must be stable X.Y.Z"): + assert build_python_release.repository_version(tmp_path) == "1.2.3-rc.1" + + +def test_repository_version_rejects_malformed_versions(tmp_path: Path) -> None: + (tmp_path / "package.json").write_text('{"version":"v1.2"}\n') + + with pytest.raises(ValueError, match="must be X.Y.Z"): build_python_release.repository_version(tmp_path) +def test_pep440_version_spells_a_prerelease_the_python_way() -> None: + # Build backends normalize to this spelling, so the wheel filename and + # metadata checks compare against it rather than the repository version. + assert build_python_release.pep440_version("1.2.3") == "1.2.3" + assert build_python_release.pep440_version("1.2.3-rc.1") == "1.2.3rc1" + assert build_python_release.pep440_version("1.2.3-alpha.2") == "1.2.3a2" + assert build_python_release.pep440_version("1.2.3-beta.10") == "1.2.3b10" + + with pytest.raises(ValueError, match="no PEP 440 spelling"): + build_python_release.pep440_version("1.2.3-nightly") + + def test_stage_sdk_keeps_distribution_module_and_runtime_pin_distinct(tmp_path: Path) -> None: destination = tmp_path / "staging" diff --git a/scripts/build-python-release.py b/scripts/build-python-release.py index c9ee5e31c0..d326222efa 100644 --- a/scripts/build-python-release.py +++ b/scripts/build-python-release.py @@ -43,6 +43,8 @@ def main() -> None: args = parser.parse_args() version = repository_version() validate_release_tag(args.tag, version) + # Wheels carry the PEP 440 spelling; the tag keeps the repository spelling. + wheel_version = pep440_version(version) if args.package == "runtime" and (args.platform is None or args.runtime_exe is None): parser.error("runtime builds require --platform and --runtime-exe") if args.package == "sdk" and (args.platform is not None or args.runtime_exe is not None): @@ -53,19 +55,19 @@ def main() -> None: with tempfile.TemporaryDirectory(prefix="dsh-python-release-") as temporary: staging = Path(temporary) / args.package if args.package == "sdk": - stage_sdk(staging, version) + stage_sdk(staging, wheel_version) environment = None - expected = output_dir / f"deepseek_harness_sdk-{version}-py3-none-any.whl" + expected = output_dir / f"deepseek_harness_sdk-{wheel_version}-py3-none-any.whl" else: platform_tag, executable_name = PLATFORMS[args.platform] - stage_runtime(staging, version, args.runtime_exe.resolve(), executable_name) + stage_runtime(staging, wheel_version, args.runtime_exe.resolve(), executable_name) environment = {"DSH_RUNTIME_PLATFORM_TAG": platform_tag} - expected = output_dir / f"deepseek_harness_runtime_bin-{version}-py3-none-{platform_tag}.whl" + expected = output_dir / f"deepseek_harness_runtime_bin-{wheel_version}-py3-none-{platform_tag}.whl" command = ["uv", "build", "--wheel", "--out-dir", str(output_dir), str(staging)] subprocess.run(command, cwd=ROOT, env=None if environment is None else {**os.environ, **environment}, check=True) if not expected.is_file(): raise RuntimeError(f"build did not produce expected wheel: {expected}") - verify_wheel(expected, args.package, version, None if args.platform is None else PLATFORMS[args.platform]) + verify_wheel(expected, args.package, wheel_version, None if args.platform is None else PLATFORMS[args.platform]) print(expected) @@ -76,13 +78,35 @@ def repository_version(root: Path = ROOT) -> str: except (OSError, json.JSONDecodeError) as error: raise ValueError(f"could not read repository version from {package_json}") from error version = payload.get("version") if isinstance(payload, dict) else None - if not isinstance(version, str) or re.fullmatch(r"\d+\.\d+\.\d+", version) is None: + if not isinstance(version, str) or re.fullmatch(r"\d+\.\d+\.\d+(?:-[0-9A-Za-z.]+)?", version) is None: raise ValueError( - f"{package_json} version must be stable X.Y.Z, got {version!r}" + f"{package_json} version must be X.Y.Z with an optional prerelease segment, got {version!r}" ) return version +def pep440_version(version: str) -> str: + """The Python spelling of a repository version. + + A release candidate is `0.0.1-rc.1` in the repository and `0.0.1rc1` under + PEP 440. Build backends normalize to the latter, so the wheel filename and + metadata carry it: comparing them against the repository spelling would + reject every prerelease build. + """ + stable, separator, prerelease = version.partition("-") + if not separator: + return stable + match = re.fullmatch(r"(a|b|c|rc|alpha|beta|pre|preview)\.?(\d+)", prerelease) + if match is None: + raise ValueError( + f"prerelease segment {prerelease!r} has no PEP 440 spelling; use rc.N, alpha.N, or beta.N" + ) + identifier = {"alpha": "a", "beta": "b", "c": "rc", "pre": "rc", "preview": "rc"}.get( + match.group(1), match.group(1) + ) + return f"{stable}{identifier}{match.group(2)}" + + def validate_release_tag(tag: str | None, version: str) -> None: if tag is None: return From b64c3ac1ba37a8afe20de534ab666e85ae69377b Mon Sep 17 00:00:00 2001 From: imccyu <276526105+imccyu@users.noreply.github.com> Date: Tue, 11 Aug 2026 03:04:47 +0800 Subject: [PATCH 19/36] release(dsh): 0.0.1-rc.1 --- apps/cli/package.json | 2 +- apps/web/package.json | 2 +- package.json | 2 +- packages/acp/acp/package.json | 2 +- packages/api/gateway/package.json | 2 +- packages/api/remotes/package.json | 2 +- packages/attachment/attachment-local/package.json | 2 +- packages/attachment/attachment/package.json | 2 +- packages/bash/bash-env/package.json | 2 +- packages/bash/bash-local/package.json | 2 +- packages/bash/bash-sandbox/package.json | 2 +- packages/bash/bash/package.json | 2 +- packages/bash/pwsh-local/package.json | 2 +- packages/bash/pwsh-sandbox/package.json | 2 +- packages/bash/tool-bash/package.json | 2 +- packages/bash/tool-pwsh/package.json | 2 +- packages/boot/app-boot/package.json | 2 +- packages/boot/cmdline/package.json | 2 +- packages/bundle/base/package.json | 2 +- packages/bundle/headless/package.json | 2 +- packages/bundle/web-app/package.json | 2 +- packages/client/connection/package.json | 2 +- packages/client/hmr/package.json | 2 +- packages/client/locale/package.json | 2 +- packages/client/modules/package.json | 2 +- packages/client/runtime/package.json | 2 +- packages/client/schema-form/package.json | 2 +- packages/client/test-runtime/package.json | 2 +- packages/client/ui-agent-preset/package.json | 2 +- packages/client/ui-command/package.json | 2 +- packages/client/ui-conversation/package.json | 2 +- packages/client/ui-deliverables/package.json | 2 +- packages/client/ui-goal/package.json | 2 +- packages/client/ui-layout/package.json | 2 +- packages/client/ui-model/package.json | 2 +- packages/client/ui-models/package.json | 2 +- packages/client/ui-permission/package.json | 2 +- packages/client/ui-plan/package.json | 2 +- packages/client/ui-primitives/package.json | 2 +- packages/client/ui-question/package.json | 2 +- packages/client/ui-settings-general/package.json | 2 +- packages/client/ui-settings/package.json | 2 +- packages/client/ui-sidebar/package.json | 2 +- packages/client/ui-skill/package.json | 2 +- packages/client/ui-slash/package.json | 2 +- packages/client/ui-slots/package.json | 2 +- packages/client/ui-subagent/package.json | 2 +- packages/client/ui-theme/package.json | 2 +- packages/client/ui-tool/package.json | 2 +- packages/client/ui-trajectory/package.json | 2 +- packages/client/ui-workspace/package.json | 2 +- packages/client/web-react/package.json | 2 +- packages/client/web/package.json | 2 +- packages/code-runtime/code-runtime-worker/package.json | 2 +- packages/code-runtime/code-runtime/package.json | 2 +- packages/compact/command-compact/package.json | 2 +- packages/compact/compact-basic/package.json | 2 +- packages/compact/compact-tool-result-prune/package.json | 2 +- packages/compact/compact/package.json | 2 +- packages/context/session-reference/package.json | 2 +- packages/context/time-context/package.json | 2 +- packages/context/tmux-context/package.json | 2 +- packages/context/workspace-context/package.json | 2 +- packages/core/agent-default-model/package.json | 2 +- packages/core/agent-loop/package.json | 2 +- packages/core/agent-tool-mode/package.json | 2 +- packages/core/agent/package.json | 2 +- packages/core/scope/package.json | 2 +- packages/core/session/package.json | 2 +- packages/core/system-prompt/package.json | 2 +- packages/core/tools/package.json | 2 +- packages/credentials/credentials-local/package.json | 2 +- packages/credentials/credentials/package.json | 2 +- packages/e2b/e2b/package.json | 2 +- packages/e2b/fs-e2b/package.json | 2 +- packages/e2b/subprocess-e2b/package.json | 2 +- packages/examples/acp-demo/package.json | 2 +- packages/examples/agent-spine-demo/package.json | 2 +- packages/examples/jsonrpc-demo/package.json | 2 +- packages/feedback/command-feedback/package.json | 2 +- packages/fs/fs-local/package.json | 2 +- packages/fs/fs-policy/package.json | 2 +- packages/fs/fs-sandbox/package.json | 2 +- packages/fs/fs/package.json | 2 +- packages/fs/tool-fs-search/package.json | 2 +- packages/fs/tool-fs/package.json | 2 +- packages/fs/tool-str-replace-editor/package.json | 2 +- packages/goal/command-goal/package.json | 2 +- packages/goal/goal-session/package.json | 2 +- packages/goal/goal/package.json | 2 +- packages/goal/tool-goal/package.json | 2 +- packages/guard/repeat-tool-guard/package.json | 2 +- packages/guard/timeout-policy/package.json | 2 +- packages/hooks/hook-protocol/package.json | 2 +- packages/hooks/hooks-claude/package.json | 2 +- packages/hooks/hooks-codex/package.json | 2 +- packages/host/apiproxy/package.json | 2 +- packages/host/directory-picker-auto/package.json | 2 +- packages/host/directory-picker-browse/package.json | 2 +- packages/host/directory-picker-native/package.json | 2 +- packages/host/directory-picker/package.json | 2 +- packages/host/frontend-static/package.json | 2 +- packages/host/webserver/package.json | 2 +- packages/interaction/commands/package.json | 2 +- packages/interaction/permission/package.json | 2 +- packages/interaction/tool-ask-user/package.json | 2 +- packages/interaction/user-approval/package.json | 2 +- packages/interaction/user-interaction/package.json | 2 +- packages/llm/llm-deepseek/package.json | 2 +- packages/llm/llm-pi-ai/package.json | 2 +- packages/llm/llm-retry/package.json | 2 +- packages/llm/llm/package.json | 2 +- packages/llm/token-meter/package.json | 2 +- packages/lsp/lsp-local/package.json | 2 +- packages/lsp/lsp/package.json | 2 +- packages/lsp/tool-lsp/package.json | 2 +- packages/mcp/mcp-client/package.json | 2 +- packages/plan/plan-mode/package.json | 2 +- packages/preset/agent-presets/package.json | 2 +- packages/preset/persona/package.json | 2 +- packages/pty/pty-local/package.json | 2 +- packages/pty/pty/package.json | 2 +- packages/pty/tool-bash-persistent/package.json | 2 +- packages/pty/tool-pty/package.json | 2 +- packages/sandbox/sandbox-local/package.json | 2 +- packages/sandbox/sandbox-policy/package.json | 2 +- packages/sandbox/sandbox-windows-acl/package.json | 2 +- packages/sandbox/sandbox/package.json | 2 +- packages/scaffold/client/package.json | 2 +- packages/scaffold/create-sdk/package.json | 2 +- packages/scaffold/helper/package.json | 2 +- packages/scaffold/protocol/package.json | 2 +- packages/scaffold/scripts/package.json | 2 +- packages/scaffold/server/package.json | 2 +- packages/scaffold/telemetry/package.json | 2 +- packages/self-modification/tool-cordis/package.json | 2 +- packages/session-query/session-query-sqlite/package.json | 2 +- packages/session-query/session-query/package.json | 2 +- packages/session-query/tool-session-query/package.json | 2 +- packages/session/session-checkpoint-policy/package.json | 2 +- packages/session/session-persistence-jsonl/package.json | 2 +- packages/session/session-persistence-sqlite/package.json | 2 +- packages/session/session-persistence/package.json | 2 +- packages/session/session-projection-cache/package.json | 2 +- packages/session/session-projection/package.json | 2 +- packages/session/session-telemetry-otel/package.json | 2 +- packages/session/session-telemetry/package.json | 2 +- packages/session/session-title-all-messages-llm/package.json | 2 +- packages/session/session-title-first-message-llm/package.json | 2 +- packages/session/session-title-llm/package.json | 2 +- packages/session/session-title/package.json | 2 +- packages/session/user-id/package.json | 2 +- packages/settings/settings-local/package.json | 2 +- packages/settings/settings/package.json | 2 +- packages/skill/skill-badge/package.json | 2 +- packages/skill/skill-local/package.json | 2 +- packages/skill/skill/package.json | 2 +- packages/skill/tool-skill/package.json | 2 +- packages/spill/spill-local/package.json | 2 +- packages/spill/spill-policy/package.json | 2 +- packages/spill/spill/package.json | 2 +- packages/storage/storage-domain/package.json | 2 +- packages/storage/storage-json/package.json | 2 +- packages/storage/storage-sqlite/package.json | 2 +- packages/storage/storage/package.json | 2 +- packages/subagent/subagent-acp/package.json | 2 +- packages/subagent/subagent-claude-code/package.json | 2 +- packages/subagent/subagent-codex/package.json | 2 +- packages/subagent/subagent-dsh-sdk/package.json | 2 +- packages/subagent/subagent-fork/package.json | 2 +- packages/subagent/subagent-inprocess/package.json | 2 +- packages/subagent/subagent-spawn/package.json | 2 +- packages/subagent/subagent/package.json | 2 +- packages/subagent/tool-subagent-control/package.json | 2 +- packages/subagent/tool-subagent-report/package.json | 2 +- packages/subagent/tool-subagent/package.json | 2 +- packages/subprocess/subprocess-local/package.json | 2 +- packages/subprocess/subprocess/package.json | 2 +- packages/support/acp-snapshot/package.json | 2 +- packages/support/agent-loop-testkit/package.json | 2 +- packages/support/invariants/package.json | 2 +- packages/support/llm-mock-server/package.json | 2 +- packages/support/llm-replay/package.json | 2 +- packages/support/loader-smoke/package.json | 2 +- packages/tasks/tasks-local/package.json | 2 +- packages/tasks/tasks/package.json | 2 +- packages/tasks/tool-tasks/package.json | 2 +- packages/todo/tool-todo/package.json | 2 +- packages/typert/generator/package.json | 2 +- packages/typert/loader/package.json | 2 +- packages/typert/registry/package.json | 2 +- packages/typert/type-meta/package.json | 2 +- packages/util/atomic-write/package.json | 2 +- packages/util/brand/package.json | 2 +- packages/util/environment/package.json | 2 +- packages/util/native-command/package.json | 2 +- packages/util/paths/package.json | 2 +- packages/util/retention/package.json | 2 +- packages/util/timeout/package.json | 2 +- packages/web/tool-web/package.json | 2 +- packages/web/web-fetch-local/package.json | 2 +- packages/web/web-search-deepseek/package.json | 2 +- packages/web/web-search-exa/package.json | 2 +- packages/web/web-search-perplexity/package.json | 2 +- packages/web/web/package.json | 2 +- packages/workflow/tool-ralph/package.json | 2 +- packages/workflow/tool-workflow/package.json | 2 +- packages/workflow/workflow-workerthread/package.json | 2 +- packages/workflow/workflow/package.json | 2 +- packages/workspace/workspace/package.json | 2 +- 210 files changed, 210 insertions(+), 210 deletions(-) diff --git a/apps/cli/package.json b/apps/cli/package.json index b8f0887ac6..a294813086 100644 --- a/apps/cli/package.json +++ b/apps/cli/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh", "description": "dsh CLI: profile boot, plugin management, and the browser UI alias", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/apps/web/package.json b/apps/web/package.json index 9e71181b4b..828dffbe70 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-frontend", "description": "Web application entry: vite build over the @deepseek-ai/dsh-client-web shell library; dist/ served by apps/cli's dsh web", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/package.json b/package.json index 277bd7fe85..d99acadf7a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@deepseek-ai/dsh-root", - "version": "0.0.1", + "version": "0.0.1-rc.1", "private": true, "type": "module", "packageManager": "pnpm@11.7.0", diff --git a/packages/acp/acp/package.json b/packages/acp/acp/package.json index 5293a94e5d..b244c0367d 100644 --- a/packages/acp/acp/package.json +++ b/packages/acp/acp/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-acp", "description": "Automation-only Agent Client Protocol server for driving DeepSeek Harness agents over JSON-RPC stdio", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/api/gateway/package.json b/packages/api/gateway/package.json index bd90451fdc..48615dc55f 100644 --- a/packages/api/gateway/package.json +++ b/packages/api/gateway/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-api-gateway", "description": "TypeRT Remote Host dispatcher and Client API endpoint", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/api/remotes/package.json b/packages/api/remotes/package.json index 0a96fb2239..241a86ff9f 100644 --- a/packages/api/remotes/package.json +++ b/packages/api/remotes/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-api-remotes", "description": "Remote BFF assembly and Host Agent/Session lookup policy", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/attachment/attachment-local/package.json b/packages/attachment/attachment-local/package.json index c8804218f1..3bbf361032 100644 --- a/packages/attachment/attachment-local/package.json +++ b/packages/attachment/attachment-local/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-attachment-local", "description": "Private content-addressed DSH_HOME attachment storage", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/attachment/attachment/package.json b/packages/attachment/attachment/package.json index 9d58dccdf6..1fa800d2bf 100644 --- a/packages/attachment/attachment/package.json +++ b/packages/attachment/attachment/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-attachment", "description": "Durable immutable attachment storage seam for the DeepSeek Harness", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/bash/bash-env/package.json b/packages/bash/bash-env/package.json index cde53b2bd1..acde7f422f 100644 --- a/packages/bash/bash-env/package.json +++ b/packages/bash/bash-env/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-bash-env", "description": "Tool-independent managed DSH_* shell environment registry", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/bash/bash-local/package.json b/packages/bash/bash-local/package.json index 85eb6f2655..a46c5b6502 100644 --- a/packages/bash/bash-local/package.json +++ b/packages/bash/bash-local/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-bash-local", "description": "Local-subprocess implementation of the DeepSeek Harness bash executor seam", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/bash/bash-sandbox/package.json b/packages/bash/bash-sandbox/package.json index e77dba32e5..293748a67e 100644 --- a/packages/bash/bash-sandbox/package.json +++ b/packages/bash/bash-sandbox/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-bash-sandbox", "description": "Sandbox-consuming implementation of the DeepSeek Harness bash executor seam (confines every command via ctx.sandbox, reports denial/enforcement result facts)", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/bash/bash/package.json b/packages/bash/bash/package.json index 8d22d657fe..0821a526c8 100644 --- a/packages/bash/bash/package.json +++ b/packages/bash/bash/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-bash", "description": "Abstract bash executor seam (ctx.bash) for the DeepSeek Harness", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/bash/pwsh-local/package.json b/packages/bash/pwsh-local/package.json index 5e58a5cd3f..59e8714608 100644 --- a/packages/bash/pwsh-local/package.json +++ b/packages/bash/pwsh-local/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-pwsh-local", "description": "Local PowerShell implementation of the DeepSeek Harness bash executor seam", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/bash/pwsh-sandbox/package.json b/packages/bash/pwsh-sandbox/package.json index 12669329c4..53e418f401 100644 --- a/packages/bash/pwsh-sandbox/package.json +++ b/packages/bash/pwsh-sandbox/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-pwsh-sandbox", "description": "Sandbox-consuming implementation of the DeepSeek Harness PowerShell executor seam (confines every command via ctx.sandbox, reports denial/enforcement result facts)", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/bash/tool-bash/package.json b/packages/bash/tool-bash/package.json index a3d878e8e2..9da6eb65ca 100644 --- a/packages/bash/tool-bash/package.json +++ b/packages/bash/tool-bash/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-tool-bash", "description": "Model-facing bash tool with optional generic background-task and sandbox-escalation support", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/bash/tool-pwsh/package.json b/packages/bash/tool-pwsh/package.json index 5188891aea..0b93e820c2 100644 --- a/packages/bash/tool-pwsh/package.json +++ b/packages/bash/tool-pwsh/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-tool-pwsh", "description": "Model-facing pwsh tool over the bash executor seam", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/boot/app-boot/package.json b/packages/boot/app-boot/package.json index 4139847364..f6d4cfc07d 100644 --- a/packages/boot/app-boot/package.json +++ b/packages/boot/app-boot/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-app-boot", "description": "Shared boot glue for the app bins: .env loading, fail-loud Loader guards, snapshot-aware config resolution, and the Loader boot sequence", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/boot/cmdline/package.json b/packages/boot/cmdline/package.json index 131c254af0..9b30a9f7c5 100644 --- a/packages/boot/cmdline/package.json +++ b/packages/boot/cmdline/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-cmdline", "description": "Immutable command-line handoff from a dsh launcher to any app plugin that injects cmdlineArgs", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/bundle/base/package.json b/packages/bundle/base/package.json index 9c5fc2a5a8..655de66ec0 100644 --- a/packages/bundle/base/package.json +++ b/packages/bundle/base/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-base", "description": "The shared dsh core as a profile bundle: every profile's first patch layer, inserting the base plugin rows over the empty profile root", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/bundle/headless/package.json b/packages/bundle/headless/package.json index 7778b7be8b..af0935d2a4 100644 --- a/packages/bundle/headless/package.json +++ b/packages/bundle/headless/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-headless", "description": "The dsh one-shot bundle: a direct core Agent/Session runner over dsh-base with no Host, HTTP, or browser layer", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/bundle/web-app/package.json b/packages/bundle/web-app/package.json index cde4fa1013..181bb269c4 100644 --- a/packages/bundle/web-app/package.json +++ b/packages/bundle/web-app/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-web-app", "description": "The dsh browser-surface bundle: the web patch layer over dsh-base plus the runtime glue plugin (frontend dist serving, web-surface prompt, bash runtime variables, URL line)", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/client/connection/package.json b/packages/client/connection/package.json index 1b9481db93..025b5ffb90 100644 --- a/packages/client/connection/package.json +++ b/packages/client/connection/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-connection", "description": "Wire consumer layer: HTTP-up/WebSocket-down client, ConnectionController dual streams with reconnect, and fixture api", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/client/hmr/package.json b/packages/client/hmr/package.json index 3dad86d07a..6e7614bc27 100644 --- a/packages/client/hmr/package.json +++ b/packages/client/hmr/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-hmr", "description": "Dev-only hot-reload driver for script-loaded client entries: SSE rebuilt frames → invalidate/prefetch → fiber swap through the vendored Loader entry", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/client/locale/package.json b/packages/client/locale/package.json index d44e8ee529..6415c26961 100644 --- a/packages/client/locale/package.json +++ b/packages/client/locale/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-locale", "description": "Locale plugin: Host-backed zh/en preference, browser-derived fallback, locale snapshots, and typed namespace dictionaries", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/client/modules/package.json b/packages/client/modules/package.json index e93cd2951d..3d97f98fa6 100644 --- a/packages/client/modules/package.json +++ b/packages/client/modules/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-modules", "description": "Client module system, dual-face: node half composes the __DSH_BOOT__ entry graph (incremental dsh.client scan, bundle route, index tap, webPlugins service); browser half is the lazy-CJS module table the vendored cordis Loader consumes as its internal seam", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/client/runtime/package.json b/packages/client/runtime/package.json index 87e259f64c..749e564ef5 100644 --- a/packages/client/runtime/package.json +++ b/packages/client/runtime/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-runtime", "description": "Client core services: SlotsService, SessionsService (scope tree + object layer)", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/client/schema-form/package.json b/packages/client/schema-form/package.json index 35d80feba6..90f59b329a 100644 --- a/packages/client/schema-form/package.json +++ b/packages/client/schema-form/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-schema-form", "description": "Schema/draft model layer for settings editors: rehydrates a serialized schemastery schema, validates drafts, and edits them immutably by path", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/client/test-runtime/package.json b/packages/client/test-runtime/package.json index 54088ded59..96f3add186 100644 --- a/packages/client/test-runtime/package.json +++ b/packages/client/test-runtime/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-test-runtime", "description": "jsdom slot test runtime: real Cordis Context + SlotsService + web-react renderer with test-owned session/workspace doubles for feature specs", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/client/ui-agent-preset/package.json b/packages/client/ui-agent-preset/package.json index 77133dac21..e5d4e27790 100644 --- a/packages/client/ui-agent-preset/package.json +++ b/packages/client/ui-agent-preset/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-agent-preset", "description": "Agent-preset surfaces: the default for later sessions, this session's seat, and the composition editor", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/client/ui-command/package.json b/packages/client/ui-command/package.json index d6b015eb96..93c0cf3910 100644 --- a/packages/client/ui-command/package.json +++ b/packages/client/ui-command/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-command", "description": "Client command surface: global directory cache, '/' source, three command UI kinds, popupSelect registry", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/client/ui-conversation/package.json b/packages/client/ui-conversation/package.json index f3dd749dde..e80432f79f 100644 --- a/packages/client/ui-conversation/package.json +++ b/packages/client/ui-conversation/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-conversation", "description": "Conversation domain: skeleton, ordered chat flow, composer with the Host-backed busy-Enter preference, and details host", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/client/ui-deliverables/package.json b/packages/client/ui-deliverables/package.json index a5a82a833f..71eb96cf02 100644 --- a/packages/client/ui-deliverables/package.json +++ b/packages/client/ui-deliverables/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-deliverables", "description": "Produced-files turn tail: the deliverables row a finished turn ends with", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/client/ui-goal/package.json b/packages/client/ui-goal/package.json index d1ed34e43c..9216af858a 100644 --- a/packages/client/ui-goal/package.json +++ b/packages/client/ui-goal/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-goal", "description": "Session goal surface: GoalBar docked above the composer, read from the goal session projection", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/client/ui-layout/package.json b/packages/client/ui-layout/package.json index 879100dbe6..232c4606ab 100644 --- a/packages/client/ui-layout/package.json +++ b/packages/client/ui-layout/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-layout", "description": "Shell plugin: three-column AppFrame with drag handles, ctx.layout viewing-state service (navigation + panels)", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/client/ui-model/package.json b/packages/client/ui-model/package.json index b8f411cdc7..069fb47c8e 100644 --- a/packages/client/ui-model/package.json +++ b/packages/client/ui-model/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-model", "description": "Model selection: the /model popupSelect over session.models / session.selectModel", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/client/ui-models/package.json b/packages/client/ui-models/package.json index 0a7b6bbae8..af55b2a5cc 100644 --- a/packages/client/ui-models/package.json +++ b/packages/client/ui-models/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-models", "description": "Models settings and official-DeepSeek first-run routing over one live provider/settings/credential join", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/client/ui-permission/package.json b/packages/client/ui-permission/package.json index 880666ecad..41c3c7eb30 100644 --- a/packages/client/ui-permission/package.json +++ b/packages/client/ui-permission/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-permission", "description": "Permission surfaces: a new-session default in General settings and a current-session /permission popup over the permissions projection", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/client/ui-plan/package.json b/packages/client/ui-plan/package.json index 52d8e9fffd..3ee6860ce5 100644 --- a/packages/client/ui-plan/package.json +++ b/packages/client/ui-plan/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-plan", "description": "Plan-mode composer control: the conversation.input.plan seat over the plan projection and the /plan command channel", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/client/ui-primitives/package.json b/packages/client/ui-primitives/package.json index 732321b932..05dbe8f822 100644 --- a/packages/client/ui-primitives/package.json +++ b/packages/client/ui-primitives/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-primitives", "description": "Pure React atoms for the dsh web UI: controls, icons, markdown, and JSON inspectors (zero cordis)", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/client/ui-question/package.json b/packages/client/ui-question/package.json index 3153f8fd69..aafb3bf534 100644 --- a/packages/client/ui-question/package.json +++ b/packages/client/ui-question/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-question", "description": "Web ask_user_question feature: host tool mount plus composer-takeover question UI", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/client/ui-settings-general/package.json b/packages/client/ui-settings-general/package.json index 8eee8eab62..e720ad810a 100644 --- a/packages/client/ui-settings-general/package.json +++ b/packages/client/ui-settings-general/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-settings-general", "description": "Settings ownerless-copy and product onboarding plugin: the General section, shell trigger/header chrome content, settings dictionaries, and the versioned welcome notice", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/client/ui-settings/package.json b/packages/client/ui-settings/package.json index 37c1e1607c..3447573398 100644 --- a/packages/client/ui-settings/package.json +++ b/packages/client/ui-settings/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-settings", "description": "Settings shell plugin: sidebar trigger, modal panel, feature sections, and an ordered full-page onboarding stage", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/client/ui-sidebar/package.json b/packages/client/ui-sidebar/package.json index bffbbfd54c..73ce0817d7 100644 --- a/packages/client/ui-sidebar/package.json +++ b/packages/client/ui-sidebar/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-sidebar", "description": "Sidebar plugin: session multi-level tree, search, grouping, state dots", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/client/ui-skill/package.json b/packages/client/ui-skill/package.json index c1ee7720bb..5734767d7b 100644 --- a/packages/client/ui-skill/package.json +++ b/packages/client/ui-skill/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-skill", "description": "Web skill references and the dedicated skill tool row", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/client/ui-slash/package.json b/packages/client/ui-slash/package.json index 00b5bd1f9a..485052ae5f 100644 --- a/packages/client/ui-slash/package.json +++ b/packages/client/ui-slash/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-slash", "description": "Input trigger pipeline: '/' and '@' detection, candidate menu, pick routing to registered sources", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/client/ui-slots/package.json b/packages/client/ui-slots/package.json index 54b3d64925..85a8886519 100644 --- a/packages/client/ui-slots/package.json +++ b/packages/client/ui-slots/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-slots", "description": "Slot registry pure core: SlotMap declaration merging, single register composition API, four-share props types, store-seat types, renderer install seam", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/client/ui-subagent/package.json b/packages/client/ui-subagent/package.json index 997bfadcf6..75e5b53af7 100644 --- a/packages/client/ui-subagent/package.json +++ b/packages/client/ui-subagent/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-subagent", "description": "Subagent conversation catalog, continuation routing UI, and '@' reference source", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/client/ui-theme/package.json b/packages/client/ui-theme/package.json index 8d22586ffd..99538ed6ec 100644 --- a/packages/client/ui-theme/package.json +++ b/packages/client/ui-theme/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-theme", "description": "Theme plugin: ThemeService (light/dark/system preference, prefers-color-scheme resolution, theme/change snapshots; no DOM), --dsw-* token base stylesheets; registers the Appearance settings row", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/client/ui-tool/package.json b/packages/client/ui-tool/package.json index c0465db10c..6644d1d506 100644 --- a/packages/client/ui-tool/package.json +++ b/packages/client/ui-tool/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-tool", "description": "Client Tool call-tree renderer and keyed per-tool presentation slot", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/client/ui-trajectory/package.json b/packages/client/ui-trajectory/package.json index c50633c2c1..c11b607939 100644 --- a/packages/client/ui-trajectory/package.json +++ b/packages/client/ui-trajectory/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-trajectory", "description": "Trajectory event ledger with an interactive timing overview: pure-consumer plugin registering into the conversation ViewMap (no service)", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/client/ui-workspace/package.json b/packages/client/ui-workspace/package.json index 206e037bc1..f19c44ea57 100644 --- a/packages/client/ui-workspace/package.json +++ b/packages/client/ui-workspace/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-workspace", "description": "Workspace picker plugin: one WorkspacePicker registered into the sidebar and empty-state workspace slots", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/client/web-react/package.json b/packages/client/web-react/package.json index 1fe9231134..16bab468df 100644 --- a/packages/client/web-react/package.json +++ b/packages/client/web-react/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-web-react", "description": "Shell-side React glue: createSlotRenderer, SessionProvider, bindSnapshotSelector (uSES bridge), useInvoke", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/client/web/package.json b/packages/client/web/package.json index eff725c83d..df5192e070 100644 --- a/packages/client/web/package.json +++ b/packages/client/web/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-web", "description": "Web shell kernel: bootWebShell (module system holding + seed table + two-stage boot + AppRoot gate + app-shell assembly entry), consumed by the apps/web vite entry", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/code-runtime/code-runtime-worker/package.json b/packages/code-runtime/code-runtime-worker/package.json index bacaca170a..2614be990a 100644 --- a/packages/code-runtime/code-runtime-worker/package.json +++ b/packages/code-runtime/code-runtime-worker/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-code-runtime-worker", "description": "Worker-thread implementation of the DeepSeek Harness code-execution seam", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/code-runtime/code-runtime/package.json b/packages/code-runtime/code-runtime/package.json index 89db4e6d88..8d4e77136b 100644 --- a/packages/code-runtime/code-runtime/package.json +++ b/packages/code-runtime/code-runtime/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-code-runtime", "description": "Abstract code-execution seam (ctx.codeRuntime) for the DeepSeek Harness", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/compact/command-compact/package.json b/packages/compact/command-compact/package.json index 3b36536a34..83df4eae98 100644 --- a/packages/compact/command-compact/package.json +++ b/packages/compact/command-compact/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-command-compact", "description": "Human-facing slash command for explicit session compaction", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/compact/compact-basic/package.json b/packages/compact/compact-basic/package.json index 941e3aa32d..75e0dcd959 100644 --- a/packages/compact/compact-basic/package.json +++ b/packages/compact/compact-basic/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-compact-basic", "description": "Token-meter-driven compaction policy and LLM summarization backend for the DeepSeek Harness", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/compact/compact-tool-result-prune/package.json b/packages/compact/compact-tool-result-prune/package.json index 21951f5750..26f216a4dd 100644 --- a/packages/compact/compact-tool-result-prune/package.json +++ b/packages/compact/compact-tool-result-prune/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-compact-tool-result-prune", "description": "Replay-safe model-free head/middle/tail pruning for tool-result surface nodes", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/compact/compact/package.json b/packages/compact/compact/package.json index 18879ad5b5..6f484bf8f6 100644 --- a/packages/compact/compact/package.json +++ b/packages/compact/compact/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-compact", "description": "Abstract compaction service seam (ctx.compact) for the DeepSeek Harness", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/context/session-reference/package.json b/packages/context/session-reference/package.json index 4c7c7af3f8..c9dcb6af03 100644 --- a/packages/context/session-reference/package.json +++ b/packages/context/session-reference/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-session-reference", "description": "Cross-session snapshot references and durable untrusted model context (ctx.sessionReferences)", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/context/time-context/package.json b/packages/context/time-context/package.json index 6956bf48e0..c1c222bd6f 100644 --- a/packages/context/time-context/package.json +++ b/packages/context/time-context/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-time-context", "description": "Opt-in durable per-step context with the current time and elapsed time", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/context/tmux-context/package.json b/packages/context/tmux-context/package.json index 241661250f..6a4d7b81d8 100644 --- a/packages/context/tmux-context/package.json +++ b/packages/context/tmux-context/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-tmux-context", "description": "Opt-in durable per-step context with this agent's tmux pane and window location", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/context/workspace-context/package.json b/packages/context/workspace-context/package.json index 236009f90d..9181b2aded 100644 --- a/packages/context/workspace-context/package.json +++ b/packages/context/workspace-context/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-workspace-context", "description": "Workspace context loader for AGENTS.md/CLAUDE.md instruction files", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/core/agent-default-model/package.json b/packages/core/agent-default-model/package.json index 8826a9fcc4..6e3f6c0413 100644 --- a/packages/core/agent-default-model/package.json +++ b/packages/core/agent-default-model/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-agent-default-model", "description": "Default model selection shared by Agent entry points", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/core/agent-loop/package.json b/packages/core/agent-loop/package.json index 9f37505853..038822967a 100644 --- a/packages/core/agent-loop/package.json +++ b/packages/core/agent-loop/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-agent-loop", "description": "The concrete agent loop plugin for the DeepSeek Harness", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/core/agent-tool-mode/package.json b/packages/core/agent-tool-mode/package.json index a47dbd1434..e0d35abf0f 100644 --- a/packages/core/agent-tool-mode/package.json +++ b/packages/core/agent-tool-mode/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-agent-tool-mode", "description": "Agent-plane presentation selector: composes one agent's tools as Code Mode, native, or both", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/core/agent/package.json b/packages/core/agent/package.json index b4fe30f2e5..6c85552224 100644 --- a/packages/core/agent/package.json +++ b/packages/core/agent/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-agent", "description": "Agent interface, registry, initiator scope, and event vocabulary for the DeepSeek Harness", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/core/scope/package.json b/packages/core/scope/package.json index 53bd185aa5..d0a67e8841 100644 --- a/packages/core/scope/package.json +++ b/packages/core/scope/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-scope", "description": "Scoped-context registration primitive (scope tags, scope-filtered event dispatch) for the DeepSeek Harness", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/core/session/package.json b/packages/core/session/package.json index 40508e9a64..3528334b3c 100644 --- a/packages/core/session/package.json +++ b/packages/core/session/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-session", "description": "Event-sourced session store for the DeepSeek Harness", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/core/system-prompt/package.json b/packages/core/system-prompt/package.json index e219dfa37a..1f411b554f 100644 --- a/packages/core/system-prompt/package.json +++ b/packages/core/system-prompt/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-system-prompt", "description": "System prompt assembly registry for the DeepSeek Harness", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/core/tools/package.json b/packages/core/tools/package.json index e02c4afaef..6634098f99 100644 --- a/packages/core/tools/package.json +++ b/packages/core/tools/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-tools", "description": "Tool registry and execution pipeline for the DeepSeek Harness", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/credentials/credentials-local/package.json b/packages/credentials/credentials-local/package.json index 004c5caec4..977c51013c 100644 --- a/packages/credentials/credentials-local/package.json +++ b/packages/credentials/credentials-local/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-credentials-local", "description": "File-backed credentials provider ($DSH_HOME/.env under the live process environment) for the DeepSeek Harness", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/credentials/credentials/package.json b/packages/credentials/credentials/package.json index 8cc0d61e40..68c6be2f1b 100644 --- a/packages/credentials/credentials/package.json +++ b/packages/credentials/credentials/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-credentials", "description": "Abstract credential seam (ctx.credentials): settings carry references to secrets, providers own the values", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/e2b/e2b/package.json b/packages/e2b/e2b/package.json index fb47ba6c83..dafbb57b00 100644 --- a/packages/e2b/e2b/package.json +++ b/packages/e2b/e2b/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-e2b", "description": "Shared E2B sandbox lifecycle for DeepSeek Harness provider adapters", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/e2b/fs-e2b/package.json b/packages/e2b/fs-e2b/package.json index 47c026eaf2..1f6e085e5f 100644 --- a/packages/e2b/fs-e2b/package.json +++ b/packages/e2b/fs-e2b/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-fs-e2b", "description": "E2B filesystem implementation for DeepSeek Harness", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/e2b/subprocess-e2b/package.json b/packages/e2b/subprocess-e2b/package.json index b7be6db8be..dfbdf73da5 100644 --- a/packages/e2b/subprocess-e2b/package.json +++ b/packages/e2b/subprocess-e2b/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-subprocess-e2b", "description": "E2B subprocess implementation for DeepSeek Harness", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/examples/acp-demo/package.json b/packages/examples/acp-demo/package.json index 1c7763482c..1d35f2b23f 100644 --- a/packages/examples/acp-demo/package.json +++ b/packages/examples/acp-demo/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-acp-demo", "description": "ACP automation server app: agent spine + JSONL persistence + ACP transport, with a JSON-RPC stdio bin", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/examples/agent-spine-demo/package.json b/packages/examples/agent-spine-demo/package.json index 3bfac5084c..2092965d75 100644 --- a/packages/examples/agent-spine-demo/package.json +++ b/packages/examples/agent-spine-demo/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-agent-spine-demo", "description": "The default executor-less/UI-less agent spine with fallback session titles, provider-routed retry, and optional persisted goals", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/examples/jsonrpc-demo/package.json b/packages/examples/jsonrpc-demo/package.json index ac6b0f05ee..2524d75378 100644 --- a/packages/examples/jsonrpc-demo/package.json +++ b/packages/examples/jsonrpc-demo/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-jsonrpc-demo", "description": "Bin that boots an external Cordis config for the stdio JSON-RPC SDK runtime", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/feedback/command-feedback/package.json b/packages/feedback/command-feedback/package.json index afdba48641..b557eb788b 100644 --- a/packages/feedback/command-feedback/package.json +++ b/packages/feedback/command-feedback/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-command-feedback", "description": "Log-only session feedback producer and human-facing slash command", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/fs/fs-local/package.json b/packages/fs/fs-local/package.json index c79a13a9d2..77ed82d979 100644 --- a/packages/fs/fs-local/package.json +++ b/packages/fs/fs-local/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-fs-local", "description": "Local-filesystem implementation of the DeepSeek Harness filesystem seam (ctx.fs)", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/fs/fs-policy/package.json b/packages/fs/fs-policy/package.json index 39b6e0b6f0..a9e204ba90 100644 --- a/packages/fs/fs-policy/package.json +++ b/packages/fs/fs-policy/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-fs-policy", "description": "File-context policy plugin for the DeepSeek Harness — observed-state, read-before-edit, and version-guarded write/edit added over the ctx.fs provider seam through the fs/* event gate (no service surface)", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/fs/fs-sandbox/package.json b/packages/fs/fs-sandbox/package.json index 610724a528..cc6daed922 100644 --- a/packages/fs/fs-sandbox/package.json +++ b/packages/fs/fs-sandbox/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-fs-sandbox", "description": "Sandbox-enforcing implementation of the DeepSeek Harness filesystem seam: fences write/edit by the per-call sandbox mode (read-only denies mutation, workspace-write contains it to the workspace + temp roots) while reads pass through", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/fs/fs/package.json b/packages/fs/fs/package.json index fa97204f47..e9779e9d96 100644 --- a/packages/fs/fs/package.json +++ b/packages/fs/fs/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-fs", "description": "Abstract filesystem capability seam (ctx.fs) for the DeepSeek Harness — vocabulary types, the FileSystem service (text IO + optional version-guarded atomic mutations), and the fs/* policy event vocabulary", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/fs/tool-fs-search/package.json b/packages/fs/tool-fs-search/package.json index 8a6a50f1b3..ca56b0198a 100644 --- a/packages/fs/tool-fs-search/package.json +++ b/packages/fs/tool-fs-search/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-tool-fs-search", "description": "Model-facing filesystem discovery tools (glob, grep) backed by the packaged ripgrep binary (@vscode/ripgrep)", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/fs/tool-fs/package.json b/packages/fs/tool-fs/package.json index 1e4ef4fbf8..65ed3dcb1a 100644 --- a/packages/fs/tool-fs/package.json +++ b/packages/fs/tool-fs/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-tool-fs", "description": "Model-facing filesystem tools (read, write, edit) over the DeepSeek Harness filesystem seam (ctx.fs)", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/fs/tool-str-replace-editor/package.json b/packages/fs/tool-str-replace-editor/package.json index 2a3b18bfdc..5b20d4afc4 100644 --- a/packages/fs/tool-str-replace-editor/package.json +++ b/packages/fs/tool-str-replace-editor/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-tool-str-replace-editor", "description": "Model-facing view, create, literal replace, and line insert tool over the Harness filesystem service", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/goal/command-goal/package.json b/packages/goal/command-goal/package.json index bac6e02048..b87f385599 100644 --- a/packages/goal/command-goal/package.json +++ b/packages/goal/command-goal/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-command-goal", "description": "Human-facing slash command for persisted same-session goals", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/goal/goal-session/package.json b/packages/goal/goal-session/package.json index a43a4b1169..fa42ef63d3 100644 --- a/packages/goal/goal-session/package.json +++ b/packages/goal/goal-session/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-goal-session", "description": "Race-fenced same-session goal-round driver", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/goal/goal/package.json b/packages/goal/goal/package.json index 5ae59a8093..a2f90fced3 100644 --- a/packages/goal/goal/package.json +++ b/packages/goal/goal/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-goal", "description": "Event-sourced same-session goal state and lifecycle service for the DeepSeek Harness", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/goal/tool-goal/package.json b/packages/goal/tool-goal/package.json index 309e020842..e83648ab97 100644 --- a/packages/goal/tool-goal/package.json +++ b/packages/goal/tool-goal/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-tool-goal", "description": "Model-facing same-session goal tools with execution-time authority checks", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/guard/repeat-tool-guard/package.json b/packages/guard/repeat-tool-guard/package.json index fbb6a39192..27e7cc916e 100644 --- a/packages/guard/repeat-tool-guard/package.json +++ b/packages/guard/repeat-tool-guard/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-repeat-tool-guard", "description": "Repeat-tool-call guard plugin: advisory reminders when an agent loops on identical tool calls", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/guard/timeout-policy/package.json b/packages/guard/timeout-policy/package.json index ab07cc70e0..4800c0f472 100644 --- a/packages/guard/timeout-policy/package.json +++ b/packages/guard/timeout-policy/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-timeout-policy", "description": "Tool-call timeout policy: a tools/execute wrapper that arms a per-tool deadline on exec.signal and returns TOOL_TIMEOUT when it wins", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/hooks/hook-protocol/package.json b/packages/hooks/hook-protocol/package.json index 7d842222e0..ad92d9dd78 100644 --- a/packages/hooks/hook-protocol/package.json +++ b/packages/hooks/hook-protocol/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-hook-protocol", "description": "Shared Claude Code / Codex hook wire protocol: matcher engine, stdin/exit-code/stdout codec, multi-hook merge, and hook/* session events", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/hooks/hooks-claude/package.json b/packages/hooks/hooks-claude/package.json index a41e2e3b4d..9ed1ed7ceb 100644 --- a/packages/hooks/hooks-claude/package.json +++ b/packages/hooks/hooks-claude/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-hooks-claude", "description": "Bridge plugin: run a Claude Code hooks.json / settings hook config on the DeepSeek Harness interception seams", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/hooks/hooks-codex/package.json b/packages/hooks/hooks-codex/package.json index 4ff3f3dc38..a2bd73fba1 100644 --- a/packages/hooks/hooks-codex/package.json +++ b/packages/hooks/hooks-codex/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-hooks-codex", "description": "Bridge plugin: run a Codex hooks.json hook config on the DeepSeek Harness interception seams", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/host/apiproxy/package.json b/packages/host/apiproxy/package.json index c6da4ab3ae..6ccec04164 100644 --- a/packages/host/apiproxy/package.json +++ b/packages/host/apiproxy/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-host-apiproxy", "description": "API gateway: the ApiProxy contract (api/), the fetch carrier pair (fetch/), and the host-side gateway plugin providing ctx.apiProxy", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/host/directory-picker-auto/package.json b/packages/host/directory-picker-auto/package.json index bea692eedc..4ad110d48f 100644 --- a/packages/host/directory-picker-auto/package.json +++ b/packages/host/directory-picker-auto/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-host-directory-picker-auto", "description": "Adaptive chooser of the directory-picker seam: resolves the host situation at boot and mounts the native or browse backend for the DeepSeek Harness web GUI host", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/host/directory-picker-browse/package.json b/packages/host/directory-picker-browse/package.json index 224f73de29..3b42032e16 100644 --- a/packages/host/directory-picker-browse/package.json +++ b/packages/host/directory-picker-browse/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-host-directory-picker-browse", "description": "In-app browsing backend of the directory-picker seam (listing/creation primitives over the host filesystem)", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/host/directory-picker-native/package.json b/packages/host/directory-picker-native/package.json index acf9278c89..01817a238e 100644 --- a/packages/host/directory-picker-native/package.json +++ b/packages/host/directory-picker-native/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-host-directory-picker-native", "description": "Native-OS-chooser backend of the directory-picker seam for the DeepSeek Harness web GUI host", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/host/directory-picker/package.json b/packages/host/directory-picker/package.json index afad024fa2..0540414965 100644 --- a/packages/host/directory-picker/package.json +++ b/packages/host/directory-picker/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-host-directory-picker", "description": "Abstract workspace-directory picking seam (ctx.directoryPicker) for the DeepSeek Harness web GUI host", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/host/frontend-static/package.json b/packages/host/frontend-static/package.json index de7ceb9cf2..61c144abe9 100644 --- a/packages/host/frontend-static/package.json +++ b/packages/host/frontend-static/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-frontend-static", "description": "SPA dist server for the Web shell: owns the webserver fallback seat, serving the built frontend with index-tap injection, traversal rejection, and SPA index fallback", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/host/webserver/package.json b/packages/host/webserver/package.json index 48378f5ff9..016ae8f253 100644 --- a/packages/host/webserver/package.json +++ b/packages/host/webserver/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-host-webserver", "description": "Web route-registration plugin: HTTP and upgrade routes, index transform taps, and static dist fallback; knows no harness concepts", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/interaction/commands/package.json b/packages/interaction/commands/package.json index 8e527f64be..870a901b99 100644 --- a/packages/interaction/commands/package.json +++ b/packages/interaction/commands/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-commands", "description": "Plugin-owned human command registry for DeepSeek Harness UI surfaces", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/interaction/permission/package.json b/packages/interaction/permission/package.json index 85c959315d..054773f691 100644 --- a/packages/interaction/permission/package.json +++ b/packages/interaction/permission/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-permission", "description": "User-facing permission presets (ctx.permission) for the DeepSeek Harness: one product-level Permissions select bundling the sandbox-mode and approval-policy knobs, written through to their own session events", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/interaction/tool-ask-user/package.json b/packages/interaction/tool-ask-user/package.json index b0ffe378ee..dc025017e0 100644 --- a/packages/interaction/tool-ask-user/package.json +++ b/packages/interaction/tool-ask-user/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-tool-ask-user", "description": "Model-facing ask_user_question tool over the ctx.userInteraction seam", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/interaction/user-approval/package.json b/packages/interaction/user-approval/package.json index 892dcbcf87..37b29c4697 100644 --- a/packages/interaction/user-approval/package.json +++ b/packages/interaction/user-approval/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-user-approval", "description": "User-approval seam (ctx.approval) for the DeepSeek Harness: one-shot permission decisions dispatched to composed answerers over the approval/request waterfall, fail-closed by default", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/interaction/user-interaction/package.json b/packages/interaction/user-interaction/package.json index cd0336ae5c..fe90d7534c 100644 --- a/packages/interaction/user-interaction/package.json +++ b/packages/interaction/user-interaction/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-user-interaction", "description": "Abstract user-interaction seam (ctx.userInteraction) for asking the human during agent runs", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/llm/llm-deepseek/package.json b/packages/llm/llm-deepseek/package.json index 8baa42f0c9..834e6c5387 100644 --- a/packages/llm/llm-deepseek/package.json +++ b/packages/llm/llm-deepseek/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-llm-deepseek", "description": "DeepSeek chat-completions adapter for the DeepSeek Harness LLM seam", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/llm/llm-pi-ai/package.json b/packages/llm/llm-pi-ai/package.json index 5427a26277..3d36802a3e 100644 --- a/packages/llm/llm-pi-ai/package.json +++ b/packages/llm/llm-pi-ai/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-llm-pi-ai", "description": "pi-ai-backed DeepSeek adapter for the DeepSeek Harness LLM seam (design-verification twin of dsh-llm-deepseek)", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/llm/llm-retry/package.json b/packages/llm/llm-retry/package.json index 556d42abf9..da8358c620 100644 --- a/packages/llm/llm-retry/package.json +++ b/packages/llm/llm-retry/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-llm-retry", "description": "Provider-routed LLM request retry policy for the DeepSeek Harness", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/llm/llm/package.json b/packages/llm/llm/package.json index 9341670dd1..523ab16cb3 100644 --- a/packages/llm/llm/package.json +++ b/packages/llm/llm/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-llm", "description": "Provider-neutral LLM service interface for the DeepSeek Harness", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/llm/token-meter/package.json b/packages/llm/token-meter/package.json index 0755e6842a..ef08734fe2 100644 --- a/packages/llm/token-meter/package.json +++ b/packages/llm/token-meter/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-token-meter", "description": "Replay-aware token measurement service (ctx.tokenMeter) for the DeepSeek Harness", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/lsp/lsp-local/package.json b/packages/lsp/lsp-local/package.json index 9cdc20a6c7..f31e48080f 100644 --- a/packages/lsp/lsp-local/package.json +++ b/packages/lsp/lsp-local/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-lsp-local", "description": "Generic stdio language-server provider for the DeepSeek Harness LSP capability seam (ctx.lsp) — spawns configured servers, translates JSON-RPC, and serves transient-open goToDefinition/findReferences/goToImplementation/hover queries in the host filesystem namespace", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/lsp/lsp/package.json b/packages/lsp/lsp/package.json index 41b5f12e42..6395749c68 100644 --- a/packages/lsp/lsp/package.json +++ b/packages/lsp/lsp/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-lsp", "description": "Abstract LSP capability seam (ctx.lsp) for the DeepSeek Harness — language-server provider registry keyed by branded id and extension mapping, order-independent per-query selection, normalized definition/references/implementation/hover requests and results, and the LspError taxonomy", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/lsp/tool-lsp/package.json b/packages/lsp/tool-lsp/package.json index ab5b9603e8..d4003a61e5 100644 --- a/packages/lsp/tool-lsp/package.json +++ b/packages/lsp/tool-lsp/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-tool-lsp", "description": "Model-facing lsp tool over the DeepSeek Harness LSP capability seam (ctx.lsp) — one read-only tool with goToDefinition/findReferences/goToImplementation/hover operations, one-based UTF-16 cursor coordinates, bounded location rendering, and hover normalization", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/mcp/mcp-client/package.json b/packages/mcp/mcp-client/package.json index 1a12f7c674..99b3474c6e 100644 --- a/packages/mcp/mcp-client/package.json +++ b/packages/mcp/mcp-client/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-mcp-client", "description": "MCP client bridge: connects to MCP servers and registers their tools on ctx.tools", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/plan/plan-mode/package.json b/packages/plan/plan-mode/package.json index c8c228e00a..33b536d3ee 100644 --- a/packages/plan/plan-mode/package.json +++ b/packages/plan/plan-mode/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-plan-mode", "description": "Logged per-agent plan mode with deployment guidance, a direct slash command, and a user-reviewed exit", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/preset/agent-presets/package.json b/packages/preset/agent-presets/package.json index c5fc5eb165..5a3bd3e913 100644 --- a/packages/preset/agent-presets/package.json +++ b/packages/preset/agent-presets/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-agent-presets", "description": "Per-session agent composition from preset cordis.yml files for the DeepSeek Harness", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/preset/persona/package.json b/packages/preset/persona/package.json index db3121cdaa..7a9c4cd746 100644 --- a/packages/preset/persona/package.json +++ b/packages/preset/persona/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-persona", "description": "Composition-authored deployment persona section for the DeepSeek Harness", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/pty/pty-local/package.json b/packages/pty/pty-local/package.json index f7f84504bd..3db9e83889 100644 --- a/packages/pty/pty-local/package.json +++ b/packages/pty/pty-local/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-pty-local", "description": "Persistent shell PTY backend over the DeepSeek Harness subprocess terminal primitive", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/pty/pty/package.json b/packages/pty/pty/package.json index ad874ee876..37837181fb 100644 --- a/packages/pty/pty/package.json +++ b/packages/pty/pty/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-pty", "description": "Persistent PTY session seam for the DeepSeek Harness — owner-scoped ids, backend registry, interactive sends, reads, signals, and awaited cleanup", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/pty/tool-bash-persistent/package.json b/packages/pty/tool-bash-persistent/package.json index 25f248e047..0074f050b1 100644 --- a/packages/pty/tool-bash-persistent/package.json +++ b/packages/pty/tool-bash-persistent/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-tool-bash-persistent", "description": "Model-facing owner-scoped persistent Bash tool backed by the Harness PTY service", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/pty/tool-pty/package.json b/packages/pty/tool-pty/package.json index c60acc3572..804f6fb1a4 100644 --- a/packages/pty/tool-pty/package.json +++ b/packages/pty/tool-pty/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-tool-pty", "description": "Six model-facing persistent PTY tools with owner isolation and generic background-task integration", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/sandbox/sandbox-local/package.json b/packages/sandbox/sandbox-local/package.json index 52a2801b7b..64fdcb8991 100644 --- a/packages/sandbox/sandbox-local/package.json +++ b/packages/sandbox/sandbox-local/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-sandbox-local", "description": "Local process-sandbox backends for the DeepSeek Harness sandbox seam: bwrap, the npm-distributed landlock-run launcher, macOS Seatbelt, or the Windows ACL restricted-token runner — functionally probed, fail-closed", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/sandbox/sandbox-policy/package.json b/packages/sandbox/sandbox-policy/package.json index 9aaf77e59f..e5736878e3 100644 --- a/packages/sandbox/sandbox-policy/package.json +++ b/packages/sandbox/sandbox-policy/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-sandbox-policy", "description": "Per-call sandbox policy resolver and current model context: deployment fallbacks plus each session's mode and workspace root, shared by every enforcing capability family", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/sandbox/sandbox-windows-acl/package.json b/packages/sandbox/sandbox-windows-acl/package.json index a59898ea86..0cbc1e9113 100644 --- a/packages/sandbox/sandbox-windows-acl/package.json +++ b/packages/sandbox/sandbox-windows-acl/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-sandbox-windows-acl", "description": "Windows ACL write-restriction sandbox backend (restricted-token spawn with orphan-SID write allowlist) for the DeepSeek Harness sandbox seam", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/sandbox/sandbox/package.json b/packages/sandbox/sandbox/package.json index 057920ce44..b25c8b74a0 100644 --- a/packages/sandbox/sandbox/package.json +++ b/packages/sandbox/sandbox/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-sandbox", "description": "Abstract process-sandbox seam (ctx.sandbox) for the DeepSeek Harness: same-world confinement vocabulary and the SandboxProvider contract", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/scaffold/client/package.json b/packages/scaffold/client/package.json index 41786be068..796a32d5c0 100644 --- a/packages/scaffold/client/package.json +++ b/packages/scaffold/client/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-sdk-client", "description": "TypeScript client SDK for driving a DeepSeek Harness runtime subprocess over stdio JSON-RPC: the DeepSeekHarness high-level turns API and the lower-level HarnessClient", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/scaffold/create-sdk/package.json b/packages/scaffold/create-sdk/package.json index 3f4395eed7..33cf2f2f15 100644 --- a/packages/scaffold/create-sdk/package.json +++ b/packages/scaffold/create-sdk/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/create-sdk", "description": "Create a DeepSeek Harness SDK project with npm create @deepseek-ai/sdk", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/scaffold/helper/package.json b/packages/scaffold/helper/package.json index d79661c0ea..74df5f76a8 100644 --- a/packages/scaffold/helper/package.json +++ b/packages/scaffold/helper/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-helper", "description": "Domain model and infrastructure for creating and editing DeepSeek Harness SDK projects", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/scaffold/protocol/package.json b/packages/scaffold/protocol/package.json index 7fc86b5fc3..42c326edf8 100644 --- a/packages/scaffold/protocol/package.json +++ b/packages/scaffold/protocol/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-sdk-protocol", "description": "Shared wire protocol for the DeepSeek Harness SDK runtime: the newline-delimited JSON-RPC stdio transport and the named request, result, and notification types spoken between the runtime server and SDK clients", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/scaffold/scripts/package.json b/packages/scaffold/scripts/package.json index 20fd286b50..c12396fccc 100644 --- a/packages/scaffold/scripts/package.json +++ b/packages/scaffold/scripts/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-scripts", "description": "DeepSeek Harness SDK launcher for start, dev, build, and project configuration", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/scaffold/server/package.json b/packages/scaffold/server/package.json index 237ce06ecc..0bd44281fe 100644 --- a/packages/scaffold/server/package.json +++ b/packages/scaffold/server/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-jsonrpc", "description": "Stdio JSON-RPC server plugin for out-of-process DeepSeek Harness SDK clients", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/scaffold/telemetry/package.json b/packages/scaffold/telemetry/package.json index 50c501cd51..4dfeb54e2b 100644 --- a/packages/scaffold/telemetry/package.json +++ b/packages/scaffold/telemetry/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-telemetry", "description": "Launcher-side dsh-sdk telemetry: secret redaction, consent resolution, anonymous id, payload builder, and fire-and-forget reporter", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/self-modification/tool-cordis/package.json b/packages/self-modification/tool-cordis/package.json index ed0f466b62..66fc24d91a 100644 --- a/packages/self-modification/tool-cordis/package.json +++ b/packages/self-modification/tool-cordis/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-tool-cordis", "description": "Self-referential cordis toolset: inspect the live runtime, mount and dispose model-written plugins", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/session-query/session-query-sqlite/package.json b/packages/session-query/session-query-sqlite/package.json index 9a799bf167..156643a8bd 100644 --- a/packages/session-query/session-query-sqlite/package.json +++ b/packages/session-query/session-query-sqlite/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-session-query-sqlite", "description": "Concrete ctx.sessionQuery backend with SQLite FTS5 search", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/session-query/session-query/package.json b/packages/session-query/session-query/package.json index 6f19563c7b..4d0e4c29de 100644 --- a/packages/session-query/session-query/package.json +++ b/packages/session-query/session-query/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-session-query", "description": "Combined session query service contract with concrete reads, traces, and filters", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/session-query/tool-session-query/package.json b/packages/session-query/tool-session-query/package.json index 71afb52687..6d8ef7696a 100644 --- a/packages/session-query/tool-session-query/package.json +++ b/packages/session-query/tool-session-query/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-tool-session-query", "description": "Workspace-authorized model-facing session history search, trace, and event read tools", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/session/session-checkpoint-policy/package.json b/packages/session/session-checkpoint-policy/package.json index 1151cf1a9c..751b95d56a 100644 --- a/packages/session/session-checkpoint-policy/package.json +++ b/packages/session/session-checkpoint-policy/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-session-checkpoint-policy", "description": "Semantic session durability checkpoints before model requests and tool side effects", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/session/session-persistence-jsonl/package.json b/packages/session/session-persistence-jsonl/package.json index 38d6cfba97..aec127fa21 100644 --- a/packages/session/session-persistence-jsonl/package.json +++ b/packages/session/session-persistence-jsonl/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-session-persistence-jsonl", "description": "JSONL durable session persistence backend for the DeepSeek Harness", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/session/session-persistence-sqlite/package.json b/packages/session/session-persistence-sqlite/package.json index f52fdc6bca..60858d5aa8 100644 --- a/packages/session/session-persistence-sqlite/package.json +++ b/packages/session/session-persistence-sqlite/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-session-persistence-sqlite", "description": "SQLite durable session persistence backend for the DeepSeek Harness", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/session/session-persistence/package.json b/packages/session/session-persistence/package.json index 8430c7c91a..33c900a3d8 100644 --- a/packages/session/session-persistence/package.json +++ b/packages/session/session-persistence/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-session-persistence", "description": "Abstract durable session persistence seam (ctx.sessionPersistence) for the DeepSeek Harness", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/session/session-projection-cache/package.json b/packages/session/session-projection-cache/package.json index cbc40eebe0..59c3cd2a57 100644 --- a/packages/session/session-projection-cache/package.json +++ b/packages/session/session-projection-cache/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-session-projection-cache", "description": "Persisted projection cache (ctx.sessionProjectionCache): durable per-session projection checkpoints over the domain data form, throttled write-behind, and the cold-read ladder (cache row + persistence tail replay)", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/session/session-projection/package.json b/packages/session/session-projection/package.json index 4d7a438fae..fee23d3970 100644 --- a/packages/session/session-projection/package.json +++ b/packages/session/session-projection/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-session-projection", "description": "Session-projection seam: the merge-extensible projection type table, the provider contract, and the ctx.sessionProjections registry serving whole current values of log-derived per-session state", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/session/session-telemetry-otel/package.json b/packages/session/session-telemetry-otel/package.json index 0d2a88bc6a..d5229618a8 100644 --- a/packages/session/session-telemetry-otel/package.json +++ b/packages/session/session-telemetry-otel/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-session-telemetry-otel", "description": "OpenTelemetry backend for the DeepSeek Harness telemetry seam: hands captured session records to the OTel JS SDK's log pipeline", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/session/session-telemetry/package.json b/packages/session/session-telemetry/package.json index 613d1f6ac3..8dc9a7fb67 100644 --- a/packages/session/session-telemetry/package.json +++ b/packages/session/session-telemetry/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-session-telemetry", "description": "Telemetry seam for the DeepSeek Harness: session-event capture, projection, redaction, and handoff to a reporting backend", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/session/session-title-all-messages-llm/package.json b/packages/session/session-title-all-messages-llm/package.json index c406342a9f..d333b5d5ca 100644 --- a/packages/session/session-title-all-messages-llm/package.json +++ b/packages/session/session-title-all-messages-llm/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-session-title-all-messages-llm", "description": "All-user-messages LLM provider plugin for DeepSeek Harness session titles", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/session/session-title-first-message-llm/package.json b/packages/session/session-title-first-message-llm/package.json index a75f220053..f259b41435 100644 --- a/packages/session/session-title-first-message-llm/package.json +++ b/packages/session/session-title-first-message-llm/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-session-title-first-message-llm", "description": "First-message LLM provider plugin for DeepSeek Harness session titles", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/session/session-title-llm/package.json b/packages/session/session-title-llm/package.json index 062eca9259..dff4c3fde3 100644 --- a/packages/session/session-title-llm/package.json +++ b/packages/session/session-title-llm/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-session-title-llm", "description": "Shared LLM generation policy for DeepSeek Harness session-title providers", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/session/session-title/package.json b/packages/session/session-title/package.json index e0239f185b..5ae395c008 100644 --- a/packages/session/session-title/package.json +++ b/packages/session/session-title/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-session-title", "description": "Log-backed session title service and provider registry for the DeepSeek Harness", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/session/user-id/package.json b/packages/session/user-id/package.json index 36046b5b58..5ea2e7a5a9 100644 --- a/packages/session/user-id/package.json +++ b/packages/session/user-id/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-user-id", "description": "Shared anonymous user identity for DeepSeek Harness telemetry and feedback correlation", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/settings/settings-local/package.json b/packages/settings/settings-local/package.json index 0f5bca31f3..2ea49671fc 100644 --- a/packages/settings/settings-local/package.json +++ b/packages/settings/settings-local/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-settings-local", "description": "File-backed settings provider (settings.yaml) for the DeepSeek Harness", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/settings/settings/package.json b/packages/settings/settings/package.json index 568a8fba58..9899ded2cc 100644 --- a/packages/settings/settings/package.json +++ b/packages/settings/settings/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-settings", "description": "Abstract user-settings seam (ctx.settings) for the DeepSeek Harness", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/skill/skill-badge/package.json b/packages/skill/skill-badge/package.json index eb55678529..c3c79538c2 100644 --- a/packages/skill/skill-badge/package.json +++ b/packages/skill/skill-badge/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-skill-badge", "description": "Bundled dsh badge skill provider for DeepSeek Harness", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/skill/skill-local/package.json b/packages/skill/skill-local/package.json index 386da9386b..c9f3ba8f27 100644 --- a/packages/skill/skill-local/package.json +++ b/packages/skill/skill-local/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-skill-local", "description": "Local filesystem skill provider for the DeepSeek Harness", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/skill/skill/package.json b/packages/skill/skill/package.json index b546ae9c60..dbb4429d9d 100644 --- a/packages/skill/skill/package.json +++ b/packages/skill/skill/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-skill", "description": "Agent skill provider registry for the DeepSeek Harness", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/skill/tool-skill/package.json b/packages/skill/tool-skill/package.json index f1315b47cf..7712261549 100644 --- a/packages/skill/tool-skill/package.json +++ b/packages/skill/tool-skill/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-tool-skill", "description": "Model-facing skill loading tool for the DeepSeek Harness", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/spill/spill-local/package.json b/packages/spill/spill-local/package.json index 43f1bfcfeb..1bab4c650f 100644 --- a/packages/spill/spill-local/package.json +++ b/packages/spill/spill-local/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-spill-local", "description": "Local-filesystem implementation of the DeepSeek Harness spill storage seam (private session-scoped files)", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/spill/spill-policy/package.json b/packages/spill/spill-policy/package.json index 8236e9104a..cadec495fb 100644 --- a/packages/spill/spill-policy/package.json +++ b/packages/spill/spill-policy/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-spill-policy", "description": "Tool-result spill policy for the DeepSeek Harness — replaces oversized plain-text tool results with a retained preview plus a spill-file path (no service surface)", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/spill/spill/package.json b/packages/spill/spill/package.json index 48a21f52c9..c3379e6f72 100644 --- a/packages/spill/spill/package.json +++ b/packages/spill/spill/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-spill", "description": "Abstract spill storage seam (ctx.spillStore) for the DeepSeek Harness — save oversized tool text and return a retrieval locator", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/storage/storage-domain/package.json b/packages/storage/storage-domain/package.json index 9c3acd2ba7..064ec4aa8a 100644 --- a/packages/storage/storage-domain/package.json +++ b/packages/storage/storage-domain/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-storage-domain", "description": "Domain data form (ctx.storage.domain): schema-validated, event-emitting KV domains over storage backends for the DeepSeek Harness", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/storage/storage-json/package.json b/packages/storage/storage-json/package.json index 86ec3dc5b8..78e1d9231a 100644 --- a/packages/storage/storage-json/package.json +++ b/packages/storage/storage-json/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-storage-json", "description": "JSON file KV storage backend for the DeepSeek Harness storage hub", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/storage/storage-sqlite/package.json b/packages/storage/storage-sqlite/package.json index b30e80b5e7..2fef41cebd 100644 --- a/packages/storage/storage-sqlite/package.json +++ b/packages/storage/storage-sqlite/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-storage-sqlite", "description": "SQLite storage backend (kv facet) for the DeepSeek Harness storage hub", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/storage/storage/package.json b/packages/storage/storage/package.json index efe8294de3..39c8f0bed3 100644 --- a/packages/storage/storage/package.json +++ b/packages/storage/storage/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-storage", "description": "Storage hub (ctx.storage): named backend registry plus mounted data-form facilities for the DeepSeek Harness", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/subagent/subagent-acp/package.json b/packages/subagent/subagent-acp/package.json index 62a648e3d5..5efd65bcd5 100644 --- a/packages/subagent/subagent-acp/package.json +++ b/packages/subagent/subagent-acp/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-subagent-acp", "description": "Out-of-process ACP subagent backend: drives a child agent in a spawned subprocess over the Agent Client Protocol", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/subagent/subagent-claude-code/package.json b/packages/subagent/subagent-claude-code/package.json index 22876aa0ca..4767d1ccb8 100644 --- a/packages/subagent/subagent-claude-code/package.json +++ b/packages/subagent/subagent-claude-code/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-subagent-claude-code", "description": "One-shot Claude Code subagent provider over the official Agent SDK", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/subagent/subagent-codex/package.json b/packages/subagent/subagent-codex/package.json index d22b5c517f..17e13287ef 100644 --- a/packages/subagent/subagent-codex/package.json +++ b/packages/subagent/subagent-codex/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-subagent-codex", "description": "One-shot Codex subagent provider over the official app-server protocol", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/subagent/subagent-dsh-sdk/package.json b/packages/subagent/subagent-dsh-sdk/package.json index d6cc3a3eef..5d15e3da45 100644 --- a/packages/subagent/subagent-dsh-sdk/package.json +++ b/packages/subagent/subagent-dsh-sdk/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-subagent-dsh-sdk", "description": "Out-of-process SDK subagent backend: drives a child DeepSeek Harness runtime subprocess over stdio JSON-RPC through the TypeScript SDK client", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/subagent/subagent-fork/package.json b/packages/subagent/subagent-fork/package.json index 08515ea47b..85ef8c6d88 100644 --- a/packages/subagent/subagent-fork/package.json +++ b/packages/subagent/subagent-fork/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-subagent-fork", "description": "In-process fork subagent backend: runs a child agent seeded with a prefix of the parent's log", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/subagent/subagent-inprocess/package.json b/packages/subagent/subagent-inprocess/package.json index 8bf3d7a8ca..457bd16d36 100644 --- a/packages/subagent/subagent-inprocess/package.json +++ b/packages/subagent/subagent-inprocess/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-subagent-inprocess", "description": "Shared in-process subagent run driver: drives a child agent on ctx.agents (used by the spawn and fork backends)", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/subagent/subagent-spawn/package.json b/packages/subagent/subagent-spawn/package.json index a45bc78143..094470807b 100644 --- a/packages/subagent/subagent-spawn/package.json +++ b/packages/subagent/subagent-spawn/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-subagent-spawn", "description": "In-process spawn subagent backend: runs a fresh child agent on ctx.agents", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/subagent/subagent/package.json b/packages/subagent/subagent/package.json index 4be1d4d947..8a1bbef19f 100644 --- a/packages/subagent/subagent/package.json +++ b/packages/subagent/subagent/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-subagent", "description": "Abstract subagent seam (ctx.subagents): named-provider registry for delegating to child agents", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/subagent/tool-subagent-control/package.json b/packages/subagent/tool-subagent-control/package.json index 0184a5af1a..1a4a1ad4ad 100644 --- a/packages/subagent/tool-subagent-control/package.json +++ b/packages/subagent/tool-subagent-control/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-tool-subagent-control", "description": "Globally named send_message, interrupt_agent, and list_agents tools over ctx.subagents continuations", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/subagent/tool-subagent-report/package.json b/packages/subagent/tool-subagent-report/package.json index 78adfef325..f9dcd90588 100644 --- a/packages/subagent/tool-subagent-report/package.json +++ b/packages/subagent/tool-subagent-report/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-tool-subagent-report", "description": "Child-scoped report tool over ctx.subagents continuations", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/subagent/tool-subagent/package.json b/packages/subagent/tool-subagent/package.json index 6930f5dcc2..b4b912e7db 100644 --- a/packages/subagent/tool-subagent/package.json +++ b/packages/subagent/tool-subagent/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-tool-subagent", "description": "Model-facing subagent delegation tool over the ctx.subagents seam", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/subprocess/subprocess-local/package.json b/packages/subprocess/subprocess-local/package.json index d307a0742b..12f47c0400 100644 --- a/packages/subprocess/subprocess-local/package.json +++ b/packages/subprocess/subprocess-local/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-subprocess-local", "description": "Local-subprocess implementation of the DeepSeek Harness subprocess seam", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/subprocess/subprocess/package.json b/packages/subprocess/subprocess/package.json index 214f5f67a8..55558024f4 100644 --- a/packages/subprocess/subprocess/package.json +++ b/packages/subprocess/subprocess/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-subprocess", "description": "Subprocess seam (ctx.subprocess) for the DeepSeek Harness — managed process groups, bounded spill-backed output, and escalated kills behind one abstract service", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/support/acp-snapshot/package.json b/packages/support/acp-snapshot/package.json index 642565885f..e06a890806 100644 --- a/packages/support/acp-snapshot/package.json +++ b/packages/support/acp-snapshot/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-acp-snapshot", "description": "ACP test kit: shared subprocess launcher, snapshot scenario harness, expected-output normalizers, and suite factory", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/support/agent-loop-testkit/package.json b/packages/support/agent-loop-testkit/package.json index 0bde847ca9..43c49f3953 100644 --- a/packages/support/agent-loop-testkit/package.json +++ b/packages/support/agent-loop-testkit/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-agent-loop-testkit", "description": "Shared prerequisite mounting for tests that exercise the concrete agent loop", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/support/invariants/package.json b/packages/support/invariants/package.json index 122ab3dd9f..1d01c18bd0 100644 --- a/packages/support/invariants/package.json +++ b/packages/support/invariants/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-invariants", "description": "Registry service for package-owned DeepSeek Harness runtime invariants", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/support/llm-mock-server/package.json b/packages/support/llm-mock-server/package.json index 13456d14e7..203b092987 100644 --- a/packages/support/llm-mock-server/package.json +++ b/packages/support/llm-mock-server/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-llm-mock-server", "description": "Scriptable OpenAI-compatible HTTP/SSE fault server for LLM recovery tests", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/support/llm-replay/package.json b/packages/support/llm-replay/package.json index 326d13bb81..3c05e7fbf6 100644 --- a/packages/support/llm-replay/package.json +++ b/packages/support/llm-replay/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-llm-replay", "description": "Replay LLM plugin: short-circuits llm/stream with model chunks reconstructed from a recorded session JSONL (keyless snapshot tests)", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/support/loader-smoke/package.json b/packages/support/loader-smoke/package.json index 169bf2f548..9f43ca3a01 100644 --- a/packages/support/loader-smoke/package.json +++ b/packages/support/loader-smoke/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-loader-smoke", "description": "Shared subprocess and direct-agent harness for keyless real-Loader example smoke tests", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/tasks/tasks-local/package.json b/packages/tasks/tasks-local/package.json index b92cbfe03f..cd40629948 100644 --- a/packages/tasks/tasks-local/package.json +++ b/packages/tasks/tasks-local/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-tasks-local", "description": "Process-local implementation of the DeepSeek Harness background task registry seam", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/tasks/tasks/package.json b/packages/tasks/tasks/package.json index 5bd6a7e3c1..cfc7fa70bf 100644 --- a/packages/tasks/tasks/package.json +++ b/packages/tasks/tasks/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-tasks", "description": "Background task registry (ctx.tasks) for the DeepSeek Harness — shared ids, owner isolation, polling, cancellation, and completion listeners for long-running tool work", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/tasks/tool-tasks/package.json b/packages/tasks/tool-tasks/package.json index 69aed7e859..c1ab0be9c4 100644 --- a/packages/tasks/tool-tasks/package.json +++ b/packages/tasks/tool-tasks/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-tool-tasks", "description": "Model-facing background task control tools (task_output, task_list, task_kill) over the ctx.tasks registry", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/todo/tool-todo/package.json b/packages/todo/tool-todo/package.json index d15d05bb10..0f080c5d33 100644 --- a/packages/todo/tool-todo/package.json +++ b/packages/todo/tool-todo/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-tool-todo", "description": "Model-facing todo_write tool over the DeepSeek Harness event-sourced session log", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/typert/generator/package.json b/packages/typert/generator/package.json index f17ce63b8a..53e711b3a7 100644 --- a/packages/typert/generator/package.json +++ b/packages/typert/generator/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-typert-generator", "description": "TypeScript project analyzer and model-driven Typert artifact generator", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/typert/loader/package.json b/packages/typert/loader/package.json index 7d1baa743a..ec66e2165b 100644 --- a/packages/typert/loader/package.json +++ b/packages/typert/loader/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-typert-loader", "description": "Loader integration for generated Typert package contributions", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/typert/registry/package.json b/packages/typert/registry/package.json index 464415116b..0a75703929 100644 --- a/packages/typert/registry/package.json +++ b/packages/typert/registry/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-typert-registry", "description": "Runtime registry for generated package reflection and Zod schemas", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/typert/type-meta/package.json b/packages/typert/type-meta/package.json index e383ba0eec..3195392acb 100644 --- a/packages/typert/type-meta/package.json +++ b/packages/typert/type-meta/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-type-meta", "description": "Compiler-independent Remote metadata and TypeRT provider protocols", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/util/atomic-write/package.json b/packages/util/atomic-write/package.json index b514058816..a26a5e62d3 100644 --- a/packages/util/atomic-write/package.json +++ b/packages/util/atomic-write/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-atomic-write", "description": "Zero-dependency atomic file replacement: exclusive-create random-suffix temp + rename carrying the caller-stated permissions (writeFileAtomic)", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/util/brand/package.json b/packages/util/brand/package.json index 01f33fefe5..1496dfdb3a 100644 --- a/packages/util/brand/package.json +++ b/packages/util/brand/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-brand", "description": "Type-only Branded nominal-typing primitive for the DeepSeek Harness", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/util/environment/package.json b/packages/util/environment/package.json index ddc2e40d23..6fa44ab20c 100644 --- a/packages/util/environment/package.json +++ b/packages/util/environment/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-environment", "description": "Immutable DeepSeek Harness launch environment that records which layer supplied each value", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/util/native-command/package.json b/packages/util/native-command/package.json index b3145ee41a..af0891fb82 100644 --- a/packages/util/native-command/package.json +++ b/packages/util/native-command/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-native-command", "description": "Zero-dependency no-shell execFile runner for host-native OS integrations: utf8 stdio capture, abort propagation, Windows hide", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/util/paths/package.json b/packages/util/paths/package.json index 04d692f56d..e3c492ea34 100644 --- a/packages/util/paths/package.json +++ b/packages/util/paths/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-paths", "description": "Shared filesystem path helpers for the DeepSeek Harness", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/util/retention/package.json b/packages/util/retention/package.json index 7e172bb131..eea04fee3e 100644 --- a/packages/util/retention/package.json +++ b/packages/util/retention/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-retention", "description": "Zero-dependency bounded-retention primitive: ItemRetainer/TextRetainer + neutral notice helpers (what did we keep, what did we omit)", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/util/timeout/package.json b/packages/util/timeout/package.json index 194662100a..72daaa2c6b 100644 --- a/packages/util/timeout/package.json +++ b/packages/util/timeout/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-timeout", "description": "Zero-dependency timeout/deadline primitive: clampTimeout, deadline, timeoutOf, TimeoutReason (timing + classification only, no termination)", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/web/tool-web/package.json b/packages/web/tool-web/package.json index c5e1ea2b6b..0135e83403 100644 --- a/packages/web/tool-web/package.json +++ b/packages/web/tool-web/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-tool-web", "description": "Model-facing web tools (web_search, web_fetch) over the DeepSeek Harness web capability seam (ctx.web)", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/web/web-fetch-local/package.json b/packages/web/web-fetch-local/package.json index 148ecde3e0..562f8be8f6 100644 --- a/packages/web/web-fetch-local/package.json +++ b/packages/web/web-fetch-local/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-web-fetch-local", "description": "Anonymous public HTTP(S) fetch provider for the DeepSeek Harness web capability seam (ctx.web)", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/web/web-search-deepseek/package.json b/packages/web/web-search-deepseek/package.json index f3b29d20a4..c3d304678c 100644 --- a/packages/web/web-search-deepseek/package.json +++ b/packages/web/web-search-deepseek/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-web-search-deepseek", "description": "DeepSeek-backed search provider (native web_search via the Anthropic-compatible API) for the DeepSeek Harness web capability seam (ctx.web)", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/web/web-search-exa/package.json b/packages/web/web-search-exa/package.json index da16ca3fce..55b18bec50 100644 --- a/packages/web/web-search-exa/package.json +++ b/packages/web/web-search-exa/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-web-search-exa", "description": "Exa-backed search provider for the DeepSeek Harness web capability seam (ctx.web)", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/web/web-search-perplexity/package.json b/packages/web/web-search-perplexity/package.json index 1d266f1d13..09c3b823ae 100644 --- a/packages/web/web-search-perplexity/package.json +++ b/packages/web/web-search-perplexity/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-web-search-perplexity", "description": "Perplexity-backed search provider for the DeepSeek Harness web capability seam (ctx.web)", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/web/web/package.json b/packages/web/web/package.json index d9cf4f5726..21e9811c1e 100644 --- a/packages/web/web/package.json +++ b/packages/web/web/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-web", "description": "Abstract web access capability seam (ctx.web) for the DeepSeek Harness — search/fetch provider registry, registration-order-independent selection, request/result vocabulary, and the WebError taxonomy", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/workflow/tool-ralph/package.json b/packages/workflow/tool-ralph/package.json index 341508e3ed..f92eb944c4 100644 --- a/packages/workflow/tool-ralph/package.json +++ b/packages/workflow/tool-ralph/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-tool-ralph", "description": "Model-facing fresh-agent Ralph loop over the workflow and subagent seams", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/workflow/tool-workflow/package.json b/packages/workflow/tool-workflow/package.json index d111d2797d..4d8bc7b924 100644 --- a/packages/workflow/tool-workflow/package.json +++ b/packages/workflow/tool-workflow/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-tool-workflow", "description": "Model-facing workflow tool: run a JavaScript orchestration script over ctx.workflows", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/workflow/workflow-workerthread/package.json b/packages/workflow/workflow-workerthread/package.json index 53e03ebc2d..af20d74fb2 100644 --- a/packages/workflow/workflow-workerthread/package.json +++ b/packages/workflow/workflow-workerthread/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-workflow-workerthread", "description": "worker-thread workflow engine: executes model-written orchestration scripts off the host event loop, bridging agent() calls back to ctx.subagents", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/workflow/workflow/package.json b/packages/workflow/workflow/package.json index 1c342bcebe..23976826bb 100644 --- a/packages/workflow/workflow/package.json +++ b/packages/workflow/workflow/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-workflow", "description": "Workflow capability seam: ctx.workflows service, run vocabulary, and workflow/* events", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, diff --git a/packages/workspace/workspace/package.json b/packages/workspace/workspace/package.json index 7efc53b6c8..4ab1aeecbe 100644 --- a/packages/workspace/workspace/package.json +++ b/packages/workspace/workspace/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-workspace", "description": "Workspace entity registry (ctx.workspace): durable workspace records with validated session attachment over the domain data form for the DeepSeek Harness", - "version": "0.0.1", + "version": "0.0.1-rc.1", "publishConfig": { "access": "restricted" }, From 3e79f7106e6017142a21037028f15781a39fce10 Mon Sep 17 00:00:00 2001 From: imccyu <276526105+imccyu@users.noreply.github.com> Date: Mon, 10 Aug 2026 18:37:59 +0800 Subject: [PATCH 20/36] feat(client-runtime): add target-owned conversation snapshots --- .../src/client/contract/conversation.ts | 21 +++++-- .../src/client/conversation/event-registry.ts | 13 ++++- packages/client/runtime/src/client/index.ts | 37 ++---------- .../client/sessions/conversation-assembler.ts | 57 +++++++++++-------- .../src/client/sessions/conversation.ts | 9 ++- .../runtime/src/client/sessions/session.ts | 1 + .../client/runtime/tests/client-apply.spec.ts | 1 + .../tests/conversation-assembler.spec.ts | 23 ++++++-- .../tests/conversation-registry.spec.ts | 1 + packages/client/runtime/tests/session.spec.ts | 5 +- packages/client/test-runtime/src/fixtures.ts | 5 +- .../client/conversation-nodes/assistant.ts | 4 +- .../src/client/conversation-nodes/command.ts | 4 +- .../client/conversation-nodes/compaction.ts | 4 +- .../src/client/conversation-nodes/fallback.ts | 3 +- .../src/client/conversation-nodes/inbox.ts | 1 - .../src/client/conversation-nodes/message.ts | 5 +- .../src/client/conversation-nodes/retry.ts | 5 +- .../src/client/conversation-nodes/tool.ts | 4 +- .../client/conversation-nodes/turn-error.ts | 4 +- .../client/conversation-nodes/turn-tail.ts | 4 +- .../ui-conversation/tests/chat-stats.spec.tsx | 3 +- .../ui-conversation/tests/chat-view.spec.tsx | 6 +- .../tests/gate-branch-tails.spec.tsx | 6 +- .../ui-conversation/tests/input-bar.spec.tsx | 6 +- .../tests/input-matrix.spec.tsx | 6 +- .../tests/input-scenarios.spec.tsx | 6 +- .../ui-conversation/tests/queue-dock.spec.tsx | 6 +- .../ui-conversation/tests/skeleton.spec.tsx | 6 +- .../src/client/turn-deliverables.ts | 1 + .../tests/produced-files.spec.tsx | 2 +- .../ui-tool/tests/chat-code-subcalls.spec.tsx | 6 +- .../client/ui-tool/tests/diff-card.spec.tsx | 7 ++- .../client/ui-tool/tests/read-card.spec.tsx | 7 ++- .../client/ui-tool/tests/search-card.spec.tsx | 7 ++- .../ui-tool/tests/terminal-card.spec.tsx | 7 ++- .../client/ui-tool/tests/web-card.spec.tsx | 7 ++- 37 files changed, 183 insertions(+), 117 deletions(-) diff --git a/packages/client/runtime/src/client/contract/conversation.ts b/packages/client/runtime/src/client/contract/conversation.ts index 9507046b33..7119980839 100644 --- a/packages/client/runtime/src/client/contract/conversation.ts +++ b/packages/client/runtime/src/client/contract/conversation.ts @@ -110,6 +110,17 @@ export interface ConversationViewNode { readonly data: unknown } +/** Merge-extensible immutable snapshots published by registered view targets. */ +export interface ConversationViewSnapshotMap {} + +/** Stable reader over the latest snapshot of every registered view target. */ +export interface ConversationViewSnapshotStore { + /** @param target - registered view target. @returns its current snapshot. */ + get( + target: Target, + ): ConversationViewSnapshotMap[Target] | undefined +} + /** Final Chat render unit produced directly by a business Definition. */ export interface ChatConversationViewNode extends ConversationViewNode { readonly target: 'chat' @@ -159,6 +170,8 @@ export type ConversationLocationDataScope = 'step' | 'turn' /** One independently registered business Event-to-Node state machine. */ export interface ConversationNodeDefinition { readonly kind: string + /** Sole view target owned by this Definition; omitted for state-only Contexts. */ + readonly target?: string /** * Extract this Definition's stable business identity from one event. * @param event - raw Session event; no Context or history access is available. @@ -207,15 +220,11 @@ export interface ConversationNodeDefinition { scope: ConversationLocationDataScope, ): ConversationLocationData | null /** - * Materialize one final Node for a registered view target. + * Materialize one final Node for this Definition's declared view target. * @param context - latest complete Context. - * @param target - registered view target such as `chat`. * @returns final Node, or null when this Context is not currently visible. */ - buildViewNode( - context: ConversationNodeContext, - target: string, - ): ConversationViewNode | null + buildViewNode?(context: ConversationNodeContext): ConversationViewNode | null } /** Reference-stable Turn/Step facts published beside view Nodes. */ diff --git a/packages/client/runtime/src/client/conversation/event-registry.ts b/packages/client/runtime/src/client/conversation/event-registry.ts index 381fff81b5..d9eabda538 100644 --- a/packages/client/runtime/src/client/conversation/event-registry.ts +++ b/packages/client/runtime/src/client/conversation/event-registry.ts @@ -17,6 +17,7 @@ export class ConversationEventRegistry extends ConversationDefinitionRegistry void { + assertDefinitionTarget(definition) return this.registerDefinition( definition.kind, definition, @@ -31,6 +32,9 @@ export class ConversationEventRegistry extends ConversationDefinitionRegistry void { + assertDefinitionTarget(definition) + const target = definition.target + if (target === undefined) throw new Error('conversation fallback Definition must declare a target') if (this.fallback !== undefined) throw new Error('conversation fallback Definition is already registered') const owner = this.ctx const dispose = owner.effect(() => { @@ -52,5 +56,12 @@ export class ConversationEventRegistry extends ConversationDefinitionRegistry sessions.scopeOf(candidate), }) - const sessionHistory = new SessionHistoryService(ctx, connection.api) const workspaces = new WorkspacesService(ctx, connection.api, sessions) ctx.effect( () => workspaces.startInitialSelection(), @@ -244,11 +237,6 @@ export function apply(ctx: Context): void { const loop = connection.start({ onMuxEnvelope: (envelope) => { sessions.handleMuxEnvelope(envelope) - try { - sessionHistory.handleMuxEnvelope(envelope) - } catch (error) { - console.error('[web-runtime] history frame routing failed:', error) - } }, onHostEnvelope: (envelope) => { sessions.handleHostEnvelope(envelope) @@ -264,21 +252,11 @@ export function apply(ctx: Context): void { else if (frame.type === 'host/settings-changed') ctx.emit('settings/changed', frame.ns) else if (frame.type === 'host/credentials-changed') ctx.emit('credentials/changed', frame.ref) else if (frame.type === 'host/models-changed') ctx.emit('models/changed') - try { - sessionHistory.handleHostEnvelope(envelope) - } catch (error) { - console.error('[web-runtime] history host-frame routing failed:', error) - } }, onConnected: () => { sessions.handleConnected() workspaces.handleConnected() ctx.emit('connection/reset') - try { - sessionHistory.handleConnected() - } catch (error) { - console.error('[web-runtime] history reconnect failed:', error) - } }, onStateChange: (state) => { // Generation death fires before any next-generation frame can arrive @@ -286,11 +264,6 @@ export function apply(ctx: Context): void { // the only safe moment to drop generation-scoped interaction state. if (state === 'reconnecting') { sessions.handleDisconnected() - try { - sessionHistory.handleDisconnected() - } catch (error) { - console.error('[web-runtime] history disconnect failed:', error) - } } }, }) diff --git a/packages/client/runtime/src/client/sessions/conversation-assembler.ts b/packages/client/runtime/src/client/sessions/conversation-assembler.ts index bdd89f56a4..ee8e6b0eae 100644 --- a/packages/client/runtime/src/client/sessions/conversation-assembler.ts +++ b/packages/client/runtime/src/client/sessions/conversation-assembler.ts @@ -2,7 +2,8 @@ import type { ConversationContextReader, ConversationEventInput, ConversationLocationData, ConversationMatch, ConversationNodeContext, ConversationNodeDefinition, ConversationPreviousContext, ConversationLocationDataScope, ConversationPublication, ConversationViewBuilder, - ConversationViewDefinition, ConversationViewNode, + ConversationViewDefinition, ConversationViewNode, ConversationViewSnapshotMap, + ConversationViewSnapshotStore, } from '../contract/conversation.ts' import { conversationContextKey } from '../contract/conversation.ts' import { @@ -133,7 +134,7 @@ export interface ConversationViewDefinitions { * Session-owned incremental engine that assembles business Contexts from a * contiguous Event window and materializes registered view snapshots. */ -export class ConversationNodeAssembler { +export class ConversationNodeAssembler implements ConversationViewSnapshotStore { private readonly contexts = new Map() private readonly contextsByKind = new Map() private readonly contextsBySeq = new Map>() @@ -266,11 +267,11 @@ export class ConversationNodeAssembler { const allByTarget = new Map() for (const target of this.views.keys()) allByTarget.set(target, []) for (const context of this.contexts.values()) { - for (const target of this.views.keys()) { - const node = this.buildNode(context, target) - context.current.set(target, node) - if (node !== null) allByTarget.get(target)?.push(node) - } + const target = context.definition.target + if (target === undefined || !this.views.has(target)) continue + const node = this.buildNode(context, target) + context.current.set(target, node) + if (node !== null) allByTarget.get(target)?.push(node) } for (const view of this.views.values()) { view.snapshot = view.builder.replace({ @@ -288,17 +289,17 @@ export class ConversationNodeAssembler { for (const target of this.views.keys()) upsertsByTarget.set(target, []) if (this.applyDirtyLocationData()) this.timelineDirty = true for (const context of this.dirty) { - for (const target of this.views.keys()) { - const previous = context.current.get(target) ?? null - const node = this.buildNode(context, target) - if (node === null && previous !== null) { - throw new Error( - `conversation Definition "${context.kind}" withdrew materialized target "${target}"; return the same key with hidden visibility instead`, - ) - } - context.current.set(target, node) - if (node !== null) upsertsByTarget.get(target)?.push(node) + const target = context.definition.target + if (target === undefined || !this.views.has(target)) continue + const previous = context.current.get(target) ?? null + const node = this.buildNode(context, target) + if (node === null && previous !== null) { + throw new Error( + `conversation Definition "${context.kind}" withdrew materialized target "${target}"; return the same key with hidden visibility instead`, + ) } + context.current.set(target, node) + if (node !== null) upsertsByTarget.get(target)?.push(node) } this.dirty.clear() const timelineDirty = this.timelineDirty @@ -323,6 +324,12 @@ export class ConversationNodeAssembler { return this.views.get(target)?.snapshot } + get( + target: Target, + ): ConversationViewSnapshotMap[Target] | undefined { + return this.snapshot(target) as ConversationViewSnapshotMap[Target] | undefined + } + private sortedInputs(): ConversationEventInput[] { return [...this.inputs.values()].sort((left, right) => left.event.seq - right.event.seq) } @@ -358,18 +365,19 @@ export class ConversationNodeAssembler { role: ConversationMatch['role'], ) => ConversationPublication, ): ConversationPublication { - let matched = false + const matchedTargets = new Set() let publication: ConversationPublication = 'none' for (const definition of this.eventDefinitions.entries()) { const result = definition.match(input.event) if (result === null) continue - matched = true + if (definition.target !== undefined) matchedTargets.add(definition.target) publication = maximumPublication(publication, accept(definition, result.id, result.role)) } - if (!matched) { - const fallback = this.eventDefinitions.fallbackEntry() - const result = fallback?.match(input.event) ?? null - if (fallback !== undefined && result !== null) { + const fallback = this.eventDefinitions.fallbackEntry() + const target = fallback?.target + if (fallback !== undefined && target !== undefined && !matchedTargets.has(target)) { + const result = fallback.match(input.event) + if (result !== null) { publication = maximumPublication(publication, accept(fallback, result.id, result.role)) } } @@ -697,7 +705,8 @@ export class ConversationNodeAssembler { } private buildNode(context: InternalContext, target: string): ConversationViewNode | null { - const node = context.definition.buildViewNode(contextSnapshot(context), target) + if (context.definition.target !== target || context.definition.buildViewNode === undefined) return null + const node = context.definition.buildViewNode(contextSnapshot(context)) if (node === null) return null if (node.key !== context.key) { throw new Error(`conversation Definition "${context.kind}" returned unstable key "${node.key}"; expected "${context.key}"`) diff --git a/packages/client/runtime/src/client/sessions/conversation.ts b/packages/client/runtime/src/client/sessions/conversation.ts index a14d6fbb96..4397013dab 100644 --- a/packages/client/runtime/src/client/sessions/conversation.ts +++ b/packages/client/runtime/src/client/sessions/conversation.ts @@ -17,7 +17,7 @@ import type { import type { PendingInteraction } from './pending.ts' import type { ContextProvenanceView, KnownContextForm } from './context-provenance.ts' import type { - ChatConversationViewNode, ConversationTimelineSnapshot, + ChatConversationViewNode, ConversationTimelineSnapshot, ConversationViewSnapshotStore, } from '../contract/conversation.ts' export type { TodoItem } @@ -384,6 +384,11 @@ export interface ChatSnapshot { const EMPTY_LIST: readonly never[] = [] const EMPTY_TIMELINE: ConversationTimelineSnapshot = { turnOrder: EMPTY_LIST, turns: new Map() } +/** Empty target store used by fixtures and Sessions without registered views. */ +export const EMPTY_CONVERSATION_VIEWS: ConversationViewSnapshotStore = { + get: () => undefined, +} + /** Empty Chat target used before a view builder is registered. */ export const EMPTY_CHAT_SNAPSHOT: ChatSnapshot = { order: EMPTY_LIST, @@ -408,6 +413,8 @@ export const EMPTY_CHAT_SNAPSHOT: ChatSnapshot = { /** The immutable snapshot contract Session hands to uSES (see the web client architecture RFC). */ export interface ConversationSnapshot { sessionId: SessionId + /** Registered target snapshots assembled from Session events. */ + views: ConversationViewSnapshotStore /** Final Chat target assembled from independently registered business Definitions. */ chat: ChatSnapshot /** Legacy top-level compatibility field mirrored from the registered Chat Definitions. */ diff --git a/packages/client/runtime/src/client/sessions/session.ts b/packages/client/runtime/src/client/sessions/session.ts index 9c1d86987c..8e984d3edc 100644 --- a/packages/client/runtime/src/client/sessions/session.ts +++ b/packages/client/runtime/src/client/sessions/session.ts @@ -727,6 +727,7 @@ export class Session implements SessionFace { const legacy = chat.legacy return { sessionId: this.sessionId, + views: this.conversation, chat, nodes: legacy.nodes, turnTimings: legacy.turnTimings, diff --git a/packages/client/runtime/tests/client-apply.spec.ts b/packages/client/runtime/tests/client-apply.spec.ts index 7c8a40e06b..7c2bdf9bc6 100644 --- a/packages/client/runtime/tests/client-apply.spec.ts +++ b/packages/client/runtime/tests/client-apply.spec.ts @@ -126,6 +126,7 @@ describe('runtime client apply', () => { const rebuild = vi.spyOn(Session.prototype, 'rebuildConversationRegistry') const definition: ConversationNodeDefinition = { kind: 'registry-probe', + target: 'chat', match: () => null, start: () => null, update: context => context.state, diff --git a/packages/client/runtime/tests/conversation-assembler.spec.ts b/packages/client/runtime/tests/conversation-assembler.spec.ts index 06dfd42567..50380a20a3 100644 --- a/packages/client/runtime/tests/conversation-assembler.spec.ts +++ b/packages/client/runtime/tests/conversation-assembler.spec.ts @@ -30,10 +30,16 @@ interface TestSnapshot { } class TestEventDefinitions { + readonly definitions: readonly ConversationNodeDefinition[] + readonly fallback: ConversationNodeDefinition | undefined + constructor( - readonly definitions: readonly ConversationNodeDefinition[], - readonly fallback?: ConversationNodeDefinition, - ) {} + definitions: readonly ConversationNodeDefinition[], + fallback?: ConversationNodeDefinition, + ) { + this.definitions = definitions.map(asChatDefinition) + this.fallback = fallback === undefined ? undefined : asChatDefinition(fallback) + } entries(): readonly ConversationNodeDefinition[] { return this.definitions @@ -44,6 +50,12 @@ class TestEventDefinitions { } } +function asChatDefinition(definition: ConversationNodeDefinition): ConversationNodeDefinition { + return definition.buildViewNode === undefined || definition.target !== undefined + ? definition + : { ...definition, target: 'chat' } +} + class TestViewDefinitions { constructor(readonly definitions: readonly ConversationViewDefinition[]) {} @@ -93,7 +105,10 @@ function chatSnapshot(assembler: ConversationNodeAssembler): TestSnapshot | unde return assembler.snapshot('chat') as TestSnapshot | undefined } -function node(context: Parameters[0], data: unknown): ConversationViewNode { +function node( + context: Parameters>[0], + data: unknown, +): ConversationViewNode { return { key: context.key, kind: context.kind, diff --git a/packages/client/runtime/tests/conversation-registry.spec.ts b/packages/client/runtime/tests/conversation-registry.spec.ts index 9f45b36c6a..0beaf1d5c2 100644 --- a/packages/client/runtime/tests/conversation-registry.spec.ts +++ b/packages/client/runtime/tests/conversation-registry.spec.ts @@ -13,6 +13,7 @@ import { FakeApiClient, ok } from './fake-api.ts' function eventDefinition(kind: string): ConversationNodeDefinition { return { kind, + target: 'chat', match: () => null, start: () => null, update: context => context.state, diff --git a/packages/client/runtime/tests/session.spec.ts b/packages/client/runtime/tests/session.spec.ts index 36d9ce1b3d..0795d9a849 100644 --- a/packages/client/runtime/tests/session.spec.ts +++ b/packages/client/runtime/tests/session.spec.ts @@ -123,12 +123,13 @@ function testViewDefinition(): ConversationViewDefinition = { kind: 'runtime-test-event', + target: 'chat', match: event => ({ id: String(event.seq), role: 'start' }), start: (_context, match) => ({ event: match.event, view: match.view }), update: context => context.state, publication: match => match.event.type === 'assistant/chunk' ? 'animation-frame' : 'immediate', - buildViewNode: (context, target) => { - if (target !== 'chat' || context.state === undefined || context.start === undefined) return null + buildViewNode: (context) => { + if (context.state === undefined || context.start === undefined) return null return { key: context.key, kind: 'runtime-test-event', diff --git a/packages/client/test-runtime/src/fixtures.ts b/packages/client/test-runtime/src/fixtures.ts index 7f65a0b5a3..3a44b05048 100644 --- a/packages/client/test-runtime/src/fixtures.ts +++ b/packages/client/test-runtime/src/fixtures.ts @@ -2,7 +2,9 @@ import type { ConversationSnapshot, ISession, SessionId, SessionSummary, WorkspaceListState, } from '@deepseek-ai/dsh-client-runtime/client' -import { EMPTY_CHAT_SNAPSHOT } from '@deepseek-ai/dsh-client-runtime/client' +import { + EMPTY_CHAT_SNAPSHOT, EMPTY_CONVERSATION_VIEWS, +} from '@deepseek-ai/dsh-client-runtime/client' /** * Fixture overrides for the session behavior face: any subset of the @@ -46,6 +48,7 @@ export interface SessionFixture { export function conversationSnapshot(sessionId: SessionId): ConversationSnapshot { return { sessionId, + views: EMPTY_CONVERSATION_VIEWS, chat: EMPTY_CHAT_SNAPSHOT, nodes: [], turnTimings: new Map(), diff --git a/packages/client/ui-conversation/src/client/conversation-nodes/assistant.ts b/packages/client/ui-conversation/src/client/conversation-nodes/assistant.ts index 5baad5c37b..641a0287e4 100644 --- a/packages/client/ui-conversation/src/client/conversation-nodes/assistant.ts +++ b/packages/client/ui-conversation/src/client/conversation-nodes/assistant.ts @@ -242,6 +242,7 @@ function projectAssistant(context: ConversationNodeContext): Ass /** Per-step Assistant streaming/final/interruption Definition. */ export const assistantDefinition: ConversationNodeDefinition = { kind: 'assistant-step', + target: 'chat', match: (event) => { if (event.type === 'step/start') return { id: `${event.data.turn}:${event.data.step}`, role: 'start' } if (event.type === 'assistant/chunk' @@ -291,8 +292,7 @@ export const assistantDefinition: ConversationNodeDefinition = { value: projected.data, } }, - buildViewNode: (context, target) => { - if (target !== 'chat') return null + buildViewNode: (context) => { const projected = projectAssistant(context) if (projected === undefined) return null if (projected.settled === undefined && !projected.visible) { diff --git a/packages/client/ui-conversation/src/client/conversation-nodes/command.ts b/packages/client/ui-conversation/src/client/conversation-nodes/command.ts index 1517fbe718..692666fb66 100644 --- a/packages/client/ui-conversation/src/client/conversation-nodes/command.ts +++ b/packages/client/ui-conversation/src/client/conversation-nodes/command.ts @@ -175,6 +175,7 @@ export function updateCompactionState( /** Slash-command lifecycle, including integrated manual compaction, Definition. */ export const commandDefinition: ConversationNodeDefinition = { kind: 'command', + target: 'chat', match: (event) => { if (event.type === 'command/run') { return { id: String(event.data.commandId), role: 'start' } @@ -202,8 +203,7 @@ export const commandDefinition: ConversationNodeDefinition = { } return updateCompactionState(context.state, match) }, - buildViewNode: (context, target) => { - if (target !== 'chat') return null + buildViewNode: (context) => { const state = context.state ?? fallbackState(context) if (state === undefined) return null if (state.command.name !== 'compact') { diff --git a/packages/client/ui-conversation/src/client/conversation-nodes/compaction.ts b/packages/client/ui-conversation/src/client/conversation-nodes/compaction.ts index 2852019c3f..18f3205df7 100644 --- a/packages/client/ui-conversation/src/client/conversation-nodes/compaction.ts +++ b/packages/client/ui-conversation/src/client/conversation-nodes/compaction.ts @@ -30,6 +30,7 @@ function fallbackState(context: ConversationNodeContext): Compa /** Automatic compaction lifecycle and landed checkpoint Definition. */ export const compactionDefinition: ConversationNodeDefinition = { kind: 'compaction', + target: 'chat', match: (event) => { const checkpoint = compactSource(event) if (checkpoint !== undefined && checkpoint.sourceCommandId === undefined) { @@ -47,8 +48,7 @@ export const compactionDefinition: ConversationNodeDefinition = }, start: () => ({}), update: (context, match) => updateCompactionState(context.state, match), - buildViewNode: (context, target) => { - if (target !== 'chat') return null + buildViewNode: (context) => { const state = context.state ?? fallbackState(context) if (state.checkpoint === undefined) return null const marker = compactSummary(state.summary, state.checkpoint) diff --git a/packages/client/ui-conversation/src/client/conversation-nodes/fallback.ts b/packages/client/ui-conversation/src/client/conversation-nodes/fallback.ts index 6309c35b94..79bc97e636 100644 --- a/packages/client/ui-conversation/src/client/conversation-nodes/fallback.ts +++ b/packages/client/ui-conversation/src/client/conversation-nodes/fallback.ts @@ -15,6 +15,7 @@ declare module '@deepseek-ai/dsh-client-ui-conversation/client' { /** Unclaimed append-surface fallback Definition. */ export const unknownFallbackDefinition: ConversationNodeDefinition = { kind: 'unknown-surface', + target: 'chat', match: event => isAppendSurfaceEvent(event) ? { id: String(event.seq), role: 'start' } : null, @@ -26,7 +27,7 @@ export const unknownFallbackDefinition: ConversationNodeDefinition context.state, - buildViewNode: (context, target) => target !== 'chat' || context.state === undefined + buildViewNode: context => context.state === undefined ? null : chatNode(context, 'unknown', context.state.seq, context.state), } diff --git a/packages/client/ui-conversation/src/client/conversation-nodes/inbox.ts b/packages/client/ui-conversation/src/client/conversation-nodes/inbox.ts index 92e611f77c..4d8fb6d3e2 100644 --- a/packages/client/ui-conversation/src/client/conversation-nodes/inbox.ts +++ b/packages/client/ui-conversation/src/client/conversation-nodes/inbox.ts @@ -50,7 +50,6 @@ function inboxDefinition(target: InboxTarget): ConversationNodeDefinition context.state, publication: () => 'none', - buildViewNode: () => null, } } diff --git a/packages/client/ui-conversation/src/client/conversation-nodes/message.ts b/packages/client/ui-conversation/src/client/conversation-nodes/message.ts index d57a6d9d96..085127f9c5 100644 --- a/packages/client/ui-conversation/src/client/conversation-nodes/message.ts +++ b/packages/client/ui-conversation/src/client/conversation-nodes/message.ts @@ -30,6 +30,7 @@ function isCompactionCheckpoint(event: Parameters = { kind: 'input-message', + target: 'chat', match: event => event.type === 'user/message' && isAppendSurfaceEvent(event) && !isCompactionCheckpoint(event) @@ -68,8 +69,8 @@ export const messageDefinition: ConversationNodeDefinition = { } }, update: context => context.state, - buildViewNode: (context, target) => { - if (target !== 'chat' || context.state === undefined) return null + buildViewNode: (context) => { + if (context.state === undefined) return null return chatNode(context, context.state.kind, context.state.seq, context.state) }, } diff --git a/packages/client/ui-conversation/src/client/conversation-nodes/retry.ts b/packages/client/ui-conversation/src/client/conversation-nodes/retry.ts index 31b80075a8..4a0f9f9fed 100644 --- a/packages/client/ui-conversation/src/client/conversation-nodes/retry.ts +++ b/packages/client/ui-conversation/src/client/conversation-nodes/retry.ts @@ -40,6 +40,7 @@ function isClosed(location: ConversationLocation): boolean { /** Producer-correlated model retry chain Definition. */ export const retryDefinition: ConversationNodeDefinition = { kind: 'model-retry', + target: 'chat', match: (event) => { if (event.type === 'llm/retry') { const retryId: unknown = event.data.retryId @@ -70,8 +71,8 @@ export const retryDefinition: ConversationNodeDefinition = { attempt.retry === retry ? { ...attempt, retryState: 'started' } : attempt), } }, - buildViewNode: (context, target) => { - if (target !== 'chat' || context.state === undefined || context.state.attempts.length === 0) return null + buildViewNode: (context) => { + if (context.state === undefined || context.state.attempts.length === 0) return null const location = context.start?.location ?? context.matches[0]?.location ?? { kind: 'unresolved' as const } const stateAttempts = context.state.attempts const attempts = stateAttempts.map((attempt, index) => diff --git a/packages/client/ui-conversation/src/client/conversation-nodes/tool.ts b/packages/client/ui-conversation/src/client/conversation-nodes/tool.ts index 46c838e980..0d6fb57cf3 100644 --- a/packages/client/ui-conversation/src/client/conversation-nodes/tool.ts +++ b/packages/client/ui-conversation/src/client/conversation-nodes/tool.ts @@ -235,6 +235,7 @@ function fallbackState(context: ConversationNodeContext): ToolState | /** Root Tool lifecycle and nested Code Dispatch Definition. */ export const toolDefinition: ConversationNodeDefinition = { kind: 'tool-call', + target: 'chat', match: (event) => { if (event.type === 'tool/call') return { id: String(event.data.callId), role: 'start' } if (event.type === 'tool/result' && isAppendSurfaceEvent(event)) { @@ -257,8 +258,7 @@ export const toolDefinition: ConversationNodeDefinition = { } return updateDispatch(context.state, match) }, - buildViewNode: (context, target) => { - if (target !== 'chat') return null + buildViewNode: (context) => { const state = context.state ?? fallbackState(context) if (state === undefined) return null const projected = projectBlock(state.root, state, interruption(context)) diff --git a/packages/client/ui-conversation/src/client/conversation-nodes/turn-error.ts b/packages/client/ui-conversation/src/client/conversation-nodes/turn-error.ts index 1f5a87add8..6242276d12 100644 --- a/packages/client/ui-conversation/src/client/conversation-nodes/turn-error.ts +++ b/packages/client/ui-conversation/src/client/conversation-nodes/turn-error.ts @@ -63,6 +63,7 @@ function fallbackState(context: ConversationNodeContext): TurnEr /** Terminal turn failure Definition, suppressed when the turn owns a retry chain. */ export const turnErrorDefinition: ConversationNodeDefinition = { kind: 'turn-error', + target: 'chat', match: (event) => { if (event.type === 'turn/start') return { id: String(event.data.turn), role: 'start' } if (event.type === 'turn/end' && event.data.reason.kind === 'error') { @@ -82,8 +83,7 @@ export const turnErrorDefinition: ConversationNodeDefinition = { ? { ...context.state, hidden: true } : context.state }, - buildViewNode: (context, target) => { - if (target !== 'chat') return null + buildViewNode: (context) => { const state = context.state ?? fallbackState(context) if (state?.failure === undefined) return null const failure = state.failure diff --git a/packages/client/ui-conversation/src/client/conversation-nodes/turn-tail.ts b/packages/client/ui-conversation/src/client/conversation-nodes/turn-tail.ts index 01bee27f3f..94fb72a383 100644 --- a/packages/client/ui-conversation/src/client/conversation-nodes/turn-tail.ts +++ b/packages/client/ui-conversation/src/client/conversation-nodes/turn-tail.ts @@ -151,6 +151,7 @@ function tailData(context: ConversationNodeContext): TurnTailChat /** Completed-turn footer Definition independent of any Assistant row. */ export const turnTailDefinition: ConversationNodeDefinition = { kind: 'turn-tail', + target: 'chat', match: (event) => { if (event.type === 'turn/start') return { id: String(event.data.turn), role: 'start' } if (event.type === 'turn/end') return { id: String(event.data.turn), role: 'update' } @@ -179,8 +180,7 @@ export const turnTailDefinition: ConversationNodeDefinition = { value, } }, - buildViewNode: (context, target) => { - if (target !== 'chat') return null + buildViewNode: (context) => { const turn = turnLocation(context) const data = turn?.data.get('turn-tail') return data === undefined ? null : chatNode(context, 'turn-tail', closingAnchor(context), data) diff --git a/packages/client/ui-conversation/tests/chat-stats.spec.tsx b/packages/client/ui-conversation/tests/chat-stats.spec.tsx index 959a91c3ac..0b2d648661 100644 --- a/packages/client/ui-conversation/tests/chat-stats.spec.tsx +++ b/packages/client/ui-conversation/tests/chat-stats.spec.tsx @@ -7,6 +7,7 @@ import { act, cleanup, fireEvent, render } from '@testing-library/react' import type { AssistantMessageNode, ConversationSnapshot, SessionId, ToolResultNode, } from '@deepseek-ai/dsh-client-runtime/client' +import { EMPTY_CONVERSATION_VIEWS } from '@deepseek-ai/dsh-client-runtime/client' import { bindSnapshotSelector } from '@deepseek-ai/dsh-client-web-react' import { makeTranslate } from '@deepseek-ai/dsh-client-test-runtime' import { en as commonEn } from '@deepseek-ai/dsh-client-locale/src/locales/en.ts' @@ -43,7 +44,7 @@ const assistant = (seq: number, turn: number, usage?: unknown): AssistantMessage function snapshotBase(): ConversationSnapshot { return { - sessionId: SID, chat: chatSnapshotFixture(), + sessionId: SID, views: EMPTY_CONVERSATION_VIEWS, chat: chatSnapshotFixture(), nodes: [], turnTimings: new Map(), turnEnds: new Map(), partial: null, runningCalls: [], pending: [], queue: [], running: false, composerPhase: 'active', removed: false, openState: 'open', openError: null, hasMore: false, loadingOlder: false, promptError: null, blank: false, subagent: null, lastAgentError: null, diff --git a/packages/client/ui-conversation/tests/chat-view.spec.tsx b/packages/client/ui-conversation/tests/chat-view.spec.tsx index d6b4996567..fd306eb132 100644 --- a/packages/client/ui-conversation/tests/chat-view.spec.tsx +++ b/packages/client/ui-conversation/tests/chat-view.spec.tsx @@ -12,7 +12,9 @@ import type { UserMessageNode, WorkspaceListState, } from '@deepseek-ai/dsh-client-runtime/client' import { bindSnapshotSelector } from '@deepseek-ai/dsh-client-web-react' -import { createSnapshotStore, PendingWait } from '@deepseek-ai/dsh-client-runtime/client' +import { + createSnapshotStore, EMPTY_CONVERSATION_VIEWS, PendingWait, +} from '@deepseek-ai/dsh-client-runtime/client' import { RpcId } from '@deepseek-ai/dsh-client-connection/client' import type { ChatNode, ChatNodeOwnerProps, ChatNodeViewProps, ChatViewSlotProps, SelectionTarget, UseChatNodeTurnData, @@ -47,7 +49,7 @@ type RoutedChatNodeOwner = ChatNodeOwnerProps & { readonly node: ChatNode } function snapshotBase(): ConversationSnapshot { return { - sessionId: SID, chat: chatSnapshotFixture(), nodes: [], turnTimings: new Map(), turnEnds: new Map(), partial: null, runningCalls: [], + sessionId: SID, views: EMPTY_CONVERSATION_VIEWS, chat: chatSnapshotFixture(), nodes: [], turnTimings: new Map(), turnEnds: new Map(), partial: null, runningCalls: [], pending: [], queue: [], running: false, composerPhase: 'active', removed: false, openState: 'open', openError: null, hasMore: false, loadingOlder: false, promptError: null, blank: false, subagent: null, lastAgentError: null, } diff --git a/packages/client/ui-conversation/tests/gate-branch-tails.spec.tsx b/packages/client/ui-conversation/tests/gate-branch-tails.spec.tsx index 3acdc44a2a..6e0df4dd8c 100644 --- a/packages/client/ui-conversation/tests/gate-branch-tails.spec.tsx +++ b/packages/client/ui-conversation/tests/gate-branch-tails.spec.tsx @@ -3,7 +3,9 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import { cleanup, render } from '@testing-library/react' import { bindSnapshotSelector } from '@deepseek-ai/dsh-client-web-react' -import { createSnapshotStore, EMPTY_CHAT_SNAPSHOT } from '@deepseek-ai/dsh-client-runtime/client' +import { + createSnapshotStore, EMPTY_CHAT_SNAPSHOT, EMPTY_CONVERSATION_VIEWS, +} from '@deepseek-ai/dsh-client-runtime/client' import type { UseSession } from '@deepseek-ai/dsh-client-web-react' import type { ConversationSnapshot, SessionId, SessionListState, WorkspaceListState } from '@deepseek-ai/dsh-client-runtime/client' import type { SessionProviderComponent } from '@deepseek-ai/dsh-client-ui-slots' @@ -48,7 +50,7 @@ function renderToolDetailsProbe(owners?: DetailsToolOwnerProps[]): DetailsSlotPr function snapshotBase(): ConversationSnapshot { return { - sessionId: SID, chat: EMPTY_CHAT_SNAPSHOT, + sessionId: SID, views: EMPTY_CONVERSATION_VIEWS, chat: EMPTY_CHAT_SNAPSHOT, nodes: [], turnTimings: new Map(), turnEnds: new Map(), partial: null, runningCalls: [], pending: [], queue: [], running: false, composerPhase: 'active', removed: false, openState: 'open', openError: null, hasMore: false, loadingOlder: false, promptError: null, blank: false, subagent: null, lastAgentError: null, diff --git a/packages/client/ui-conversation/tests/input-bar.spec.tsx b/packages/client/ui-conversation/tests/input-bar.spec.tsx index 59c0f9eefa..b9aa56f7c8 100644 --- a/packages/client/ui-conversation/tests/input-bar.spec.tsx +++ b/packages/client/ui-conversation/tests/input-bar.spec.tsx @@ -7,7 +7,9 @@ import { afterEach, describe, expect, it, onTestFinished, vi } from 'vitest' import { act, cleanup, fireEvent, render } from '@testing-library/react' import { bindSnapshotSelector } from '@deepseek-ai/dsh-client-web-react' -import { createSnapshotStore, EMPTY_CHAT_SNAPSHOT } from '@deepseek-ai/dsh-client-runtime/client' +import { + createSnapshotStore, EMPTY_CHAT_SNAPSHOT, EMPTY_CONVERSATION_VIEWS, +} from '@deepseek-ai/dsh-client-runtime/client' import { makeTranslate } from '@deepseek-ai/dsh-client-test-runtime' import { zh as commonZh } from '@deepseek-ai/dsh-client-locale/src/locales/zh.ts' import type { ClientContext, ConversationSnapshot, SessionId } from '@deepseek-ai/dsh-client-runtime/client' @@ -37,7 +39,7 @@ const SID = 's1' as SessionId function snapshotOf(overrides: Partial = {}): ConversationSnapshot { return { - sessionId: SID, chat: EMPTY_CHAT_SNAPSHOT, + sessionId: SID, views: EMPTY_CONVERSATION_VIEWS, chat: EMPTY_CHAT_SNAPSHOT, nodes: [], turnTimings: new Map(), turnEnds: new Map(), partial: null, runningCalls: [], pending: [], queue: [], running: false, composerPhase: 'active', removed: false, openState: 'open', openError: null, hasMore: false, loadingOlder: false, diff --git a/packages/client/ui-conversation/tests/input-matrix.spec.tsx b/packages/client/ui-conversation/tests/input-matrix.spec.tsx index 09cfe4ca66..bb6ba10990 100644 --- a/packages/client/ui-conversation/tests/input-matrix.spec.tsx +++ b/packages/client/ui-conversation/tests/input-matrix.spec.tsx @@ -8,7 +8,9 @@ import { afterEach, describe, expect, it, vi } from 'vitest' import { act, cleanup, fireEvent, render } from '@testing-library/react' import { bindSnapshotSelector } from '@deepseek-ai/dsh-client-web-react' -import { createSnapshotStore, EMPTY_CHAT_SNAPSHOT } from '@deepseek-ai/dsh-client-runtime/client' +import { + createSnapshotStore, EMPTY_CHAT_SNAPSHOT, EMPTY_CONVERSATION_VIEWS, +} from '@deepseek-ai/dsh-client-runtime/client' import type { ClientContext, ConversationSnapshot, SessionId } from '@deepseek-ai/dsh-client-runtime/client' import type { SubmitOutcome } from '@deepseek-ai/dsh-client-ui-slash/client' import { makeTranslate } from '@deepseek-ai/dsh-client-test-runtime' @@ -26,7 +28,7 @@ const SID = 's1' as SessionId /** Standard-props InputBar mount over a real shell (the composer-bar entry shape). */ function mountBar(shell: SessionInputShell, over?: { running?: boolean; disabled?: boolean }) { const session = createSnapshotStore({ - sessionId: SID, chat: EMPTY_CHAT_SNAPSHOT, + sessionId: SID, views: EMPTY_CONVERSATION_VIEWS, chat: EMPTY_CHAT_SNAPSHOT, nodes: [], turnTimings: new Map(), turnEnds: new Map(), partial: null, runningCalls: [], pending: [], queue: [], running: over?.running ?? false, composerPhase: 'active', removed: over?.disabled ?? false, openState: 'open', openError: null, hasMore: false, diff --git a/packages/client/ui-conversation/tests/input-scenarios.spec.tsx b/packages/client/ui-conversation/tests/input-scenarios.spec.tsx index 416d2fe620..0722ccb2e1 100644 --- a/packages/client/ui-conversation/tests/input-scenarios.spec.tsx +++ b/packages/client/ui-conversation/tests/input-scenarios.spec.tsx @@ -11,7 +11,9 @@ import { Context } from '@deepseek-ai/cordis' import { afterEach, describe, expect, it, vi } from 'vitest' import { act, cleanup, fireEvent, render } from '@testing-library/react' -import { EMPTY_CHAT_SNAPSHOT, SessionsService } from '@deepseek-ai/dsh-client-runtime/client' +import { + EMPTY_CHAT_SNAPSHOT, EMPTY_CONVERSATION_VIEWS, SessionsService, +} from '@deepseek-ai/dsh-client-runtime/client' import { SlashService } from '@deepseek-ai/dsh-client-ui-slash/client' import type { ClientSessionContext, CommandClaim, PickOutcome, SubmitOutcome } from '@deepseek-ai/dsh-client-ui-slash/client' import { FakeApiClient, ok } from '../../runtime/tests/fake-api.ts' @@ -112,7 +114,7 @@ async function scopedBench(register?: (slash: SlashService) => void) { actx.on('slash/input-consume-token', req => shell.consumeToken(req.guard) ? true : undefined) const wiring = shell const sessionStore = createSnapshotStore({ - sessionId, chat: EMPTY_CHAT_SNAPSHOT, + sessionId, views: EMPTY_CONVERSATION_VIEWS, chat: EMPTY_CHAT_SNAPSHOT, nodes: [], turnTimings: new Map(), turnEnds: new Map(), partial: null, runningCalls: [], pending: [], queue: [], running: false, composerPhase: 'active', removed: false, openState: 'open', openError: null, hasMore: false, loadingOlder: false, diff --git a/packages/client/ui-conversation/tests/queue-dock.spec.tsx b/packages/client/ui-conversation/tests/queue-dock.spec.tsx index 68170b604f..4367a74dad 100644 --- a/packages/client/ui-conversation/tests/queue-dock.spec.tsx +++ b/packages/client/ui-conversation/tests/queue-dock.spec.tsx @@ -6,7 +6,9 @@ import { afterEach, describe, expect, it, vi } from 'vitest' import { act, cleanup, fireEvent, render, waitFor } from '@testing-library/react' import { useSyncExternalStore } from 'react' -import { EMPTY_CHAT_SNAPSHOT } from '@deepseek-ai/dsh-client-runtime/client' +import { + EMPTY_CHAT_SNAPSHOT, EMPTY_CONVERSATION_VIEWS, +} from '@deepseek-ai/dsh-client-runtime/client' import type { ConversationSnapshot, QueuedMessage, SessionId, SessionListState, } from '@deepseek-ai/dsh-client-runtime/client' @@ -33,7 +35,7 @@ function row(id: string, text: string | null, preview = text ?? '[image]'): Queu function snapshotWith(queue: QueuedMessage[]): ConversationSnapshot { return { - sessionId: SID, chat: EMPTY_CHAT_SNAPSHOT, + sessionId: SID, views: EMPTY_CONVERSATION_VIEWS, chat: EMPTY_CHAT_SNAPSHOT, nodes: [], turnTimings: new Map(), turnEnds: new Map(), partial: null, runningCalls: [], pending: [], queue, running: true, composerPhase: 'active', removed: false, openState: 'open', openError: null, hasMore: false, loadingOlder: false, promptError: null, blank: false, subagent: null, lastAgentError: null, diff --git a/packages/client/ui-conversation/tests/skeleton.spec.tsx b/packages/client/ui-conversation/tests/skeleton.spec.tsx index 7d7596a49e..4651a27bea 100644 --- a/packages/client/ui-conversation/tests/skeleton.spec.tsx +++ b/packages/client/ui-conversation/tests/skeleton.spec.tsx @@ -5,7 +5,9 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import { act, cleanup, fireEvent, render } from '@testing-library/react' import { bindSnapshotSelector } from '@deepseek-ai/dsh-client-web-react' -import { createSnapshotStore, EMPTY_CHAT_SNAPSHOT } from '@deepseek-ai/dsh-client-runtime/client' +import { + createSnapshotStore, EMPTY_CHAT_SNAPSHOT, EMPTY_CONVERSATION_VIEWS, +} from '@deepseek-ai/dsh-client-runtime/client' import type { ConversationSnapshot, SessionId, SessionListState, WorkspaceId, WorkspaceListState, WorkspaceView, } from '@deepseek-ai/dsh-client-runtime/client' @@ -70,7 +72,7 @@ const workspaceState = (items: readonly WorkspaceView[]): WorkspaceListState => function conversationSnapshot(overrides: Partial = {}): ConversationSnapshot { return { - sessionId: SID, chat: EMPTY_CHAT_SNAPSHOT, + sessionId: SID, views: EMPTY_CONVERSATION_VIEWS, chat: EMPTY_CHAT_SNAPSHOT, nodes: [], turnTimings: new Map(), turnEnds: new Map(), partial: null, runningCalls: [], pending: [], queue: [], running: false, composerPhase: 'active', removed: false, openState: 'open', openError: null, hasMore: false, loadingOlder: false, diff --git a/packages/client/ui-deliverables/src/client/turn-deliverables.ts b/packages/client/ui-deliverables/src/client/turn-deliverables.ts index 9151f88869..0061400e7a 100644 --- a/packages/client/ui-deliverables/src/client/turn-deliverables.ts +++ b/packages/client/ui-deliverables/src/client/turn-deliverables.ts @@ -97,6 +97,7 @@ export function selectProducedFiles(owner: TurnTailOwnerProps): readonly string[ /** Turn-local successful mutation accumulator; it publishes no view Node. */ export const deliverablesDefinition: ConversationNodeDefinition = { kind: 'deliverables', + target: 'chat', match: (event) => { if (event.type === 'turn/start') return { id: String(event.data.turn), role: 'start' } if (event.type === 'tool/call') return { id: String(event.data.turn), role: 'update' } diff --git a/packages/client/ui-deliverables/tests/produced-files.spec.tsx b/packages/client/ui-deliverables/tests/produced-files.spec.tsx index f38faf8dd5..48303f2e54 100644 --- a/packages/client/ui-deliverables/tests/produced-files.spec.tsx +++ b/packages/client/ui-deliverables/tests/produced-files.spec.tsx @@ -73,7 +73,7 @@ interface TimelineSnapshot { class TestEventDefinitions { entries(): readonly ConversationNodeDefinition[] { return [deliverablesDefinition] } - fallbackEntry(): undefined { return undefined } + fallbackEntries(): readonly ConversationNodeDefinition[] { return [] } } class TestViewDefinitions { diff --git a/packages/client/ui-tool/tests/chat-code-subcalls.spec.tsx b/packages/client/ui-tool/tests/chat-code-subcalls.spec.tsx index 1a7dd2d892..8840e6a19d 100644 --- a/packages/client/ui-tool/tests/chat-code-subcalls.spec.tsx +++ b/packages/client/ui-tool/tests/chat-code-subcalls.spec.tsx @@ -12,7 +12,8 @@ import { Context } from '@deepseek-ai/cordis' import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import { cleanup, fireEvent, render } from '@testing-library/react' import { - ConversationEventRegistry, ConversationViewRegistry, createSnapshotStore, SlotsService, + ConversationEventRegistry, ConversationViewRegistry, createSnapshotStore, + EMPTY_CONVERSATION_VIEWS, SlotsService, } from '@deepseek-ai/dsh-client-runtime/client' import type { ConversationSnapshot, RunningToolCall, SessionId, SessionListState, @@ -78,7 +79,8 @@ function snapshotWith( const nestedNodes = nodes.map(node => ({ ...node, subCalls })) const nestedRunningCalls = runningCalls.map(call => ({ ...call, subCalls })) return { - sessionId: SID, chat: toolChatSnapshot(nestedNodes, nestedRunningCalls), + sessionId: SID, views: EMPTY_CONVERSATION_VIEWS, + chat: toolChatSnapshot(nestedNodes, nestedRunningCalls), nodes: nestedNodes, turnTimings: new Map(), turnEnds: new Map(), partial: null, runningCalls: nestedRunningCalls, pending: [], queue: [], running: runningCalls.length > 0, composerPhase: 'active', removed: false, diff --git a/packages/client/ui-tool/tests/diff-card.spec.tsx b/packages/client/ui-tool/tests/diff-card.spec.tsx index 600949f5e8..3990cba157 100644 --- a/packages/client/ui-tool/tests/diff-card.spec.tsx +++ b/packages/client/ui-tool/tests/diff-card.spec.tsx @@ -7,7 +7,9 @@ import { afterEach, describe, expect, it, vi } from 'vitest' import { cleanup, fireEvent, render } from '@testing-library/react' import { bindSnapshotSelector } from '@deepseek-ai/dsh-client-web-react' -import { createSnapshotStore } from '@deepseek-ai/dsh-client-runtime/client' +import { + createSnapshotStore, EMPTY_CONVERSATION_VIEWS, +} from '@deepseek-ai/dsh-client-runtime/client' import type { ConversationSnapshot, RunningToolCall, SessionId, SessionListState, ToolResultNode, WorkspaceListState, } from '@deepseek-ai/dsh-client-runtime/client' @@ -351,7 +353,8 @@ describe('DetailsPanel diff Output section', () => { const nodes = over.nodes ?? [] const runningCalls = over.runningCalls ?? [] return { - sessionId: SID, chat: over.chat ?? toolChatSnapshot(nodes, runningCalls), + sessionId: SID, views: EMPTY_CONVERSATION_VIEWS, + chat: over.chat ?? toolChatSnapshot(nodes, runningCalls), nodes: [], turnTimings: new Map(), turnEnds: new Map(), partial: null, runningCalls: [], pending: [], queue: [], running: false, composerPhase: 'active', removed: false, openState: 'open', openError: null, hasMore: false, loadingOlder: false, diff --git a/packages/client/ui-tool/tests/read-card.spec.tsx b/packages/client/ui-tool/tests/read-card.spec.tsx index ef00460103..14baac6b9b 100644 --- a/packages/client/ui-tool/tests/read-card.spec.tsx +++ b/packages/client/ui-tool/tests/read-card.spec.tsx @@ -10,7 +10,9 @@ import { afterEach, describe, expect, it, vi } from 'vitest' import { cleanup, fireEvent, render } from '@testing-library/react' import { Context } from '@deepseek-ai/cordis' import { bindSnapshotSelector } from '@deepseek-ai/dsh-client-web-react' -import { createSnapshotStore } from '@deepseek-ai/dsh-client-runtime/client' +import { + createSnapshotStore, EMPTY_CONVERSATION_VIEWS, +} from '@deepseek-ai/dsh-client-runtime/client' import { makeTranslate } from '@deepseek-ai/dsh-client-test-runtime' import { zh as commonZh } from '@deepseek-ai/dsh-client-locale/src/locales/zh.ts' import type { @@ -297,7 +299,8 @@ describe('DetailsPanel Output section (read)', () => { const nodes = over.nodes ?? [] const runningCalls = over.runningCalls ?? [] return { - sessionId: SID, chat: over.chat ?? toolChatSnapshot(nodes, runningCalls), + sessionId: SID, views: EMPTY_CONVERSATION_VIEWS, + chat: over.chat ?? toolChatSnapshot(nodes, runningCalls), nodes: [], turnTimings: new Map(), turnEnds: new Map(), partial: null, runningCalls: [], pending: [], queue: [], running: false, composerPhase: 'active', removed: false, openState: 'open', openError: null, hasMore: false, loadingOlder: false, diff --git a/packages/client/ui-tool/tests/search-card.spec.tsx b/packages/client/ui-tool/tests/search-card.spec.tsx index b41b665ea8..67d5eea6ca 100644 --- a/packages/client/ui-tool/tests/search-card.spec.tsx +++ b/packages/client/ui-tool/tests/search-card.spec.tsx @@ -9,7 +9,9 @@ import { afterEach, describe, expect, it, vi } from 'vitest' import { cleanup, fireEvent, render } from '@testing-library/react' import { bindSnapshotSelector } from '@deepseek-ai/dsh-client-web-react' -import { createSnapshotStore } from '@deepseek-ai/dsh-client-runtime/client' +import { + createSnapshotStore, EMPTY_CONVERSATION_VIEWS, +} from '@deepseek-ai/dsh-client-runtime/client' import type { ConversationSnapshot, RunningToolCall, SessionId, SessionListState, ToolResultNode, WorkspaceListState, } from '@deepseek-ai/dsh-client-runtime/client' @@ -413,7 +415,8 @@ describe('DetailsPanel Output section (search)', () => { const nodes = over.nodes ?? [] const runningCalls = over.runningCalls ?? [] return { - sessionId: SID, chat: over.chat ?? toolChatSnapshot(nodes, runningCalls), + sessionId: SID, views: EMPTY_CONVERSATION_VIEWS, + chat: over.chat ?? toolChatSnapshot(nodes, runningCalls), nodes: [], turnTimings: new Map(), turnEnds: new Map(), partial: null, runningCalls: [], pending: [], queue: [], running: false, composerPhase: 'active', removed: false, openState: 'open', openError: null, hasMore: false, loadingOlder: false, diff --git a/packages/client/ui-tool/tests/terminal-card.spec.tsx b/packages/client/ui-tool/tests/terminal-card.spec.tsx index a868ffa744..c0af5adff7 100644 --- a/packages/client/ui-tool/tests/terminal-card.spec.tsx +++ b/packages/client/ui-tool/tests/terminal-card.spec.tsx @@ -7,7 +7,9 @@ import { afterEach, describe, expect, it, vi } from 'vitest' import { cleanup, fireEvent, render } from '@testing-library/react' import { bindSnapshotSelector } from '@deepseek-ai/dsh-client-web-react' -import { createSnapshotStore } from '@deepseek-ai/dsh-client-runtime/client' +import { + createSnapshotStore, EMPTY_CONVERSATION_VIEWS, +} from '@deepseek-ai/dsh-client-runtime/client' import type { ConversationSnapshot, RunningToolCall, SessionId, SessionListState, ToolResultNode, WorkspaceListState, } from '@deepseek-ai/dsh-client-runtime/client' @@ -482,7 +484,8 @@ describe('DetailsPanel Output section', () => { const nodes = over.nodes ?? [] const runningCalls = over.runningCalls ?? [] return { - sessionId: SID, chat: over.chat ?? toolChatSnapshot(nodes, runningCalls), + sessionId: SID, views: EMPTY_CONVERSATION_VIEWS, + chat: over.chat ?? toolChatSnapshot(nodes, runningCalls), nodes: [], turnTimings: new Map(), turnEnds: new Map(), partial: null, runningCalls: [], pending: [], queue: [], running: false, composerPhase: 'active', removed: false, openState: 'open', openError: null, hasMore: false, loadingOlder: false, diff --git a/packages/client/ui-tool/tests/web-card.spec.tsx b/packages/client/ui-tool/tests/web-card.spec.tsx index 44f63147a0..67ec839471 100644 --- a/packages/client/ui-tool/tests/web-card.spec.tsx +++ b/packages/client/ui-tool/tests/web-card.spec.tsx @@ -10,7 +10,9 @@ import { afterEach, describe, expect, it, vi } from 'vitest' import { cleanup, fireEvent, render } from '@testing-library/react' -import { createSnapshotStore } from '@deepseek-ai/dsh-client-runtime/client' +import { + createSnapshotStore, EMPTY_CONVERSATION_VIEWS, +} from '@deepseek-ai/dsh-client-runtime/client' import type { ConversationSnapshot, RunningToolCall, SessionId, SessionListState, ToolResultNode, WorkspaceListState, } from '@deepseek-ai/dsh-client-runtime/client' @@ -243,7 +245,8 @@ describe('DetailsPanel web Output section', () => { const nodes = over.nodes ?? [] const runningCalls = over.runningCalls ?? [] return { - sessionId: SID, chat: over.chat ?? toolChatSnapshot(nodes, runningCalls), + sessionId: SID, views: EMPTY_CONVERSATION_VIEWS, + chat: over.chat ?? toolChatSnapshot(nodes, runningCalls), nodes: [], turnTimings: new Map(), turnEnds: new Map(), partial: null, runningCalls: [], pending: [], queue: [], running: false, composerPhase: 'active', removed: false, openState: 'open', openError: null, hasMore: false, loadingOlder: false, From f479c60b6dabb0c8061ef7ac8dbeb34ba67cc37a Mon Sep 17 00:00:00 2001 From: imccyu <276526105+imccyu@users.noreply.github.com> Date: Mon, 10 Aug 2026 18:38:22 +0800 Subject: [PATCH 21/36] feat(ui-trajectory): assemble registered conversation nodes --- .../src/client/TrajectoryView.tsx | 40 +- .../client/ui-trajectory/src/client/index.ts | 30 +- .../client/trajectory-assistant-definition.ts | 397 ++++++++++++++++++ .../trajectory-compaction-definition.ts | 139 ++++++ .../src/client/trajectory-contract.ts | 75 ++++ .../client/trajectory-definition-common.ts | 29 ++ .../client/trajectory-message-definitions.ts | 114 +++++ .../trajectory-request-header-definition.ts | 76 ++++ .../src/client/trajectory-snapshot-builder.ts | 222 ++++++++++ .../src/client/trajectory-tool-definition.ts | 250 +++++++++++ .../ui-trajectory/tests/client-bundle.spec.ts | 16 +- .../client/ui-trajectory/tests/views.spec.tsx | 141 ++++--- 12 files changed, 1425 insertions(+), 104 deletions(-) create mode 100644 packages/client/ui-trajectory/src/client/trajectory-assistant-definition.ts create mode 100644 packages/client/ui-trajectory/src/client/trajectory-compaction-definition.ts create mode 100644 packages/client/ui-trajectory/src/client/trajectory-contract.ts create mode 100644 packages/client/ui-trajectory/src/client/trajectory-definition-common.ts create mode 100644 packages/client/ui-trajectory/src/client/trajectory-message-definitions.ts create mode 100644 packages/client/ui-trajectory/src/client/trajectory-request-header-definition.ts create mode 100644 packages/client/ui-trajectory/src/client/trajectory-snapshot-builder.ts create mode 100644 packages/client/ui-trajectory/src/client/trajectory-tool-definition.ts diff --git a/packages/client/ui-trajectory/src/client/TrajectoryView.tsx b/packages/client/ui-trajectory/src/client/TrajectoryView.tsx index 6d77f907f1..95476ac851 100644 --- a/packages/client/ui-trajectory/src/client/TrajectoryView.tsx +++ b/packages/client/ui-trajectory/src/client/TrajectoryView.tsx @@ -1,11 +1,11 @@ /** Trajectory view: compact summary over a turn-aware event ledger. */ -import { useCallback, useEffect, useMemo, useRef, useState } from 'react' +import { useCallback, useMemo, useState } from 'react' import type { ConvViewProps } from '@deepseek-ai/dsh-client-ui-conversation/client' import type { InjectFace } from '@deepseek-ai/dsh-client-ui-slots' import type { AssistantBlock, AssistantMessageNode, ConversationContext, ConversationSnapshot, - SessionHistoryFace, SnapshotStore, + SnapshotStore, } from '@deepseek-ai/dsh-client-runtime/client' import { deriveTrajectoryContextBranches, trajectoryBranchContainsRequest, @@ -27,6 +27,7 @@ import { type TrajectoryTimeRange, } from './timeline.ts' import { trajectoryRecordId } from './trajectory-record.ts' +import { EMPTY_TRAJECTORY_SNAPSHOT } from './trajectory-snapshot-builder.ts' import css from './views.module.css' const EMPTY_TURN_IDS: ReadonlySet = new Set() @@ -64,14 +65,12 @@ function partialStructureSignature(partial: ConversationSnapshot['partial']): st : block.kind).join('\u0000') } -/** Session-history paging needed by the event-complete trajectory view. */ +/** Session-bound controls not already supplied by the conversation view slot. */ export interface TrajectoryViewInjected { hooks: { - history: SessionHistoryFace duration: SnapshotStore } - loadHistoryTail: (signal: AbortSignal) => Promise - loadOlderHistory: (signal: AbortSignal) => Promise + loadOlder: () => Promise setActualDuration: (actualDuration: boolean) => void } @@ -184,7 +183,7 @@ function mergeSearchMatches( } export function TrajectoryView({ - useHistory, useDuration, loadHistoryTail, loadOlderHistory, setActualDuration, + useSession, useDuration, loadOlder, setActualDuration, inspect, onInspectDone, }: ConvViewProps & InjectFace) { const [collapsedTurns, setCollapsedTurns] = useState>(EMPTY_TURN_IDS) @@ -204,23 +203,15 @@ export function TrajectoryView({ const [timelineRecordFocus, setTimelineRecordFocus] = useState<{ readonly index: number } | null>(null) - const inspection = useHistory(snapshot => snapshot.inspection) - const historyLoading = useHistory(snapshot => - snapshot.state === 'cold' || snapshot.state === 'loading') - const hasOlderHistory = useHistory(snapshot => snapshot.hasMore) - const historyBaseSeq = useHistory(snapshot => snapshot.baseSeq) + const inspection = useSession(snapshot => + snapshot.views.get('trajectory') ?? EMPTY_TRAJECTORY_SNAPSHOT) + const historyLoading = useSession(snapshot => + snapshot.openState === 'loading' || snapshot.loadingOlder) + const hasOlderHistory = useSession(snapshot => snapshot.hasMore) const nodes = inspection.eventNodes + const historyBaseSeq = nodes[0]?.seq ?? 0 const partial = inspection.partial const runningCalls = inspection.runningCalls - const loadHistoryTailRef = useRef(loadHistoryTail) - loadHistoryTailRef.current = loadHistoryTail - const historyControllerRef = useRef(null) - useEffect(() => { - const controller = new AbortController() - historyControllerRef.current = controller - void loadHistoryTailRef.current(controller.signal) - return () => { controller.abort() } - }, []) const requests = inspection.requests const callSchemas = inspection.callSchemas const historyContexts = inspection.contexts @@ -518,11 +509,8 @@ export function TrajectoryView({ } const loadEarlierHistory = useCallback(() => { - const signal = historyControllerRef.current?.signal - return signal?.aborted === false - ? loadOlderHistory(signal) - : Promise.resolve(false) - }, [loadOlderHistory]) + return loadOlder() + }, [loadOlder]) return (
diff --git a/packages/client/ui-trajectory/src/client/index.ts b/packages/client/ui-trajectory/src/client/index.ts index e1d3a5cc17..1f48a4711d 100644 --- a/packages/client/ui-trajectory/src/client/index.ts +++ b/packages/client/ui-trajectory/src/client/index.ts @@ -9,9 +9,15 @@ import type { SessionId } from '@deepseek-ai/dsh-client-runtime/client' import type {} from '@deepseek-ai/dsh-client-ui-conversation/client' import { createTrajectoryDurationStore } from './duration-store.ts' import { TrajectoryView, type TrajectoryViewInjected } from './TrajectoryView.tsx' +import { registerTrajectoryAssistantDefinition } from './trajectory-assistant-definition.ts' +import { registerTrajectoryCompactionDefinitions } from './trajectory-compaction-definition.ts' +import { registerTrajectoryMessageDefinitions } from './trajectory-message-definitions.ts' +import { registerTrajectoryRequestHeaderDefinition } from './trajectory-request-header-definition.ts' +import { registerTrajectoryConversationView } from './trajectory-snapshot-builder.ts' +import { registerTrajectoryToolDefinition } from './trajectory-tool-definition.ts' -/** Required services: the conversation view slot and independent history source. */ -export const inject = ['slots', 'sessionHistory'] +/** Required services: the conversation slot, registries, and ordinary Session paging. */ +export const inject = ['slots', 'conversationEvents', 'conversationViews', 'sessions'] /** * Client plugin body: register the trajectory view tab. The registration @@ -20,17 +26,29 @@ export const inject = ['slots', 'sessionHistory'] */ export function apply(ctx: Context): void { const duration = createTrajectoryDurationStore() + registerTrajectoryMessageDefinitions(ctx) + registerTrajectoryRequestHeaderDefinition(ctx) + registerTrajectoryAssistantDefinition(ctx) + registerTrajectoryToolDefinition(ctx) + registerTrajectoryCompactionDefinitions(ctx) + registerTrajectoryConversationView(ctx) ctx.slots.inject('conversation.view', () => ctx.slots.register({ name: 'conversation.view', id: 'trajectory', order: 10, label: 'Trajectory', inject: (sessionId: SessionId): TrajectoryViewInjected => { - const history = ctx.sessionHistory.source(sessionId) + const session = ctx.sessions.binding(sessionId)?.session + if (session === undefined) { + throw new Error(`ui-trajectory: session "${sessionId}" is unavailable`) + } return { - hooks: { history, duration }, - loadHistoryTail: signal => history.loadTail(signal), - loadOlderHistory: signal => history.loadOlder(signal), + hooks: { duration }, + loadOlder: async () => { + const hadMore = session.getSnapshot().hasMore + await session.loadOlder() + return hadMore + }, setActualDuration: (value) => { duration.set(value) }, } }, diff --git a/packages/client/ui-trajectory/src/client/trajectory-assistant-definition.ts b/packages/client/ui-trajectory/src/client/trajectory-assistant-definition.ts new file mode 100644 index 0000000000..8f0d9ff430 --- /dev/null +++ b/packages/client/ui-trajectory/src/client/trajectory-assistant-definition.ts @@ -0,0 +1,397 @@ +import type { Context } from 'cordis' +import type { + AssistantBlock, AssistantMessageNode, ConversationLocation, ConversationMatch, + ConversationNodeContext, ConversationNodeDefinition, PartialAssistant, RequestView, +} from '@deepseek-ai/dsh-client-runtime/client' +import { + displayFailureMessage, emptyAssistantBlock, isTokenDelta, toAssistantBlock, + toAssistantBlocks, +} from '@deepseek-ai/dsh-client-runtime/client' +import { trajectoryNode } from './trajectory-definition-common.ts' + +interface UsageValue { + readonly inputTokens: number + readonly outputTokens: number + readonly cacheReadTokens?: number + readonly cacheWriteTokens?: number + readonly reasoningTokens?: number +} + +interface RetryValue { + readonly message: string + readonly retry: number + readonly maxRetries?: number + readonly delayMs: number +} + +interface AssistantState { + readonly turn: number + readonly step: number + readonly startSeq: number + readonly startTime: number + readonly started: boolean + readonly sawChunk: boolean + readonly blocks: readonly (AssistantBlock | undefined)[] + readonly firstVisibleSeq: number | undefined + readonly firstVisibleTime: number | undefined + readonly firstTokenTime: number | undefined + readonly final: ConversationMatch | undefined + readonly usage: UsageValue | undefined + readonly retry: RetryValue | undefined + readonly stepEnd: ConversationMatch | undefined +} + +function initialState( + turn: number, + step: number, + startSeq: number, + startTime: number, + started: boolean, +): AssistantState { + return { + turn, + step, + startSeq, + startTime, + started, + sawChunk: false, + blocks: [], + firstVisibleSeq: undefined, + firstVisibleTime: undefined, + firstTokenTime: undefined, + final: undefined, + usage: undefined, + retry: undefined, + stepEnd: undefined, + } +} + +function compactBlocks(blocks: readonly (AssistantBlock | undefined)[]): AssistantBlock[] { + return blocks.filter((block): block is AssistantBlock => block !== undefined) +} + +function hasVisibleContent(blocks: readonly AssistantBlock[]): boolean { + return blocks.some((block) => { + if (block.kind === 'tool-call') return false + if (block.kind === 'text' || block.kind === 'reasoning') return block.text.trim() !== '' + return true + }) +} + +function hasInterruptionEvidence(blocks: readonly AssistantBlock[]): boolean { + return blocks.some((block) => { + if (block.kind === 'text' || block.kind === 'reasoning') return block.text.trim() !== '' + return true + }) +} + +function addUsage(current: UsageValue | undefined, next: UsageValue): UsageValue { + return { + inputTokens: (current?.inputTokens ?? 0) + next.inputTokens, + outputTokens: (current?.outputTokens ?? 0) + next.outputTokens, + ...(current?.cacheReadTokens === undefined && next.cacheReadTokens === undefined + ? {} + : { cacheReadTokens: (current?.cacheReadTokens ?? 0) + (next.cacheReadTokens ?? 0) }), + ...(current?.cacheWriteTokens === undefined && next.cacheWriteTokens === undefined + ? {} + : { cacheWriteTokens: (current?.cacheWriteTokens ?? 0) + (next.cacheWriteTokens ?? 0) }), + ...(current?.reasoningTokens === undefined && next.reasoningTokens === undefined + ? {} + : { reasoningTokens: (current?.reasoningTokens ?? 0) + (next.reasoningTokens ?? 0) }), + } +} + +function updateChunk(state: AssistantState, match: ConversationMatch): AssistantState { + if (match.event.type !== 'assistant/chunk') return state + const chunk = match.event.data.chunk + if (chunk.type === 'usage') { + return { ...state, sawChunk: true, usage: addUsage(state.usage, chunk.usage) } + } + const blocks = [...state.blocks] + switch (chunk.type) { + case 'block-start': + blocks[chunk.index] = emptyAssistantBlock(chunk.blockType) + break + case 'text-delta': { + const previous = blocks[chunk.index] + blocks[chunk.index] = { + kind: 'text', + text: (previous?.kind === 'text' ? previous.text : '') + chunk.text, + } + break + } + case 'reasoning-delta': { + const previous = blocks[chunk.index] + blocks[chunk.index] = { + kind: 'reasoning', + text: (previous?.kind === 'reasoning' ? previous.text : '') + chunk.text, + } + break + } + case 'tool-call-delta': { + const previous = blocks[chunk.index] + const base = previous?.kind === 'tool-call' + ? previous + : { kind: 'tool-call' as const, callId: '', name: '', argsRaw: '' } + blocks[chunk.index] = { + kind: 'tool-call', + callId: base.callId || String(chunk.id), + name: chunk.name ?? base.name, + argsRaw: base.argsRaw + chunk.argumentsDelta, + } + break + } + case 'block-end': + blocks[chunk.index] = toAssistantBlock(chunk.block) + break + default: + return { ...state, sawChunk: true } + } + const visible = hasVisibleContent(compactBlocks(blocks)) + return { + ...state, + sawChunk: true, + blocks, + ...(visible && state.firstVisibleSeq === undefined + ? { firstVisibleSeq: match.event.seq, firstVisibleTime: match.event.time } + : {}), + ...(isTokenDelta(chunk) && state.firstTokenTime === undefined + ? { firstTokenTime: match.event.time } + : {}), + } +} + +function closedBoundary( + context: ConversationNodeContext, +): { seq: number; time: number } | undefined { + if (context.state?.stepEnd?.event.type === 'step/end') return context.state.stepEnd.event + const location: ConversationLocation | undefined = context.start?.location + ?? context.matches.at(-1)?.location + if (location?.kind === 'step' && location.step.status === 'closed') return location.step.end + if ((location?.kind === 'step' || location?.kind === 'turn') + && location.turn.status === 'closed') return location.turn.end + return undefined +} + +function fallbackState(context: ConversationNodeContext): AssistantState | undefined { + let state: AssistantState | undefined + for (const match of context.matches) { + const event = match.event + if (event.type === 'assistant/chunk') { + state ??= initialState(event.data.turn, event.data.step, event.seq, event.time, false) + state = updateChunk(state, match) + } else if (event.type === 'assistant/message') { + state ??= initialState(event.data.turn, event.data.step, event.seq, event.time, false) + state = { + ...state, + blocks: toAssistantBlocks(event.data.message.content), + final: match, + usage: state.usage ?? event.data.usage, + } + } else if (event.type === 'step/end' && state !== undefined) { + state = { ...state, stepEnd: match } + } + } + return state +} + +function finalNode( + state: AssistantState, + context: ConversationNodeContext, +): AssistantMessageNode | undefined { + const final = state.final + if (final?.event.type === 'assistant/message') { + const event = final.event + return { + kind: 'assistant', + seq: event.seq, + time: event.time, + turn: state.turn, + step: state.step, + blocks: toAssistantBlocks(event.data.message.content), + usage: event.data.usage, + provenance: { + provider: event.data.message.source.provider, + model: event.data.message.source.model, + }, + timing: { + stepStartTime: state.started ? state.startTime : null, + firstTokenTime: state.firstTokenTime ?? null, + completedTime: event.time, + }, + } + } + const boundary = closedBoundary(context) + const blocks = compactBlocks(state.blocks) + if (boundary === undefined || !hasInterruptionEvidence(blocks)) return undefined + return { + kind: 'assistant', + seq: boundary.seq - 0.9, + time: boundary.time, + turn: state.turn, + step: state.step, + blocks, + interrupted: true, + } +} + +function assistantRequest( + state: AssistantState, + node: AssistantMessageNode | undefined, + boundary: { seq: number; time: number } | undefined, +): Extract | undefined { + if (!state.started) return undefined + const status = node !== undefined && node.interrupted !== true + ? 'complete' + : state.retry !== undefined || boundary !== undefined ? 'error' : 'running' + return { + purpose: 'assistant', + startSeq: state.startSeq, + turn: state.turn, + step: state.step, + startedAt: state.startTime, + completedAt: node?.time ?? boundary?.time ?? null, + status, + ...(state.retry === undefined + ? {} + : { + error: state.retry.message, + retry: state.retry.retry, + ...(state.retry.maxRetries === undefined ? {} : { maxRetries: state.retry.maxRetries }), + retryDelayMs: state.retry.delayMs, + }), + ...(node === undefined || node.interrupted === true + ? {} + : { + resultSeq: node.seq, + ...(node.provenance === undefined ? {} : { provenance: node.provenance }), + }), + ...(state.usage === undefined ? {} : { usage: state.usage }), + } +} + +/** Trajectory-owned Assistant streaming, settlement, and request lifecycle. */ +const trajectoryAssistantDefinition: ConversationNodeDefinition = { + kind: 'trajectory-assistant-step', + target: 'trajectory', + match: (event) => { + if (event.type === 'step/start') { + return { id: `${event.data.turn}:${event.data.step}`, role: 'start' } + } + if (event.type === 'assistant/chunk' + || event.type === 'assistant/message' + || event.type === 'llm/retry' + || event.type === 'step/end') { + return { id: `${event.data.turn}:${event.data.step}`, role: 'update' } + } + return null + }, + start: (_context, match) => { + if (match.event.type !== 'step/start') { + throw new Error('trajectory-assistant-step start requires step/start') + } + return initialState( + match.event.data.turn, + match.event.data.step, + match.event.seq, + match.event.time, + true, + ) + }, + update: (context, match) => { + if (match.event.type === 'assistant/chunk') return updateChunk(context.state, match) + if (match.event.type === 'assistant/message') { + return { + ...context.state, + blocks: toAssistantBlocks(match.event.data.message.content), + final: match, + usage: context.state.usage ?? match.event.data.usage, + } + } + if (match.event.type === 'step/end') return { ...context.state, stepEnd: match } + if (match.event.type !== 'llm/retry') return context.state + const data = match.event.data + return { + ...initialState( + context.state.turn, + context.state.step, + context.state.startSeq, + context.state.startTime, + true, + ), + firstTokenTime: context.state.firstTokenTime, + usage: context.state.usage, + retry: { + message: displayFailureMessage(data.failure), + retry: data.retry, + ...(data.mode === 'normal' ? { maxRetries: data.maxRetries } : {}), + delayMs: data.delayMs, + }, + } + }, + publication: (match) => { + if (match.event.type === 'step/start') return 'none' + if (match.event.type !== 'assistant/chunk') return 'immediate' + const type = match.event.data.chunk.type + return type === 'usage' || type === 'finish' ? 'none' : 'animation-frame' + }, + buildViewNode: (context) => { + const state = context.state ?? fallbackState(context) + if (state === undefined) return null + const node = finalNode(state, context) + const boundary = closedBoundary(context) + const partial: PartialAssistant | null = node === undefined && boundary === undefined && state.sawChunk + ? { turn: state.turn, step: state.step, blocks: compactBlocks(state.blocks) } + : null + const request = assistantRequest(state, node, boundary) + if (node === undefined && partial === null && request === undefined) return null + return trajectoryNode(context, state.startSeq, { + kind: 'assistant', + ...(node === undefined ? {} : { node }), + partial, + ...(request === undefined ? {} : { request }), + }) + }, +} + +interface TurnEndState { + readonly turn: number + readonly seq: number + readonly time: number + readonly error?: string +} + +const trajectoryTurnEndDefinition: ConversationNodeDefinition = { + kind: 'trajectory-turn-end', + target: 'trajectory', + match: event => event.type === 'turn/end' + ? { id: String(event.seq), role: 'start' } + : null, + start: (_context, match) => { + if (match.event.type !== 'turn/end') { + throw new Error('trajectory-turn-end start requires turn/end') + } + const reason = match.event.data.reason + return { + turn: match.event.data.turn, + seq: match.event.seq, + time: match.event.time, + ...(reason.kind === 'error' ? { error: displayFailureMessage(reason.error) } : {}), + } + }, + update: context => context.state, + buildViewNode: context => context.state === undefined + ? null + : trajectoryNode(context, context.state.seq, { + kind: 'turn-end', + turn: context.state.turn, + time: context.state.time, + ...(context.state.error === undefined ? {} : { error: context.state.error }), + }), +} + +/** Register the Trajectory Assistant lifecycle. */ +export function registerTrajectoryAssistantDefinition(ctx: Context): void { + ctx.conversationEvents.register(trajectoryAssistantDefinition) + ctx.conversationEvents.register(trajectoryTurnEndDefinition) +} diff --git a/packages/client/ui-trajectory/src/client/trajectory-compaction-definition.ts b/packages/client/ui-trajectory/src/client/trajectory-compaction-definition.ts new file mode 100644 index 0000000000..65bab06059 --- /dev/null +++ b/packages/client/ui-trajectory/src/client/trajectory-compaction-definition.ts @@ -0,0 +1,139 @@ +import type { Context } from 'cordis' +import type { + ConversationMatch, ConversationNodeDefinition, RequestView, +} from '@deepseek-ai/dsh-client-runtime/client' +import type {} from '@deepseek-ai/dsh-compact/types' +import { trajectoryNode } from './trajectory-definition-common.ts' + +interface CompactionState { + readonly start: ConversationMatch + readonly summary?: ConversationMatch + readonly end?: ConversationMatch + readonly checkpoint?: ConversationMatch +} + +function checkpointId( + event: Parameters[0], +): string | undefined { + if (event.type !== 'user/message') return undefined + const source = event.data.source as unknown as { + readonly kind?: unknown + readonly plugin?: unknown + readonly compactionId?: unknown + } + return source.kind === 'plugin' && source.plugin === 'compact' + && typeof source.compactionId === 'string' && source.compactionId !== '' + ? source.compactionId + : undefined +} + +function eventCompactionId( + event: Parameters[0], +): string | undefined { + if (event.type !== 'compact/start' + && event.type !== 'compact/summary' + && event.type !== 'compact/end') return undefined + const value: unknown = event.data.compactionId + return typeof value === 'string' && value !== '' ? value : undefined +} + +function requestFromState( + state: CompactionState, +): Extract | undefined { + const start = state.start.event + if (start.type !== 'compact/start') return undefined + const summary = state.summary?.event + const end = state.end?.event + const checkpoint = state.checkpoint?.event + return { + purpose: 'compaction', + startSeq: start.seq, + turn: start.data.turn, + step: 0, + startedAt: start.time, + completedAt: end?.type === 'compact/end' ? end.time : null, + status: end?.type !== 'compact/end' + ? 'running' + : end.data.error === undefined ? 'complete' : 'error', + ...(end?.type === 'compact/end' && end.data.error !== undefined + ? { error: end.data.error } + : {}), + ...(summary?.type !== 'compact/summary' + ? {} + : { + resultSeq: summary.seq, + summary: summary.data.summary, + ...(summary.data.rawOutput === undefined ? {} : { rawOutput: summary.data.rawOutput }), + provenance: { provider: summary.data.provider, model: summary.data.model }, + requestConfig: { + provider: summary.data.provider, + model: summary.data.model, + purpose: 'compaction', + ...(summary.data.maxTokens === undefined ? {} : { maxTokens: summary.data.maxTokens }), + }, + ...(summary.data.usage === undefined ? {} : { usage: summary.data.usage }), + }), + ...(checkpoint?.type === 'user/message' ? { replacementSeq: checkpoint.seq } : {}), + } +} + +const trajectoryCompactionDefinition: ConversationNodeDefinition = { + kind: 'trajectory-compaction', + target: 'trajectory', + match: (event) => { + const compactId = eventCompactionId(event) + if (compactId !== undefined) { + return { id: compactId, role: event.type === 'compact/start' ? 'start' : 'update' } + } + const checkpoint = checkpointId(event) + return checkpoint === undefined ? null : { id: checkpoint, role: 'update' } + }, + start: (_context, match) => { + if (match.event.type !== 'compact/start') { + throw new Error('trajectory-compaction start requires compact/start') + } + return { start: match } + }, + update: (context, match) => { + if (match.event.type === 'compact/summary') return { ...context.state, summary: match } + if (match.event.type === 'compact/end') return { ...context.state, end: match } + return checkpointId(match.event) === undefined + ? context.state + : { ...context.state, checkpoint: match } + }, + buildViewNode: (context) => { + if (context.state === undefined) return null + const request = requestFromState(context.state) + return request === undefined + ? null + : trajectoryNode(context, request.startSeq, { kind: 'compaction', request }) + }, +} + +interface SessionEndState { + readonly seq: number + readonly time: number +} + +const trajectorySessionEndDefinition: ConversationNodeDefinition = { + kind: 'trajectory-session-end', + target: 'trajectory', + match: event => event.type === 'session/end-seed' + ? { id: String(event.seq), role: 'start' } + : null, + start: (_context, match) => ({ seq: match.event.seq, time: match.event.time }), + update: context => context.state, + buildViewNode: context => context.state === undefined + ? null + : trajectoryNode(context, context.state.seq, { + kind: 'session-end', + seq: context.state.seq, + time: context.state.time, + }), +} + +/** Register Trajectory compaction requests and session boundaries. */ +export function registerTrajectoryCompactionDefinitions(ctx: Context): void { + ctx.conversationEvents.register(trajectoryCompactionDefinition) + ctx.conversationEvents.register(trajectorySessionEndDefinition) +} diff --git a/packages/client/ui-trajectory/src/client/trajectory-contract.ts b/packages/client/ui-trajectory/src/client/trajectory-contract.ts new file mode 100644 index 0000000000..e261eeb9fc --- /dev/null +++ b/packages/client/ui-trajectory/src/client/trajectory-contract.ts @@ -0,0 +1,75 @@ +import type { + AssistantMessageNode, ConversationContext, ConversationLocation, ConversationNode, + ConversationPromptSnapshot, ConversationViewNode, PartialAssistant, + RequestPromptChange, RequestView, RunningToolCall, ToolCallBlock, +} from '@deepseek-ai/dsh-client-runtime/client' + +/** Request-header facts retained by the Trajectory target. */ +export interface TrajectoryRequestHeaderState { + readonly seq: number + readonly time: number + readonly prompt: ConversationPromptSnapshot + readonly change?: RequestPromptChange + readonly location: ConversationLocation +} + +/** One independently assembled contribution to the legacy Trajectory ledger. */ +export type TrajectoryContribution = + | { + readonly kind: 'node' + readonly node: ConversationNode + } + | { + readonly kind: 'assistant' + readonly node?: AssistantMessageNode + readonly partial: PartialAssistant | null + readonly request?: Extract + } + | { + readonly kind: 'tool' + readonly root: ToolCallBlock + } + | { + readonly kind: 'request-header' + readonly header: TrajectoryRequestHeaderState + } + | { + readonly kind: 'compaction' + readonly request: Extract + } + | { + readonly kind: 'session-end' + readonly seq: number + readonly time: number + } + | { + readonly kind: 'turn-end' + readonly turn: number + readonly time: number + readonly error?: string + } + +/** Target envelope consumed by the Trajectory snapshot builder. */ +export interface TrajectoryConversationViewNode extends ConversationViewNode { + readonly target: 'trajectory' + readonly anchorSeq: number + readonly data: TrajectoryContribution +} + +/** Stage-oriented Trajectory data assembled from registered business Contexts. */ +export interface TrajectorySnapshot { + readonly eventNodes: readonly ConversationNode[] + readonly contexts: readonly ConversationContext[] + readonly requests: readonly RequestView[] + readonly callSchemas: ReadonlyMap + readonly interruptedNodes: readonly ConversationNode[] + readonly partial: PartialAssistant | null + readonly runningCalls: readonly RunningToolCall[] +} + +declare module '@deepseek-ai/dsh-client-runtime/client' { + interface ConversationViewSnapshotMap { + /** Independently assembled data consumed by the Trajectory view. */ + trajectory: TrajectorySnapshot + } +} diff --git a/packages/client/ui-trajectory/src/client/trajectory-definition-common.ts b/packages/client/ui-trajectory/src/client/trajectory-definition-common.ts new file mode 100644 index 0000000000..d11034b9b9 --- /dev/null +++ b/packages/client/ui-trajectory/src/client/trajectory-definition-common.ts @@ -0,0 +1,29 @@ +import type { + ConversationLocation, ConversationNodeContext, +} from '@deepseek-ai/dsh-client-runtime/client' +import type { + TrajectoryContribution, TrajectoryConversationViewNode, +} from './trajectory-contract.ts' + +/** Resolve the best loaded Location for one target-local Context. */ +export function trajectoryContextLocation( + context: ConversationNodeContext, +): ConversationLocation { + return context.start?.location ?? context.matches[0]?.location ?? { kind: 'unresolved' } +} + +/** Wrap one contribution in the Engine-owned target envelope. */ +export function trajectoryNode( + context: ConversationNodeContext, + anchorSeq: number, + data: TrajectoryContribution, +): TrajectoryConversationViewNode { + return { + key: context.key, + kind: context.kind, + id: context.id, + target: 'trajectory', + anchorSeq, + data, + } +} diff --git a/packages/client/ui-trajectory/src/client/trajectory-message-definitions.ts b/packages/client/ui-trajectory/src/client/trajectory-message-definitions.ts new file mode 100644 index 0000000000..5f6b203e28 --- /dev/null +++ b/packages/client/ui-trajectory/src/client/trajectory-message-definitions.ts @@ -0,0 +1,114 @@ +import type { Context } from 'cordis' +import type { + ContextMessageNode, ConversationNodeDefinition, ConversationPreviousContext, + SteeringMessageNode, UserMessageNode, +} from '@deepseek-ai/dsh-client-runtime/client' +import { + contextForm, contextProvenance, +} from '@deepseek-ai/dsh-client-runtime/client' +import type {} from '@deepseek-ai/dsh-agent/types' +import { trajectoryNode } from './trajectory-definition-common.ts' + +interface InboxIdentity { + readonly id: string +} + +interface InboxSplice { + readonly start: number + readonly removedCount?: number + readonly inserted: readonly InboxIdentity[] + readonly outcome?: 'canceled' +} + +interface InboxState { + readonly pending: readonly InboxIdentity[] + readonly claimed: ReadonlySet +} + +type MessageNode = UserMessageNode | SteeringMessageNode | ContextMessageNode + +function applySplice( + previous: ConversationPreviousContext | undefined, + splice: InboxSplice, +): InboxState { + const pending = [...(previous?.state.pending ?? [])] + const claimed = new Set(previous?.state.claimed ?? []) + const removed = pending.splice(splice.start, splice.removedCount ?? 0, ...splice.inserted) + for (const identity of splice.inserted) claimed.delete(identity.id) + if (splice.outcome !== 'canceled') { + for (const identity of removed) claimed.add(identity.id) + } + return { pending, claimed } +} + +const trajectoryInboxDefinition: ConversationNodeDefinition = { + kind: 'trajectory-inbox-next-step', + match: event => event.type === 'agent/inbox/spliced' + && event.data.target === 'next-step' + ? { id: String(event.seq), role: 'start' } + : null, + start: (_context, match, reader) => { + if (match.event.type !== 'agent/inbox/spliced') { + throw new Error('trajectory-inbox-next-step start requires agent/inbox/spliced') + } + return applySplice( + reader.previous('trajectory-inbox-next-step'), + match.event.data, + ) + }, + update: context => context.state, + publication: () => 'none', +} + +const trajectoryMessageDefinition: ConversationNodeDefinition = { + kind: 'trajectory-input-message', + target: 'trajectory', + match: event => event.type === 'user/message' + ? { id: String(event.seq), role: 'start' } + : null, + start: (_context, match, reader) => { + if (match.event.type !== 'user/message') { + throw new Error('trajectory-input-message start requires user/message') + } + const event = match.event + if (event.data.source.kind !== 'user') { + return { + kind: 'context', + seq: event.seq, + time: event.time, + content: event.data.content, + source: event.data.source, + provenance: contextProvenance(event.data.source), + form: contextForm(event.data.source), + } + } + const claimed = reader.previous('trajectory-inbox-next-step') + ?.state.claimed.has(String(event.data.id)) === true + return claimed + ? { + kind: 'steering', + messageId: event.data.id, + seq: event.seq, + time: event.time, + content: event.data.content, + source: event.data.source, + } + : { + kind: 'user', + seq: event.seq, + time: event.time, + content: event.data.content, + source: event.data.source, + } + }, + update: context => context.state, + buildViewNode: context => context.state === undefined + ? null + : trajectoryNode(context, context.state.seq, { kind: 'node', node: context.state }), +} + +/** Register Trajectory-owned inbox classification and message records. */ +export function registerTrajectoryMessageDefinitions(ctx: Context): void { + ctx.conversationEvents.register(trajectoryInboxDefinition) + ctx.conversationEvents.register(trajectoryMessageDefinition) +} diff --git a/packages/client/ui-trajectory/src/client/trajectory-request-header-definition.ts b/packages/client/ui-trajectory/src/client/trajectory-request-header-definition.ts new file mode 100644 index 0000000000..a6ec4e4597 --- /dev/null +++ b/packages/client/ui-trajectory/src/client/trajectory-request-header-definition.ts @@ -0,0 +1,76 @@ +import type { Context } from 'cordis' +import type { + ConversationMatch, ConversationNodeDefinition, ConversationPromptSnapshot, + RequestPromptChange, +} from '@deepseek-ai/dsh-client-runtime/client' +import { trajectoryNode } from './trajectory-definition-common.ts' +import type { TrajectoryRequestHeaderState } from './trajectory-contract.ts' + +function requestPrompt(match: ConversationMatch): ConversationPromptSnapshot { + if (match.event.type !== 'request/header') { + throw new Error('trajectory-request-header start requires request/header') + } + const header = match.event.data.header + const tools: unknown = header.tools + return { + config: header.config, + system: header.system ?? '', + tools: Array.isArray(tools) ? tools as ConversationPromptSnapshot['tools'] : [], + } +} + +function promptChange( + previous: ConversationPromptSnapshot | undefined, + prompt: ConversationPromptSnapshot, + match: ConversationMatch, +): RequestPromptChange | undefined { + if (match.event.type !== 'request/header') return undefined + if (previous === undefined && match.event.data.reason !== 'initial') return undefined + const systemChanged = previous !== undefined && previous.system !== prompt.system + const toolsChanged = previous !== undefined + && JSON.stringify(previous.tools) !== JSON.stringify(prompt.tools) + if (previous !== undefined && !systemChanged && !toolsChanged) return undefined + return { + seq: match.event.seq, + time: match.event.time, + kind: previous === undefined + ? 'initial' + : systemChanged && toolsChanged + ? 'system-and-tools' + : systemChanged ? 'system' : 'tools', + ...(previous === undefined ? {} : { previous }), + } +} + +const trajectoryRequestHeaderDefinition: ConversationNodeDefinition = { + kind: 'trajectory-request-header', + target: 'trajectory', + match: event => event.type === 'request/header' + ? { id: String(event.seq), role: 'start' } + : null, + start: (_context, match, reader) => { + const prompt = requestPrompt(match) + const previous = reader.previous('trajectory-request-header') + ?.state.prompt + const change = promptChange(previous, prompt, match) + return { + seq: match.event.seq, + time: match.event.time, + prompt, + location: match.location, + ...(change === undefined ? {} : { change }), + } + }, + update: context => context.state, + buildViewNode: context => context.state === undefined + ? null + : trajectoryNode(context, context.state.seq, { + kind: 'request-header', + header: context.state, + }), +} + +/** Register Trajectory request-header facts. */ +export function registerTrajectoryRequestHeaderDefinition(ctx: Context): void { + ctx.conversationEvents.register(trajectoryRequestHeaderDefinition) +} diff --git a/packages/client/ui-trajectory/src/client/trajectory-snapshot-builder.ts b/packages/client/ui-trajectory/src/client/trajectory-snapshot-builder.ts new file mode 100644 index 0000000000..613cd1e750 --- /dev/null +++ b/packages/client/ui-trajectory/src/client/trajectory-snapshot-builder.ts @@ -0,0 +1,222 @@ +import type { Context } from 'cordis' +import type { + AssistantMessageNode, ConversationNode, ConversationPromptSnapshot, + ConversationViewBuilder, ConversationViewDefinition, RequestView, + ToolCallBlock, +} from '@deepseek-ai/dsh-client-runtime/client' +import type { + TrajectoryConversationViewNode, TrajectoryRequestHeaderState, + TrajectorySnapshot, +} from './trajectory-contract.ts' + +const EMPTY_LIST: readonly never[] = [] +const EMPTY_CONTEXTS = [{ id: 0, nodes: EMPTY_LIST }] + +/** Stable empty target used until a Session has assembled Trajectory records. */ +export const EMPTY_TRAJECTORY_SNAPSHOT: TrajectorySnapshot = { + eventNodes: EMPTY_LIST, + contexts: EMPTY_CONTEXTS, + requests: EMPTY_LIST, + callSchemas: new Map(), + interruptedNodes: EMPTY_LIST, + partial: null, + runningCalls: EMPTY_LIST, +} + +function coordinates( + header: TrajectoryRequestHeaderState, +): { turn?: number; step?: number } { + const location = header.location + if (location.kind === 'step') return { turn: location.turn.turn, step: location.step.step } + if (location.kind === 'turn') return { turn: location.turn.turn } + return {} +} + +function headerFor( + request: Extract, + headers: readonly TrajectoryRequestHeaderState[], +): TrajectoryRequestHeaderState | undefined { + const exact = headers.findLast((header) => { + const location = coordinates(header) + return location.turn === request.turn && location.step === request.step + }) + return exact ?? headers.findLast(header => header.seq < request.startSeq) +} + +function applyHeader( + request: Extract, + header: TrajectoryRequestHeaderState | undefined, +): Extract { + return header === undefined + ? request + : { + ...request, + prompt: header.prompt, + requestConfig: header.prompt.config, + ...(header.change === undefined ? {} : { promptChange: header.change }), + } +} + +function withRequestConfig( + node: AssistantMessageNode, + prompt: ConversationPromptSnapshot | undefined, +): AssistantMessageNode { + return prompt === undefined ? node : { ...node, requestConfig: prompt.config } +} + +function captureSchemas( + block: ToolCallBlock, + tools: readonly ConversationPromptSnapshot['tools'][number][], + output: Map, +): void { + const name = 'kind' in block ? block.call?.name : block.name + const schema = name === undefined || name === null + ? undefined + : tools.find(candidate => candidate.name === name) + if (schema !== undefined) output.set(block.callId, schema) + for (const child of block.subCalls) captureSchemas(child, tools, output) +} + +function interruptCompactions( + requests: RequestView[], + boundaries: readonly { seq: number; time: number }[], +): void { + for (const boundary of boundaries) { + const index = requests.findLastIndex(request => + request.purpose === 'compaction' + && request.startSeq < boundary.seq + && request.status === 'running') + const request = requests[index] + if (request?.purpose !== 'compaction') continue + requests[index] = { + ...request, + completedAt: boundary.time, + status: 'error', + error: 'Compaction was interrupted before completion.', + } + } +} + +function applyTurnErrors( + requests: RequestView[], + endings: readonly { turn: number; time: number; error?: string }[], +): void { + for (const ending of endings) { + if (ending.error === undefined) continue + const index = requests.findLastIndex(request => + request.purpose === 'assistant' && request.turn === ending.turn) + const request = requests[index] + if (request?.purpose !== 'assistant') continue + requests[index] = { + ...request, + completedAt: request.completedAt ?? ending.time, + status: 'error', + error: ending.error, + } + } +} + +/** Simple keyed adapter retaining the old Trajectory snapshot and stage layout. */ +export class TrajectorySnapshotBuilder implements ConversationViewBuilder< + TrajectoryConversationViewNode, + TrajectorySnapshot +> { + private readonly nodes = new Map() + readonly empty = EMPTY_TRAJECTORY_SNAPSHOT + + replace(input: { + readonly nodes: readonly TrajectoryConversationViewNode[] + }): TrajectorySnapshot { + this.nodes.clear() + for (const node of input.nodes) this.nodes.set(node.key, node) + return this.snapshot() + } + + apply(input: { + readonly upserts: readonly TrajectoryConversationViewNode[] + }): TrajectorySnapshot { + for (const node of input.upserts) this.nodes.set(node.key, node) + return this.snapshot() + } + + private snapshot(): TrajectorySnapshot { + const contributions = [...this.nodes.values()] + .sort((left, right) => left.anchorSeq - right.anchorSeq || left.key.localeCompare(right.key)) + const headers = contributions.flatMap(node => node.data.kind === 'request-header' + ? [node.data.header] + : []) + const finalized: ConversationNode[] = [] + const requests: RequestView[] = [] + const boundaries: { seq: number; time: number }[] = [] + const turnEndings: { turn: number; time: number; error?: string }[] = [] + const callSchemas = new Map() + let partial: TrajectorySnapshot['partial'] = null + const runningCalls: TrajectorySnapshot['runningCalls'][number][] = [] + + for (const contribution of contributions) { + const data = contribution.data + if (data.kind === 'node') { + finalized.push(data.node) + continue + } + if (data.kind === 'assistant') { + const header = data.request === undefined ? undefined : headerFor(data.request, headers) + if (data.node !== undefined) finalized.push(withRequestConfig(data.node, header?.prompt)) + if (data.partial !== null) partial = data.partial + if (data.request !== undefined) requests.push(applyHeader(data.request, header)) + continue + } + if (data.kind === 'tool') { + if ('kind' in data.root) finalized.push(data.root) + else runningCalls.push(data.root) + const header = headers.findLast(candidate => candidate.seq < contribution.anchorSeq) + if (header !== undefined) captureSchemas(data.root, header.prompt.tools, callSchemas) + continue + } + if (data.kind === 'compaction') { + requests.push(data.request) + continue + } + if (data.kind === 'session-end') { + boundaries.push({ seq: data.seq, time: data.time }) + continue + } + if (data.kind === 'turn-end') { + turnEndings.push({ + turn: data.turn, + time: data.time, + ...(data.error === undefined ? {} : { error: data.error }), + }) + } + } + + requests.sort((left, right) => left.startSeq - right.startSeq) + interruptCompactions(requests, boundaries) + applyTurnErrors(requests, turnEndings) + finalized.sort((left, right) => left.seq - right.seq) + const eventNodes = finalized + return { + eventNodes, + contexts: [{ id: 0, nodes: eventNodes }], + requests, + callSchemas, + interruptedNodes: EMPTY_LIST, + partial, + runningCalls, + } + } +} + +/** Trajectory target factory preserving the existing stage-oriented view model. */ +export const trajectoryViewDefinition: ConversationViewDefinition< + TrajectoryConversationViewNode, + TrajectorySnapshot +> = { + target: 'trajectory', + create: () => new TrajectorySnapshotBuilder(), +} + +/** Register the legacy-shape Trajectory target builder. */ +export function registerTrajectoryConversationView(ctx: Context): void { + ctx.conversationViews.register(trajectoryViewDefinition) +} diff --git a/packages/client/ui-trajectory/src/client/trajectory-tool-definition.ts b/packages/client/ui-trajectory/src/client/trajectory-tool-definition.ts new file mode 100644 index 0000000000..353d89070b --- /dev/null +++ b/packages/client/ui-trajectory/src/client/trajectory-tool-definition.ts @@ -0,0 +1,250 @@ +import type { Context } from 'cordis' +import type { + ConversationMatch, ConversationNodeContext, ConversationNodeDefinition, + RunningToolCall, ToolCallBlock, ToolResultNode, +} from '@deepseek-ai/dsh-client-runtime/client' +import type {} from '@deepseek-ai/dsh-tools/types' +import { trajectoryNode } from './trajectory-definition-common.ts' + +const MAX_DEPTH = 256 + +interface ToolState { + readonly rootId: string + readonly calls: ReadonlyMap + readonly children: ReadonlyMap + readonly parents: ReadonlyMap +} + +interface DispatchData { + readonly parentCallId: string + readonly subCallId: string + readonly name: string + readonly arguments: unknown + readonly isError?: boolean + readonly content?: ToolResultNode['content'] +} + +function rootCall(match: ConversationMatch): RunningToolCall { + if (match.event.type !== 'tool/call') { + throw new Error('trajectory-tool-call start requires tool/call') + } + return { + callId: String(match.event.data.callId), + name: match.event.data.name, + argsRaw: match.event.data.arguments, + turn: match.event.data.turn, + step: match.event.data.step, + time: match.event.time, + callView: match.view?.for === 'call' ? match.view.view : null, + subCalls: [], + } +} + +function rootResult( + match: ConversationMatch, + previous?: RunningToolCall, +): ToolResultNode | undefined { + if (match.event.type !== 'tool/result') return undefined + const result = match.event.data.message.content[0] + return { + kind: 'tool-result', + seq: match.event.seq, + time: match.event.time, + callId: String(match.event.data.message.source.callId), + call: previous === undefined ? null : { name: previous.name, argsRaw: previous.argsRaw }, + callTime: previous?.time ?? null, + content: result.content, + isError: result.isError === true, + ...(match.event.data.error === undefined ? {} : { error: match.event.data.error }), + meta: match.event.data.meta, + callView: previous?.callView ?? null, + resultView: match.view?.for === 'result' ? match.view.view : null, + subCalls: [], + } +} + +function locationTurn(match: ConversationMatch): number { + return match.location.kind === 'step' || match.location.kind === 'turn' + ? match.location.turn.turn + : 0 +} + +function locationStep(match: ConversationMatch): number { + return match.location.kind === 'step' ? match.location.step.step : 0 +} + +function childCall(match: ConversationMatch, data: DispatchData): RunningToolCall { + return { + callId: data.subCallId, + name: data.name, + argsRaw: JSON.stringify(data.arguments), + turn: locationTurn(match), + step: locationStep(match), + time: match.event.time, + callView: null, + subCalls: [], + } +} + +function childResult( + match: ConversationMatch, + data: DispatchData, + previous?: ToolCallBlock, +): ToolResultNode { + return { + kind: 'tool-result', + seq: match.event.seq, + time: match.event.time, + callId: data.subCallId, + call: { name: data.name, argsRaw: JSON.stringify(data.arguments) }, + callTime: previous === undefined || 'kind' in previous ? null : previous.time, + content: data.content ?? [], + isError: data.isError === true, + callView: null, + resultView: null, + subCalls: [], + } +} + +function acceptsEdge(state: ToolState, parent: string, child: string): boolean { + if (parent === child || state.parents.has(child)) return false + let cursor: string | undefined = parent + for (let depth = 0; cursor !== undefined && depth <= MAX_DEPTH; depth++) { + if (cursor === child) return false + cursor = state.parents.get(cursor) + } + return cursor === undefined +} + +function updateDispatch(state: ToolState, match: ConversationMatch): ToolState { + const event = match.event + if (event.type !== 'tool/code-dispatch-start' && event.type !== 'tool/code-dispatch') return state + const data = event.data + const parentId = String(data.parentCallId) + const childId = String(data.subCallId) + const siblings = state.children.get(parentId) ?? [] + const index = siblings.indexOf(childId) + if (index < 0 && !acceptsEdge(state, parentId, childId)) return state + if (event.type === 'tool/code-dispatch-start' && index >= 0) return state + + const calls = new Map(state.calls) + calls.set(childId, event.type === 'tool/code-dispatch-start' + ? childCall(match, data) + : childResult(match, data, calls.get(childId))) + if (index >= 0) return { ...state, calls } + const children = new Map(state.children) + children.set(parentId, [...siblings, childId]) + const parents = new Map(state.parents) + parents.set(childId, parentId) + return { ...state, calls, children, parents } +} + +function interruption( + context: ConversationNodeContext, +): { seq: number; time: number } | undefined { + const location = context.start?.location + if (location?.kind === 'step' && location.step.status === 'closed') return location.step.end + if ((location?.kind === 'step' || location?.kind === 'turn') + && location.turn.status === 'closed') return location.turn.end + return undefined +} + +function projectCall( + state: ToolState, + callId: string, + interruptedAt: { seq: number; time: number } | undefined, + visited = new Set(), + depth = 1, +): ToolCallBlock | undefined { + const block = state.calls.get(callId) + if (block === undefined) return undefined + if (visited.has(callId) || depth > MAX_DEPTH) return { ...block, subCalls: [] } + const nextVisited = new Set(visited) + nextVisited.add(callId) + const subCalls = (state.children.get(callId) ?? []) + .flatMap((childId) => { + const child = projectCall(state, childId, interruptedAt, nextVisited, depth + 1) + return child === undefined ? [] : [child] + }) + if ('kind' in block || interruptedAt === undefined) return { ...block, subCalls } + return { + kind: 'tool-result', + seq: interruptedAt.seq - 0.8, + time: interruptedAt.time, + callId: block.callId, + call: { name: block.name, argsRaw: block.argsRaw }, + callTime: block.time, + content: [], + isError: true, + error: { name: 'Interrupted', code: 'interrupted' }, + callView: block.callView, + resultView: null, + subCalls, + } +} + +function fallbackState(context: ConversationNodeContext): ToolState | undefined { + const resultMatch = context.matches.find(match => match.event.type === 'tool/result') + const root = resultMatch === undefined ? undefined : rootResult(resultMatch) + if (root === undefined) return undefined + let state: ToolState = { + rootId: root.callId, + calls: new Map([[root.callId, root]]), + children: new Map(), + parents: new Map(), + } + for (const match of context.matches) state = updateDispatch(state, match) + return state +} + +/** Trajectory-owned root Tool lifecycle with nested Code Dispatch calls. */ +const trajectoryToolDefinition: ConversationNodeDefinition = { + kind: 'trajectory-tool-call', + target: 'trajectory', + match: (event) => { + if (event.type === 'tool/call') return { id: String(event.data.callId), role: 'start' } + if (event.type === 'tool/result') { + return { id: String(event.data.message.source.callId), role: 'update' } + } + if (event.type === 'tool/code-dispatch-start' || event.type === 'tool/code-dispatch') { + const rootCallId: unknown = event.data.rootCallId + return typeof rootCallId === 'string' && rootCallId !== '' + ? { id: rootCallId, role: 'update' } + : null + } + return null + }, + start: (_context, match) => { + const root = rootCall(match) + return { + rootId: root.callId, + calls: new Map([[root.callId, root]]), + children: new Map(), + parents: new Map(), + } + }, + update: (context, match) => { + if (match.event.type !== 'tool/result') return updateDispatch(context.state, match) + const previous = context.state.calls.get(context.state.rootId) + const running = previous !== undefined && !('kind' in previous) ? previous : undefined + const result = rootResult(match, running) + if (result === undefined) return context.state + const calls = new Map(context.state.calls) + calls.set(context.state.rootId, result) + return { ...context.state, calls } + }, + buildViewNode: (context) => { + const state = context.state ?? fallbackState(context) + if (state === undefined) return null + const root = projectCall(state, state.rootId, interruption(context)) + if (root === undefined) return null + const anchorSeq = context.start?.event.seq + ?? ('kind' in root ? root.seq : context.matches[0]?.event.seq ?? 0) + return trajectoryNode(context, anchorSeq, { kind: 'tool', root }) + }, +} + +/** Register the Trajectory Tool lifecycle. */ +export function registerTrajectoryToolDefinition(ctx: Context): void { + ctx.conversationEvents.register(trajectoryToolDefinition) +} diff --git a/packages/client/ui-trajectory/tests/client-bundle.spec.ts b/packages/client/ui-trajectory/tests/client-bundle.spec.ts index 511cf03b5c..902363b719 100644 --- a/packages/client/ui-trajectory/tests/client-bundle.spec.ts +++ b/packages/client/ui-trajectory/tests/client-bundle.spec.ts @@ -10,7 +10,9 @@ import { readFileSync } from 'node:fs' import { resolve } from 'node:path' import { Context } from '@deepseek-ai/cordis' import { afterEach, describe, expect, it } from 'vitest' -import { SlotsService } from '@deepseek-ai/dsh-client-runtime/client' +import { + ConversationEventRegistry, ConversationViewRegistry, SlotsService, +} from '@deepseek-ai/dsh-client-runtime/client' const PLUGIN_ID = '@deepseek-ai/dsh-client-ui-trajectory' @@ -61,21 +63,25 @@ describe('tsdown client artifact', () => { const { handoff, surface } = await loadArtifact() expect(handoff.id).toBe(PLUGIN_ID) expect(surface.apply).toBeTypeOf('function') - expect(surface.inject).toEqual(['slots', 'sessionHistory']) + expect(surface.inject).toEqual([ + 'slots', 'conversationEvents', 'conversationViews', 'sessions', + ]) }) it.skipIf(code === undefined)('mounted as an object plugin, apply registers the view tab on the real ring', async () => { const { surface } = await loadArtifact() const ctx = new Context() const slots = new SlotsService(ctx) + await ctx.plugin(ConversationEventRegistry).await() + await ctx.plugin(ConversationViewRegistry).await() // The conversation entry's role: the ring must be declared before riders land. slots.register({ name: 'root', children: { 'conversation.view': { kind: 'list', scope: 'session' } }, }, (_p: { renderSlot?: unknown }) => null) - // The plugin reads sessionHistory for its per-session history source; - // slot availability is tracked by slots.inject. - ctx.provide('sessionHistory', {}) + // Paging is session-owned; this registration-only probe never renders the + // entry, so the binding stays deliberately empty. + ctx.provide('sessions', { binding: () => undefined }) const fiber = ctx.plugin(surface as { apply: (ctx: Context) => void }) await fiber.await() expect(slots.entries('conversation.view').map(e => e.options.id)).toEqual(['trajectory']) diff --git a/packages/client/ui-trajectory/tests/views.spec.tsx b/packages/client/ui-trajectory/tests/views.spec.tsx index 26adf85ba8..ab3f23d829 100644 --- a/packages/client/ui-trajectory/tests/views.spec.tsx +++ b/packages/client/ui-trajectory/tests/views.spec.tsx @@ -13,12 +13,15 @@ import { act, cleanup, fireEvent, render, screen } from '@testing-library/react' import { createElement, type ComponentProps, type FC, type ReactNode } from 'react' import { bindSnapshotSelector } from '@deepseek-ai/dsh-client-web-react' import { resolveSlotLabel } from '@deepseek-ai/dsh-client-ui-slots' -import { createSnapshotStore } from '@deepseek-ai/dsh-client-runtime/client' +import { + ConversationEventRegistry, ConversationViewRegistry, createSnapshotStore, + EMPTY_CHAT_SNAPSHOT, +} from '@deepseek-ai/dsh-client-runtime/client' import type { UseSession } from '@deepseek-ai/dsh-client-web-react' import { SlotsService } from '@deepseek-ai/dsh-client-runtime/client' import type { - ConversationSnapshot, RequestView, SessionHistoryFace, SessionHistoryInspection, - SessionHistorySnapshot, SessionId, SessionListState, WorkspaceListState, + ConversationSnapshot, RequestView, + SessionId, SessionListState, SnapshotStore, WorkspaceListState, } from '@deepseek-ai/dsh-client-runtime/client' import type { ConvViewProps, ViewTab } from '@deepseek-ai/dsh-client-ui-conversation/client' import { @@ -35,9 +38,11 @@ import { TrajectoryView, type TrajectoryViewInjected, } from '../src/client/TrajectoryView.tsx' import { createTrajectoryDurationStore } from '../src/client/duration-store.ts' +import type { TrajectorySnapshot } from '../src/client/trajectory-contract.ts' import { deriveTrajectoryTimeline } from '../src/client/timeline.ts' const SID = 's1' as SessionId +const sessionSnapshots = new WeakMap>() const tConversation: ConversationSessionHeaderProps['t'] = key => (conversationZh as Record)[key] ?? key @@ -67,37 +72,55 @@ const NODES = [ function historySnapshot( nodes: ConversationSnapshot['nodes'], - inspection: Partial = {}, -): SessionHistorySnapshot { + inspection: Partial = {}, +): ConversationSnapshot { + const trajectory: TrajectorySnapshot = { + eventNodes: nodes, + contexts: [{ id: 0, nodes }], + requests: [], + callSchemas: new Map(), + interruptedNodes: [], + partial: null, + runningCalls: [], + ...inspection, + } return { - state: 'ready', - error: null, + sessionId: SID, + views: { + get: target => target === 'trajectory' ? trajectory : undefined, + } as ConversationSnapshot['views'], + chat: EMPTY_CHAT_SNAPSHOT, + nodes, + turnTimings: new Map(), + turnEnds: new Map(), + partial: trajectory.partial, + runningCalls: trajectory.runningCalls, + pending: [], + queue: [], + running: false, + subagent: null, + composerPhase: 'active', + removed: false, + openState: 'open', + openError: null, hasMore: false, - baseSeq: nodes[0]?.seq ?? 0, - inspection: { - eventNodes: nodes, - contexts: [{ id: 0, nodes }], - requests: [], - callSchemas: new Map(), - interruptedNodes: [], - partial: null, - runningCalls: [], - ...inspection, - }, + loadingOlder: false, + promptError: null, + blank: nodes.length === 0, + lastAgentError: null, } } function standaloneHistory( - snapshot: SessionHistorySnapshot, + snapshot: ConversationSnapshot, ): Pick< ComponentProps, - 'useHistory' | 'loadHistoryTail' | 'loadOlderHistory' + 'useSession' | 'loadOlder' > { const store = createSnapshotStore(snapshot) return { - useHistory: bindSnapshotSelector(store), - loadHistoryTail: () => Promise.resolve(), - loadOlderHistory: () => Promise.resolve(false), + useSession: bindSnapshotSelector(store), + loadOlder: () => Promise.resolve(false), } } @@ -112,11 +135,8 @@ function standaloneDuration(): Pick< } function fakeSession(nodes: ConversationSnapshot['nodes']) { - const store = createSnapshotStore({ - nodes, pending: [], partial: null, - runningCalls: [] as ConversationSnapshot['runningCalls'], - }) - return { store, useSession: bindSnapshotSelector(store) as unknown as UseSession } + const store = createSnapshotStore(historySnapshot(nodes)) + return { store, useSession: bindSnapshotSelector(store) as UseSession } } /** Empty sessions-list hook; breadcrumbs therefore fall back to the raw id. */ @@ -149,16 +169,19 @@ function standaloneProps(nodes: ConversationSnapshot['nodes']): ConvViewProps { async function bench(snapshot = historySnapshot(NODES)) { const ctx = new Context() const slots = new SlotsService(ctx) - const loadHistoryTail = vi.fn((_signal: AbortSignal) => Promise.resolve()) - const loadOlderHistory = vi.fn((_signal: AbortSignal) => Promise.resolve(false)) - const historyStore = createSnapshotStore(snapshot) - const history: SessionHistoryFace = { - sessionId: SID, - getSnapshot: () => historyStore.getSnapshot(), - subscribe: listener => historyStore.subscribe(listener), - loadTail: loadHistoryTail, - loadOlder: loadOlderHistory, + const loadOlder = vi.fn(() => Promise.resolve()) + const sessionStore = createSnapshotStore(snapshot) + const session = { + getSnapshot: () => sessionStore.getSnapshot(), + subscribe: (listener: () => void) => sessionStore.subscribe(listener), + loadOlder, } + await ctx.plugin(ConversationEventRegistry).await() + await ctx.plugin(ConversationViewRegistry).await() + ctx.provide('sessions', { + binding: () => ({ session }), + }) + sessionSnapshots.set(slots, sessionStore) // The conversation entry's role: declare the ring, then seed the chat entry. slots.register({ name: 'root', @@ -167,10 +190,9 @@ async function bench(snapshot = historySnapshot(NODES)) { const chatBody = vi.fn(() =>
) slots.register( { name: 'conversation.view', id: 'chat', order: 0, label: 'Chat' } as never, chatBody as never) - ctx.provide('sessionHistory', { source: () => history }) const fiber = ctx.plugin({ inject: [...inject], apply }) await fiber.await() - return { ctx, slots, fiber, loadHistoryTail, loadOlderHistory } + return { ctx, slots, fiber, loadOlder } } /** Tab projection twin of apply's viewTabs (the render-side consumption path). */ @@ -181,13 +203,8 @@ function tabsOf(slots: SlotsService): ViewTab[] { /** Mount the strict Session header/body over the ring ledger with outlet-faithful render shares. */ function mount(slots: SlotsService, nodes: ConversationSnapshot['nodes'] = NODES) { - const sessionSnapshot = createSnapshotStore({ - running: false, removed: false, promptError: null, nodes, - pending: [], - openState: 'open' as const, hasMore: true, loadingOlder: false, - partial: null, runningCalls: [] as ConversationSnapshot['runningCalls'], - }) - const useSession = bindSnapshotSelector(sessionSnapshot) as unknown as UseSession + const sessionSnapshot = sessionSnapshots.get(slots) ?? createSnapshotStore(historySnapshot(nodes)) + const useSession = bindSnapshotSelector(sessionSnapshot) as UseSession const chat = createChatStore().create() const views = { list: () => tabsOf(slots), @@ -215,10 +232,8 @@ function mount(slots: SlotsService, nodes: ConversationSnapshot['nodes'] = NODES ? (() => { const trajectory = injected as TrajectoryViewInjected return { - loadHistoryTail: trajectory.loadHistoryTail, - loadOlderHistory: trajectory.loadOlderHistory, + loadOlder: trajectory.loadOlder, setActualDuration: trajectory.setActualDuration, - useHistory: bindSnapshotSelector(trajectory.hooks.history), useDuration: bindSnapshotSelector(trajectory.hooks.duration), } })() @@ -322,13 +337,9 @@ describe('tab switching in ConversationRoot', () => { fireEvent.click(screen.getByRole('button', { name: 'Expand turns' })) expect(screen.getByRole('row', { name: /USER/ })).toBeTruthy() expect(screen.queryByTestId('chat-body')).toBeNull() - await vi.waitFor(() => { - expect(b.loadHistoryTail).toHaveBeenCalledOnce() - }) - const signal = b.loadHistoryTail.mock.calls[0]?.[0] - expect(signal?.aborted).toBe(false) + expect(b.loadOlder).not.toHaveBeenCalled() fireEvent.click(screen.getByRole('tab', { name: 'Chat' })) - expect(signal?.aborted).toBe(true) + expect(b.loadOlder).not.toHaveBeenCalled() }) it('opens a local record inspector and switches payload tabs without opening chat details', async () => { @@ -1162,9 +1173,8 @@ describe('TrajectoryView branches', () => { Promise.resolve())} - loadOlderHistory={vi.fn(() => Promise.resolve(false))} + useSession={bindSnapshotSelector(store)} + loadOlder={vi.fn(() => Promise.resolve(false))} />, ) @@ -1196,9 +1206,8 @@ describe('TrajectoryView branches', () => { Promise.resolve())} - loadOlderHistory={vi.fn(() => Promise.resolve(false))} + useSession={bindSnapshotSelector(store)} + loadOlder={vi.fn(() => Promise.resolve(false))} />, ) const row = screen.getByRole('row', { name: /stable rewind response/ }) @@ -1225,9 +1234,8 @@ describe('TrajectoryView branches', () => { Promise.resolve())} - loadOlderHistory={vi.fn(() => Promise.resolve(false))} + useSession={bindSnapshotSelector(store)} + loadOlder={vi.fn(() => Promise.resolve(false))} />, ) fireEvent.click(screen.getByRole('row', { name: /selected current response/ })) @@ -1274,9 +1282,8 @@ describe('TrajectoryView branches', () => { Promise.resolve())} - loadOlderHistory={vi.fn(() => Promise.resolve(false))} + useSession={bindSnapshotSelector(store)} + loadOlder={vi.fn(() => Promise.resolve(false))} />, ) From c828d38f5193c775132dbc300e8bf582f23d6eb4 Mon Sep 17 00:00:00 2001 From: imccyu <276526105+imccyu@users.noreply.github.com> Date: Mon, 10 Aug 2026 18:38:50 +0800 Subject: [PATCH 22/36] refactor(client-runtime): remove legacy history fold --- .../src/client/contract/session-history.ts | 43 -- .../client/session-history/history-fold.ts | 428 ----------------- .../src/client/session-history/service.ts | 66 --- .../src/client/session-history/source.ts | 432 ------------------ .../runtime/src/client/sessions/history.ts | 121 ----- .../src/client/sessions/request-inspection.ts | 328 +------------ .../client/runtime/tests/history-fold.spec.ts | 232 ---------- .../runtime/tests/request-inspection.spec.ts | 319 ------------- .../tests/session-history-source.spec.ts | 180 -------- scripts/gen-cordis-catalog.ts | 1 - 10 files changed, 4 insertions(+), 2146 deletions(-) delete mode 100644 packages/client/runtime/src/client/contract/session-history.ts delete mode 100644 packages/client/runtime/src/client/session-history/history-fold.ts delete mode 100644 packages/client/runtime/src/client/session-history/service.ts delete mode 100644 packages/client/runtime/src/client/session-history/source.ts delete mode 100644 packages/client/runtime/src/client/sessions/history.ts delete mode 100644 packages/client/runtime/tests/history-fold.spec.ts delete mode 100644 packages/client/runtime/tests/request-inspection.spec.ts delete mode 100644 packages/client/runtime/tests/session-history-source.spec.ts diff --git a/packages/client/runtime/src/client/contract/session-history.ts b/packages/client/runtime/src/client/contract/session-history.ts deleted file mode 100644 index a48e89585e..0000000000 --- a/packages/client/runtime/src/client/contract/session-history.ts +++ /dev/null @@ -1,43 +0,0 @@ -import type { - RpcError, SessionId, -} from '@deepseek-ai/dsh-client-connection/client' -import type { SessionHistoryInspection } from '../sessions/history.ts' -import type { ObservableSnapshot } from './store.ts' - -/** Observable state of one independently loaded session history ledger. */ -export interface SessionHistorySnapshot { - state: 'cold' | 'loading' | 'ready' | 'error' - error: RpcError | null - hasMore: boolean - /** Absolute sequence of the first loaded raw event, or zero for an empty window. */ - baseSeq: number - inspection: SessionHistoryInspection -} - -/** Read-only history source addressed by session id. */ -export interface SessionHistoryFace - extends ObservableSnapshot { - readonly sessionId: SessionId - /** - * Load the current tail without reading older pages. - * @param signal - Consumer lifetime. - * @returns When the tail is ready or loading fails. - */ - loadTail(signal?: AbortSignal): Promise - /** - * Prepend one older page when the current window has a predecessor. - * @param signal - Consumer lifetime. - * @returns Whether the loaded window advanced. - */ - loadOlder(signal?: AbortSignal): Promise -} - -/** Runtime service resolving independent history sources. */ -export interface ISessionHistory { - /** - * Resolve the identity-stable source for a session. - * @param sessionId - Host session identity. - * @returns The source owned outside Session and SessionManager. - */ - source(sessionId: SessionId): SessionHistoryFace -} diff --git a/packages/client/runtime/src/client/session-history/history-fold.ts b/packages/client/runtime/src/client/session-history/history-fold.ts deleted file mode 100644 index 42aaa37027..0000000000 --- a/packages/client/runtime/src/client/session-history/history-fold.ts +++ /dev/null @@ -1,428 +0,0 @@ -import type { SessionEvent } from '@deepseek-ai/dsh-session/types' -import { - SurfaceManager, isSurfaceEligibleType, isSurfaceEvent, -} from '@deepseek-ai/dsh-session/surface' -import type { - HistoryEntry, ToolCallView, ToolResultView, -} from '@deepseek-ai/dsh-client-connection/client' -import type { - AssistantRequestConfig, AssistantTiming, ConversationNode, - PartialAssistant, RunningToolCall, -} from '../sessions/conversation.ts' -import { toAssistantBlocks } from '../sessions/conversation.ts' -import { contextForm, contextProvenance } from '../sessions/context-provenance.ts' -import { SteeringHistory } from '../sessions/steering-history.ts' -import type { - ConversationContext, ConversationContextOriginKind, -} from '../sessions/conversation-context.ts' -import type { ConversationPromptSnapshot } from '../sessions/request-inspection.ts' -import { PartialAccumulator } from '../sessions/partial.ts' -import type { AssistantStepMetadata } from '../sessions/assistant-timing.ts' -import { indexAssistantStepTiming, settledAssistantTiming } from '../sessions/assistant-timing.ts' -import { ToolCallTree } from '../sessions/tool-call-tree.ts' - -interface CallIndexEntry { - name: string - argsRaw: string - time: number - callView: ToolCallView | null -} - -interface FoldedContext { - generation: number - nodes: readonly number[] - originSeq?: number -} - -/** Immutable conversation projections derived only from the history source. */ -export interface ConversationHistoryProjection { - eventNodes: readonly ConversationNode[] - contexts: readonly ConversationContext[] - interruptedNodes: readonly ConversationNode[] - partial: PartialAssistant | null - runningCalls: readonly RunningToolCall[] -} - -function replacementCrossesWindowHead(event: SessionEvent, baseSeq: number): boolean { - if (!isSurfaceEvent(event) || event.surfaceOp === 'append') return false - return event.surfaceOp.start < baseSeq || event.surfaceOp.end < baseSeq -} - -function contextOriginKind(event: SessionEvent | undefined): ConversationContextOriginKind { - if (event?.type !== 'user/message') return 'rewrite' - const source = event.data.source - if (typeof source === 'object' && 'kind' in source && 'plugin' in source) { - if (source.plugin === 'compact') return 'compaction' - if (source.plugin === 'rewind') return 'rewind' - } - return 'rewrite' -} - -function foldContexts(events: readonly SessionEvent[]): readonly FoldedContext[] { - const replay: SessionEvent[] = [] - const originalSeqs: number[] = [] - const rebasedSeqByOriginal = new Map() - const surface = new SurfaceManager(replay) - const contexts: FoldedContext[] = [] - let generation = 0 - let originSeq: number | undefined - const originalNodes = () => surface.nodes.map((seq) => { - const original = originalSeqs[seq] - if (original === undefined) throw new Error(`rebased surface seq ${seq} has no origin`) - return original - }) - for (const event of events) { - if (!isSurfaceEvent(event)) continue - if (event.surfaceOp !== 'append') { - contexts.push({ - generation, - nodes: originalNodes(), - ...(originSeq === undefined ? {} : { originSeq }), - }) - generation++ - originSeq = event.seq - } - const rebasedSeq = replay.length - const { - sourceEventSeqs: rawSources, - ...eventWithoutSources - } = event as SessionEvent & { sourceEventSeqs?: readonly number[] } - const mappedSourceEventSeqs = rawSources?.flatMap((seq) => { - const rebased = rebasedSeqByOriginal.get(seq) - return rebased === undefined ? [] : [rebased] - }) - const sourceEventSeqs = mappedSourceEventSeqs?.length === 0 - ? undefined - : mappedSourceEventSeqs - const surfaceOp = event.surfaceOp === 'append' - ? event.surfaceOp - : { - ...event.surfaceOp, - start: rebasedSeqByOriginal.get(event.surfaceOp.start) ?? event.surfaceOp.start, - end: rebasedSeqByOriginal.get(event.surfaceOp.end) ?? event.surfaceOp.end, - } - originalSeqs.push(event.seq) - rebasedSeqByOriginal.set(event.seq, rebasedSeq) - replay.push({ - ...eventWithoutSources, - seq: rebasedSeq, - surfaceOp, - ...(sourceEventSeqs === undefined ? {} : { sourceEventSeqs }), - } as SessionEvent) - } - contexts.push({ - generation, - nodes: originalNodes(), - ...(originSeq === undefined ? {} : { originSeq }), - }) - return contexts -} - -// History projection owns its node mapping so Chat's live adapter remains free -// of inspection metadata and lifecycle coupling. -/* jscpd:ignore-start */ -function materializeNode( - event: SessionEvent, - callIndex: ReadonlyMap, - resultView: ToolResultView | null, - assistantTiming: AssistantTiming | undefined, - requestConfig: AssistantRequestConfig | undefined, - steering: boolean, -): ConversationNode { - switch (event.type) { - case 'user/message': - if (event.data.source.kind !== 'user') { - return { - kind: 'context', seq: event.seq, time: event.time, - content: event.data.content, source: event.data.source, - provenance: contextProvenance(event.data.source), - form: contextForm(event.data.source), - } - } - if (steering) { - return { - kind: 'steering', messageId: event.data.id, - seq: event.seq, time: event.time, - content: event.data.content, source: event.data.source, - } - } - return { - kind: 'user', seq: event.seq, time: event.time, - content: event.data.content, source: event.data.source, - } - case 'assistant/message': - return { - kind: 'assistant', seq: event.seq, time: event.time, - turn: event.data.turn, step: event.data.step, - blocks: toAssistantBlocks(event.data.message.content), usage: event.data.usage, - provenance: { - provider: event.data.message.source.provider, - model: event.data.message.source.model, - }, - ...(requestConfig === undefined ? {} : { requestConfig }), - ...(assistantTiming === undefined ? {} : { timing: assistantTiming }), - } - case 'tool/result': { - const result = event.data.message.content[0] - const callId = String(event.data.message.source.callId) - const call = callIndex.get(callId) - return { - kind: 'tool-result', seq: event.seq, time: event.time, - callId, - call: call === undefined ? null : { name: call.name, argsRaw: call.argsRaw }, - callTime: call?.time ?? null, - content: result.content, isError: result.isError === true, - ...(event.data.error === undefined ? {} : { error: event.data.error }), - meta: event.data.meta, - callView: call?.callView ?? null, - resultView, - subCalls: [], - } - } - default: - return { - kind: 'unknown', seq: event.seq, time: event.time, - type: event.type, data: (event as { data?: unknown }).data, - } - } -} -/* jscpd:ignore-end */ - -interface TransientProjection extends Pick< - ConversationHistoryProjection, - 'interruptedNodes' | 'partial' | 'runningCalls' -> { - toolCallTree: ToolCallTree -} - -function projectTransient(entries: readonly HistoryEntry[]): TransientProjection { - let partial: PartialAccumulator | null = null - const openCalls = new Map() - const interruptedNodes: ConversationNode[] = [] - const toolCallTree = new ToolCallTree() - - for (const entry of entries) { - const { event } = entry - if (toolCallTree.apply(event)) continue - switch (event.type) { - case 'assistant/chunk': { - const { turn, step, chunk } = event.data - if (partial === null || partial.turn !== turn || partial.step !== step) { - partial = new PartialAccumulator(turn, step) - } - partial.push(chunk) - break - } - case 'assistant/message': - if (partial?.turn === event.data.turn && partial.step === event.data.step) partial = null - break - case 'tool/call': - // History reconstructs its own in-flight index; this intentionally - // mirrors the published Chat node shape, not Chat's mutable state. - /* jscpd:ignore-start */ - openCalls.set(String(event.data.callId), { - callId: String(event.data.callId), - name: event.data.name, - argsRaw: event.data.arguments, - turn: event.data.turn, - step: event.data.step, - time: event.time, - callView: entry.view?.for === 'call' ? entry.view.view : null, - subCalls: [], - }) - /* jscpd:ignore-end */ - break - case 'tool/result': - openCalls.delete(String(event.data.message.source.callId)) - break - case 'turn/end': { - if (partial !== null && partial.turn === event.data.turn) { - const { blocks } = partial.toPartial() - const visible = blocks.some(block => - block.kind === 'text' || block.kind === 'reasoning' ? block.text !== '' : true) - if (visible) { - interruptedNodes.push({ - kind: 'assistant', seq: event.seq - 0.9, time: event.time, - turn: partial.turn, step: partial.step, blocks, interrupted: true, - }) - } - partial = null - } - let callOffset = 0 - for (const [callId, call] of openCalls) { - if (call.turn !== event.data.turn) continue - openCalls.delete(callId) - // Interrupted terminal nodes are reconstructed independently so a - // Trajectory replay cannot observe Session's frozen-node lifecycle. - /* jscpd:ignore-start */ - interruptedNodes.push({ - kind: 'tool-result', seq: event.seq - 0.8 + callOffset++ * 0.01, - time: event.time, - callId, - call: { name: call.name, argsRaw: call.argsRaw }, - callTime: call.time, - content: [], - isError: true, - error: { name: 'Interrupted', code: 'interrupted' }, - callView: call.callView, - resultView: null, - subCalls: [], - }) - /* jscpd:ignore-end */ - } - break - } - default: - break - } - } - - return { - interruptedNodes, - partial: partial?.toPartial() ?? null, - runningCalls: [...openCalls.values()], - toolCallTree, - } -} - -/** - * Project one immutable history ledger without reading or mutating Chat state. - * @param entries - Contiguous history entries in sequence order. - * @returns Event order, context lineage, and transient tail state. - */ -export function projectConversationHistory( - entries: readonly HistoryEntry[], -): ConversationHistoryProjection { - const events = entries.map(entry => entry.event) - const steeringHistory = new SteeringHistory() - const steeringSeqs = new Set() - for (const event of events) { - if (steeringHistory.apply(event)) steeringSeqs.add(event.seq) - } - const baseSeq = events[0]?.seq ?? 0 - const eventsBySeq = new Map(events.map(event => [event.seq, event])) - const callIndex = new Map() - const resultViews = new Map() - const assistantSteps = new Map() - const assistantTimings = new Map() - const assistantRequestConfigs = new Map() - const promptsByContext = new Map() - let activeRequestConfig: AssistantRequestConfig | undefined - let activePrompt: ConversationPromptSnapshot | undefined - let contextGeneration = 0 - - for (const [index, event] of events.entries()) { - const view = entries[index]?.view - if (event.type === 'tool/call') { - callIndex.set(String(event.data.callId), { - name: event.data.name, - argsRaw: event.data.arguments, - time: event.time, - callView: view?.for === 'call' ? view.view : null, - }) - } else if (event.type === 'tool/result' && view?.for === 'result') { - resultViews.set(event.seq, view.view) - } - if (isSurfaceEvent(event) && event.surfaceOp !== 'append') { - contextGeneration++ - if (activePrompt !== undefined) promptsByContext.set(contextGeneration, activePrompt) - } - indexAssistantStepTiming(assistantSteps, event) - if (event.type === 'request/header') { - activeRequestConfig = event.data.header.config - activePrompt = { - config: event.data.header.config, - system: event.data.header.system ?? '', - tools: event.data.header.tools ?? [], - } - promptsByContext.set(contextGeneration, activePrompt) - } else if (event.type === 'assistant/message') { - assistantTimings.set( - event.seq, - settledAssistantTiming(assistantSteps, event.data.turn, event.data.step, event.time), - ) - if (activeRequestConfig !== undefined) { - assistantRequestConfigs.set(event.seq, activeRequestConfig) - } - } - } - - const nodeCache = new Map() - const materialize = (seq: number): ConversationNode | undefined => { - const cached = nodeCache.get(seq) - if (cached !== undefined) return cached - const event = eventsBySeq.get(seq) - if (event === undefined || !isSurfaceEligibleType(event.type)) return - const node = materializeNode( - event, - callIndex, - resultViews.get(seq) ?? null, - assistantTimings.get(seq), - assistantRequestConfigs.get(seq), - steeringSeqs.has(seq), - ) - nodeCache.set(seq, node) - return node - } - const eventNodes = events.flatMap((event) => { - const node = materialize(event.seq) - return node === undefined ? [] : [node] - }) - - let contexts: readonly ConversationContext[] - if (events.some(event => replacementCrossesWindowHead(event, baseSeq))) { - contexts = [{ - id: 0, - ...(activePrompt === undefined ? {} : { prompt: activePrompt }), - nodes: eventNodes, - }] - } else { - try { - contexts = foldContexts(events).map((context): ConversationContext => { - const nodes = context.nodes.flatMap((seq) => { - const node = materialize(seq) - return node === undefined ? [] : [node] - }) - const prompt = promptsByContext.get(context.generation) - if (context.originSeq === undefined) { - return { - id: context.generation, - ...(prompt === undefined ? {} : { prompt }), - nodes, - } - } - const originEvent = eventsBySeq.get(context.originSeq) - return { - id: context.generation, - parentId: context.generation - 1, - origin: contextOriginKind(originEvent), - originSeq: context.originSeq, - ...(originEvent === undefined ? {} : { createdAt: originEvent.time }), - ...(prompt === undefined ? {} : { prompt }), - nodes, - } - }) - } catch (error) { - console.error('[web-runtime] history surface fold failed, using event order:', error) - contexts = [{ - id: 0, - ...(activePrompt === undefined ? {} : { prompt: activePrompt }), - nodes: eventNodes, - }] - } - } - - const transient = projectTransient(entries) - const projectedEventNodes = transient.toolCallTree.projectNodes(eventNodes) - const projectedContexts = contexts.map((context): ConversationContext => { - const nodes = transient.toolCallTree.projectNodes(context.nodes) - return nodes === context.nodes ? context : { ...context, nodes } - }) - return { - eventNodes: projectedEventNodes, - contexts: projectedContexts, - interruptedNodes: transient.toolCallTree.projectNodes(transient.interruptedNodes), - partial: transient.partial, - runningCalls: transient.toolCallTree.projectRunningCalls(transient.runningCalls), - } -} diff --git a/packages/client/runtime/src/client/session-history/service.ts b/packages/client/runtime/src/client/session-history/service.ts deleted file mode 100644 index 4705b6566d..0000000000 --- a/packages/client/runtime/src/client/session-history/service.ts +++ /dev/null @@ -1,66 +0,0 @@ -import type { Context } from '@deepseek-ai/cordis' -import type { - HostFrame, IApiClient, MuxFrame, RpcRequest, SessionId, -} from '@deepseek-ai/dsh-client-connection/client' -import type { - ISessionHistory, SessionHistoryFace, -} from '../contract/session-history.ts' -import { SessionHistorySource } from './source.ts' - -/** Root registry and frame router for independent inspection histories. */ -export class SessionHistoryService implements ISessionHistory { - private readonly sources = new Map() - - /** - * @param ctx - Client root context. - * @param api - Shared wire client. - */ - constructor(ctx: Context, private readonly api: IApiClient) { - ctx.reflect.provide('sessionHistory', this, undefined) - } - - /** - * Resolve one identity-stable history source. - * @param sessionId - Host session identity. - * @returns Source independent from SessionManager. - */ - source(sessionId: SessionId): SessionHistoryFace { - let source = this.sources.get(sessionId) - if (source === undefined) { - source = new SessionHistorySource(sessionId, this.api) - this.sources.set(sessionId, source) - } - return source - } - - /** - * Route history-relevant mux frames only to an existing source. - * @param envelope - Validated mux envelope. - */ - handleMuxEnvelope(envelope: RpcRequest): void { - const frame = envelope.payload - if (frame.type === 'stream/error') return - this.sources.get(frame.sessionId)?.handleMuxFrame(frame) - } - - /** - * Drop a removed session's independent history source. - * @param envelope - Validated host envelope. - */ - handleHostEnvelope(envelope: RpcRequest): void { - const frame = envelope.payload - if (frame.type !== 'host/session-removed') return - this.sources.get(frame.sessionId)?.dispose() - this.sources.delete(frame.sessionId) - } - - /** Invalidate requests from the dead connection generation. */ - handleDisconnected(): void { - for (const source of this.sources.values()) source.handleDisconnected() - } - - /** Rebuild every previously activated source from the new generation. */ - handleConnected(): void { - for (const source of this.sources.values()) source.resync() - } -} diff --git a/packages/client/runtime/src/client/session-history/source.ts b/packages/client/runtime/src/client/session-history/source.ts deleted file mode 100644 index 44e760b2b2..0000000000 --- a/packages/client/runtime/src/client/session-history/source.ts +++ /dev/null @@ -1,432 +0,0 @@ -import type { - HistoryEntry, IApiClient, MuxFrame, RpcError, SessionId, -} from '@deepseek-ai/dsh-client-connection/client' -import type { SessionEvent } from '@deepseek-ai/dsh-session/types' -import { transportError } from '@deepseek-ai/dsh-host-apiproxy/api' -import type { - SessionHistoryFace, SessionHistorySnapshot, -} from '../contract/session-history.ts' -import { - compactHistoryInspectionEntries, createHistoryInspection, -} from '../sessions/history.ts' -import { Notifier } from '../sessions/notifier.ts' -import { isVisibleAssistantChunk, PartialAccumulator } from '../sessions/partial.ts' - -const HISTORY_PAGE_MESSAGES = 50 - -function isAborted(signal: AbortSignal | undefined): boolean { - return signal?.aborted === true -} - -/** Independent raw-history owner used only by inspection consumers. */ -export class SessionHistorySource implements SessionHistoryFace { - private entries: HistoryEntry[] = [] - private inspectionEntries: readonly HistoryEntry[] = [] - private baseSeq = 0 - private hasMore = false - private state: SessionHistorySnapshot['state'] = 'cold' - private error: RpcError | null = null - private generation = 0 - private persistentConsumer = false - private readonly consumerSignals = new Set() - private openPromise: Promise | null = null - private olderPromise: Promise | null = null - private stitching = false - private liveBuffer: HistoryEntry[] = [] - private subscribedLastSeq: number | null = null - private inspectionCache: { - entries: readonly HistoryEntry[] - value: SessionHistorySnapshot['inspection'] - } | null = null - private streamPublishToken: object | null = null - private streamPartial: PartialAccumulator | null = null - private snapshotCache: SessionHistorySnapshot - private readonly notifier = new Notifier(() => { - this.snapshotCache = this.buildSnapshot() - }) - - /** - * @param sessionId - Host session identity. - * @param api - Shared wire client. - */ - constructor( - readonly sessionId: SessionId, - private readonly api: IApiClient, - ) { - this.snapshotCache = this.buildSnapshot() - } - - /** - * Subscribe to ledger changes. - * @param listener - Change callback. - * @returns Unsubscribe function. - */ - subscribe(listener: () => void): () => void { - return this.notifier.subscribe(listener) - } - - /** - * Read the cached ledger snapshot. - * @returns Stable snapshot until the source changes. - */ - getSnapshot(): SessionHistorySnapshot { - this.notifier.ensureFresh() - return this.snapshotCache - } - - /** - * Load the current tail without reading older pages. - * @param signal - Consumer lifetime. - * @returns When the tail is ready or loading fails. - */ - async loadTail(signal?: AbortSignal): Promise { - if (isAborted(signal)) return - this.trackConsumer(signal) - await this.open() - } - - /** - * Prepend one older page when the current window has a predecessor. - * @param signal - Consumer lifetime. - * @returns Whether the loaded window advanced. - */ - async loadOlder(signal?: AbortSignal): Promise { - if (isAborted(signal)) return false - this.trackConsumer(signal) - await this.open() - if (isAborted(signal)) return false - const previousBaseSeq = this.baseSeq - await this.loadOlderPage() - return this.baseSeq !== previousBaseSeq - } - - /** - * Route a relevant mux frame without involving the Chat session. - * @param frame - Session-addressed frame. - */ - handleMuxFrame(frame: MuxFrame): void { - if (frame.type === 'session/subscribed') { - this.subscribedLastSeq = frame.lastSeq - return - } - if (frame.type !== 'session/event') return - this.acceptLive({ event: frame.event, ...(frame.view === undefined ? {} : { view: frame.view }) }) - } - - /** Invalidate dead-generation requests while retaining the last readable snapshot. */ - handleDisconnected(): void { - this.generation++ - this.openPromise = null - this.olderPromise = null - this.stitching = false - this.liveBuffer = [] - this.subscribedLastSeq = null - if (this.state !== 'cold') { - this.state = 'cold' - this.error = null - this.publishDirtyNow() - } - } - - /** Rebuild an activated ledger from the new connection generation. */ - resync(): void { - if (!this.hasConsumer()) return - this.generation++ - this.openPromise = null - this.olderPromise = null - this.stitching = false - this.liveBuffer = [] - this.subscribedLastSeq = null - this.entries = [] - this.inspectionEntries = [] - this.baseSeq = 0 - this.hasMore = false - this.state = 'cold' - this.error = null - this.publishDirtyNow() - void this.open() - } - - /** Stop future refresh work after the host removes the session. */ - dispose(): void { - this.persistentConsumer = false - this.consumerSignals.clear() - this.generation++ - this.openPromise = null - this.olderPromise = null - this.liveBuffer = [] - this.streamPublishToken = null - this.streamPartial = null - } - - private open(): Promise { - if (this.state === 'ready') return Promise.resolve() - if (this.openPromise !== null) return this.openPromise - const generation = this.generation - const operation = this.doOpen(generation) - const settled = operation.finally(() => { - if (this.openPromise === settled) this.openPromise = null - }) - this.openPromise = settled - return settled - } - - private trackConsumer(signal: AbortSignal | undefined): void { - if (signal === undefined) { - this.persistentConsumer = true - return - } - if (this.consumerSignals.has(signal)) return - this.consumerSignals.add(signal) - signal.addEventListener('abort', () => { - this.consumerSignals.delete(signal) - }, { once: true }) - } - - private hasConsumer(): boolean { - return this.persistentConsumer || this.consumerSignals.size > 0 - } - - private async doOpen(generation: number): Promise { - this.state = 'loading' - this.error = null - this.publishDirtyNow() - try { - let { result } = await this.api.sessions.history({ - sessionId: this.sessionId, - maxMessages: HISTORY_PAGE_MESSAGES, - }) - if (generation !== this.generation) return - if (!result.ok) { - this.state = 'error' - this.error = result.error - return - } - this.installTail(result.value.events, result.value.hasMore, true) - const tailSeq = this.tailSeq() - if ( - this.subscribedLastSeq !== null - && tailSeq !== null - && this.subscribedLastSeq > tailSeq - ) { - result = (await this.api.sessions.history({ - sessionId: this.sessionId, - maxMessages: HISTORY_PAGE_MESSAGES, - })).result - if (generation !== this.generation) return - if (result.ok) this.installTail(result.value.events, result.value.hasMore, true) - } - this.state = 'ready' - } catch (error) { - if (generation !== this.generation) return - this.state = 'error' - const folded = transportError(error) - /* v8 ignore next -- transportError always returns the error branch. */ - this.error = folded.ok ? null : folded.error - } finally { - if (generation === this.generation) this.publishDirtyNow() - } - } - - private loadOlderPage(): Promise { - if (this.olderPromise !== null) return this.olderPromise - if (this.state !== 'ready' || !this.hasMore) return Promise.resolve() - const generation = this.generation - const operation = (async () => { - try { - const { result } = await this.api.sessions.history({ - sessionId: this.sessionId, - beforeSeq: this.baseSeq, - maxMessages: HISTORY_PAGE_MESSAGES, - }) - if (generation !== this.generation || this.state !== 'ready' || !result.ok) return - const older = result.value.events - if (older.length === 0) { - this.hasMore = result.value.hasMore - return - } - const tail = older.at(-1) - if (tail === undefined || tail.event.seq + 1 !== this.baseSeq) { - console.error( - `[web-runtime] inspection history page discontinuous: tail seq ${tail?.event.seq} vs baseSeq ${this.baseSeq}`, - ) - this.hasMore = false - return - } - this.entries = [...older, ...this.entries] - this.inspectionEntries = compactHistoryInspectionEntries([...this.entries]) - this.baseSeq = older[0]?.event.seq ?? this.baseSeq - this.hasMore = result.value.hasMore - } catch (error) { - console.error('[web-runtime] inspection history paging failed:', error) - } - })() - const settled = operation.finally(() => { - if (this.olderPromise !== settled) return - this.olderPromise = null - this.publishDirtyNow() - }) - this.olderPromise = settled - return settled - } - - private installTail( - tail: readonly HistoryEntry[], - hasMore: boolean, - replace: boolean, - ): void { - if (replace) { - this.entries = [...tail] - this.hasMore = hasMore - } else { - const firstSeq = tail[0]?.event.seq - const prefix = firstSeq === undefined - ? this.entries - : this.entries.filter(entry => entry.event.seq < firstSeq) - this.entries = [...prefix, ...tail] - } - this.baseSeq = this.entries[0]?.event.seq ?? 0 - this.inspectionEntries = compactHistoryInspectionEntries([...this.entries]) - const buffered = this.liveBuffer - this.liveBuffer = [] - for (const entry of buffered) this.appendLive(entry) - this.publishDirtyNow() - } - - private acceptLive(entry: HistoryEntry): void { - if (this.state === 'loading' || this.stitching) { - this.liveBuffer.push(entry) - return - } - if (this.state !== 'ready') return - const tailSeq = this.tailSeq() - if (tailSeq !== null && entry.event.seq > tailSeq + 1) { - this.liveBuffer.push(entry) - void this.repairGap() - return - } - if ( - entry.event.type === 'assistant/chunk' - && entry.event.data.chunk.type !== 'usage' - ) { - if (!this.appendIncrementalChunk(entry, entry.event)) return - this.publishStreamDirty() - return - } - this.appendLive(entry) - this.publishDirtyNow() - } - - private appendLive(entry: HistoryEntry): void { - const tailSeq = this.tailSeq() - if (tailSeq !== null && entry.event.seq <= tailSeq) return - this.entries.push(entry) - this.inspectionEntries = [...this.inspectionEntries, entry] - if (entry.event.type === 'assistant/message') { - this.inspectionEntries = compactHistoryInspectionEntries(this.inspectionEntries) - } - } - - /** Append a chunk against the cached finalized projection; false means no visible publish. */ - private appendIncrementalChunk( - entry: HistoryEntry, - event: SessionEvent<'assistant/chunk'>, - ): boolean { - const { turn, step, chunk } = event.data - if (!isVisibleAssistantChunk(chunk.type)) { - const inspection = this.currentInspection() - this.appendLive(entry) - this.inspectionCache = { entries: this.inspectionEntries, value: inspection } - return false - } - const base = this.currentInspection() - if ( - this.streamPartial === null - || this.streamPartial.turn !== turn - || this.streamPartial.step !== step - ) { - const current = base.partial - this.streamPartial = new PartialAccumulator( - turn, - step, - current?.turn === turn && current.step === step ? current.blocks : [], - ) - } - this.streamPartial.push(chunk) - this.appendLive(entry) - this.inspectionCache = { - entries: this.inspectionEntries, - value: { ...base, partial: this.streamPartial.toPartial() }, - } - return true - } - - /** Coalesce token-stream projection and rendering work to one publish per browser frame. */ - private publishStreamDirty(): void { - if (this.streamPublishToken !== null) return - const token = {} - this.streamPublishToken = token - const publish = () => { - if (this.streamPublishToken !== token) return - this.streamPublishToken = null - this.notifier.markDirty() - } - if (typeof globalThis.requestAnimationFrame === 'function') { - globalThis.requestAnimationFrame(publish) - } else { - queueMicrotask(publish) - } - } - - /** Publish structural changes immediately and invalidate an older scheduled stream publish. */ - private publishDirtyNow(): void { - this.streamPublishToken = null - this.streamPartial = null - this.notifier.markDirty() - } - - private async repairGap(): Promise { - if (this.stitching) return - this.stitching = true - const generation = this.generation - try { - const { result } = await this.api.sessions.history({ - sessionId: this.sessionId, - maxMessages: HISTORY_PAGE_MESSAGES, - }) - if (result.ok && generation === this.generation && this.state === 'ready') { - this.installTail(result.value.events, result.value.hasMore, false) - } - } catch (error) { - console.error('[web-runtime] inspection history gap repair failed:', error) - } finally { - if (generation === this.generation) this.stitching = false - } - } - - private tailSeq(): number | null { - return this.entries.at(-1)?.event.seq ?? null - } - - private buildSnapshot(): SessionHistorySnapshot { - return { - state: this.state, - error: this.error, - hasMore: this.hasMore, - baseSeq: this.baseSeq, - inspection: this.currentInspection(), - } - } - - /** Inspection pinned to the source's current immutable entry array. */ - private currentInspection(): SessionHistorySnapshot['inspection'] { - if (this.inspectionCache?.entries !== this.inspectionEntries) { - const entries = this.inspectionEntries - this.inspectionCache = { - entries, - value: createHistoryInspection(() => entries), - } - } - return this.inspectionCache.value - } -} diff --git a/packages/client/runtime/src/client/sessions/history.ts b/packages/client/runtime/src/client/sessions/history.ts deleted file mode 100644 index 8609481d33..0000000000 --- a/packages/client/runtime/src/client/sessions/history.ts +++ /dev/null @@ -1,121 +0,0 @@ -import type { ToolSchema } from '@deepseek-ai/dsh-llm/types' -import type { HistoryEntry } from '@deepseek-ai/dsh-client-connection/client' -import type { - ConversationNode, PartialAssistant, RunningToolCall, -} from './conversation.ts' -import type { ConversationContext } from './conversation-context.ts' -import { projectConversationHistory } from '../session-history/history-fold.ts' -import { inspectRequests, type RequestView } from './request-inspection.ts' - -function assistantStepKey(turn: number, step: number): string { - return `${turn}\u0000${step}` -} - -function isFirstTokenCandidate(entry: HistoryEntry): boolean { - const event = entry.event - if (event.type !== 'assistant/chunk') return false - switch (event.data.chunk.type) { - case 'text-delta': - case 'reasoning-delta': - return event.data.chunk.text !== '' - case 'tool-call-delta': - return event.data.chunk.argumentsDelta !== '' || event.data.chunk.name !== undefined - default: - return false - } -} - -/** Lazily derived inspection data for one immutable session-history window. */ -export interface SessionHistoryInspection { - eventNodes: readonly ConversationNode[] - contexts: readonly ConversationContext[] - requests: readonly RequestView[] - callSchemas: ReadonlyMap - interruptedNodes: readonly ConversationNode[] - partial: PartialAssistant | null - runningCalls: readonly RunningToolCall[] -} - -/** - * Remove completed-step token payloads that no inspection projection reads. - * The first visible token preserves timing, usage chunks preserve accounting, - * and unfinished steps retain every chunk for live or interrupted content. - * @param entries - Contiguous raw history entries in sequence order. - * @returns A projection-equivalent, usually much smaller entry ledger. - */ -export function compactHistoryInspectionEntries( - entries: readonly HistoryEntry[], -): readonly HistoryEntry[] { - const completedSteps = new Set() - for (const { event } of entries) { - if (event.type === 'assistant/message') { - completedSteps.add(assistantStepKey(event.data.turn, event.data.step)) - } - } - - const firstTokenSteps = new Set() - const compacted: HistoryEntry[] = [] - let changed = false - for (const entry of entries) { - const event = entry.event - if (event.type !== 'assistant/chunk') { - compacted.push(entry) - continue - } - const key = assistantStepKey(event.data.turn, event.data.step) - if (!completedSteps.has(key) || event.data.chunk.type === 'usage') { - compacted.push(entry) - continue - } - if (isFirstTokenCandidate(entry) && !firstTokenSteps.has(key)) { - firstTokenSteps.add(key) - compacted.push(entry) - } else { - changed = true - } - } - return changed ? compacted : entries -} - -/** - * Create a lazy inspection projection over an immutable history window. - * Conversation consumers retain the cheap wrapper; only Trajectory snapshots - * the entries and replays event order and request lifecycle state. - * @param loadEntries - Lazily snapshots contiguous raw entries in sequence order. - * @returns Lazy, memoized inspection fields for that exact window. - */ -export function createHistoryInspection( - loadEntries: () => readonly HistoryEntry[], -): SessionHistoryInspection { - let entries: readonly HistoryEntry[] | undefined - let conversation: ReturnType | undefined - let requests: ReturnType | undefined - const historyEntries = () => entries ??= loadEntries() - const conversationProjection = () => - conversation ??= projectConversationHistory(historyEntries()) - const requestProjection = () => - requests ??= inspectRequests(historyEntries()) - return { - get eventNodes() { - return conversationProjection().eventNodes - }, - get contexts() { - return conversationProjection().contexts - }, - get interruptedNodes() { - return conversationProjection().interruptedNodes - }, - get partial() { - return conversationProjection().partial - }, - get runningCalls() { - return conversationProjection().runningCalls - }, - get requests() { - return requestProjection().requests - }, - get callSchemas() { - return requestProjection().callSchemas - }, - } -} diff --git a/packages/client/runtime/src/client/sessions/request-inspection.ts b/packages/client/runtime/src/client/sessions/request-inspection.ts index 162f34d5ff..9856bce2bc 100644 --- a/packages/client/runtime/src/client/sessions/request-inspection.ts +++ b/packages/client/runtime/src/client/sessions/request-inspection.ts @@ -1,17 +1,7 @@ -// Request-centric inspection read model. Ordinary generation and compaction -// calls share one chronological projection; presentation-specific grouping -// remains in the trajectory consumer. - -import type { ContentBlock, TokenUsage, ToolSchema } from '@deepseek-ai/dsh-llm/types' -import type { HistoryEntry } from '@deepseek-ai/dsh-client-connection/client' -import type { SessionEvent } from '@deepseek-ai/dsh-session/types' -import type {} from '@deepseek-ai/dsh-compact/types' -import type {} from '@deepseek-ai/dsh-llm-retry/types' -import type {} from '@deepseek-ai/dsh-tools/types' +import type { ContentBlock, ToolSchema } from '@deepseek-ai/dsh-llm/types' import type { AssistantProvenanceView, AssistantRequestConfig, } from './conversation.ts' -import { displayFailureMessage } from './failure-display.ts' export type { AssistantProvenanceView, AssistantRequestConfig, @@ -54,7 +44,7 @@ interface RequestViewBase { resultSeq?: number } -/** One ordinary assistant generation reconstructed from durable request events. */ +/** One ordinary assistant generation assembled from durable request events. */ interface AssistantRequestView extends RequestViewBase { purpose: 'assistant' turn: number @@ -85,321 +75,11 @@ interface CompactionRequestView extends RequestViewBase { rawOutput?: readonly ContentBlock[] } -/** One provider request reconstructed from durable request lifecycle events. */ +/** One provider request assembled from durable request lifecycle events. */ export type RequestView = AssistantRequestView | CompactionRequestView -/** Immutable request-centric projection derived from one history window. */ +/** Request data consumed by the stage-oriented Trajectory layout. */ export interface RequestInspectionSnapshot { requests: readonly RequestView[] callSchemas: ReadonlyMap } - -/** - * Derive the request-centric read model from one immutable history window. - * Compaction participates as a request purpose rather than a parallel - * top-level collection. A leading resume/change header exposes its prompt but - * cannot project a change until the preceding header enters the window. - * @param entries - Contiguous raw session history. - * @returns Requests and call-time schemas derived from that history. - */ -export function inspectRequests( - entries: readonly HistoryEntry[], -): RequestInspectionSnapshot { - const events = entries.map(entry => entry.event) - return { - requests: deriveRequests(events), - callSchemas: deriveCallSchemas(events), - } -} - -function requestKey(turn: number, step: number): string { - return `${turn}\u0000${step}` -} - -function addTokenUsage(current: unknown, next: TokenUsage): TokenUsage { - const previous = current as TokenUsage | undefined - return { - inputTokens: (previous?.inputTokens ?? 0) + next.inputTokens, - outputTokens: (previous?.outputTokens ?? 0) + next.outputTokens, - ...(previous?.cacheReadTokens === undefined && next.cacheReadTokens === undefined - ? {} - : { - cacheReadTokens: - (previous?.cacheReadTokens ?? 0) + (next.cacheReadTokens ?? 0), - }), - ...(previous?.cacheWriteTokens === undefined && next.cacheWriteTokens === undefined - ? {} - : { - cacheWriteTokens: - (previous?.cacheWriteTokens ?? 0) + (next.cacheWriteTokens ?? 0), - }), - ...(previous?.reasoningTokens === undefined && next.reasoningTokens === undefined - ? {} - : { - reasoningTokens: - (previous?.reasoningTokens ?? 0) + (next.reasoningTokens ?? 0), - }), - } -} - -function deriveCallSchemas( - events: readonly SessionEvent[], -): ReadonlyMap { - let active = new Map() - const calls = new Map() - const capture = (callId: string, name: string): void => { - if (calls.has(callId)) return - const schema = active.get(name) - if (schema !== undefined) calls.set(callId, schema) - } - for (const event of events) { - if (event.type === 'request/header') { - const tools: unknown = event.data.header.tools - active = new Map( - Array.isArray(tools) - ? (tools as ToolSchema[]).map(schema => [schema.name, schema]) - : [], - ) - continue - } - if (event.type === 'tool/call') { - capture(String(event.data.callId), event.data.name) - continue - } - if (event.type === 'tool/code-dispatch-start' || event.type === 'tool/code-dispatch') { - capture(String(event.data.subCallId), event.data.name) - } - } - return calls -} - -function promptChange( - previous: ConversationPromptSnapshot | undefined, - prompt: ConversationPromptSnapshot, - event: SessionEvent<'request/header'>, -): RequestPromptChange | undefined { - if (previous === undefined && event.data.reason !== 'initial') return - const systemChanged = previous !== undefined && previous.system !== prompt.system - const toolsChanged = previous !== undefined - && JSON.stringify(previous.tools) !== JSON.stringify(prompt.tools) - if (previous !== undefined && !systemChanged && !toolsChanged) return - return { - seq: event.seq, - time: event.time, - kind: previous === undefined - ? 'initial' - : systemChanged && toolsChanged - ? 'system-and-tools' - : systemChanged - ? 'system' - : 'tools', - ...(previous === undefined ? {} : { previous }), - } -} - -/** Project ordinary and compaction provider calls into one chronological request stream. */ -function deriveRequests(events: readonly SessionEvent[]): readonly RequestView[] { - const requests: RequestView[] = [] - const ordinaryByStep = new Map() - const lastStepByTurn = new Map() - let activeStep: string | undefined - let activePrompt: ConversationPromptSnapshot | undefined - let activeCompaction: number | undefined - - const updateAssistant = ( - index: number | undefined, - change: Partial>, - ): void => { - if (index === undefined) return - const request = requests[index] - if (request?.purpose === 'assistant') requests[index] = { ...request, ...change } - } - const updateCompaction = ( - index: number | undefined, - change: Partial>, - ): void => { - if (index === undefined) return - const request = requests[index] - if (request?.purpose === 'compaction') requests[index] = { ...request, ...change } - } - - for (const sourceEvent of events) { - if (sourceEvent.type === 'step/start') { - const { turn, step } = sourceEvent.data - const key = requestKey(turn, step) - ordinaryByStep.set(key, requests.length) - lastStepByTurn.set(turn, key) - requests.push({ - purpose: 'assistant', - startSeq: sourceEvent.seq, - turn, - step, - startedAt: sourceEvent.time, - completedAt: null, - status: 'running', - ...(activePrompt === undefined - ? {} - : { prompt: activePrompt, requestConfig: activePrompt.config }), - }) - activeStep = key - continue - } - if (sourceEvent.type === 'request/header') { - const tools: unknown = sourceEvent.data.header.tools - const prompt: ConversationPromptSnapshot = { - config: sourceEvent.data.header.config, - system: sourceEvent.data.header.system ?? '', - tools: Array.isArray(tools) ? tools as ToolSchema[] : [], - } - const change = promptChange(activePrompt, prompt, sourceEvent) - activePrompt = prompt - updateAssistant(activeStep === undefined ? undefined : ordinaryByStep.get(activeStep), { - prompt, - requestConfig: prompt.config, - ...(change === undefined ? {} : { promptChange: change }), - }) - continue - } - if ( - sourceEvent.type === 'assistant/chunk' - && sourceEvent.data.chunk.type === 'usage' - ) { - const index = ordinaryByStep.get( - requestKey(sourceEvent.data.turn, sourceEvent.data.step), - ) - const request = index === undefined ? undefined : requests[index] - updateAssistant(index, { - usage: addTokenUsage( - request?.purpose === 'assistant' ? request.usage : undefined, - sourceEvent.data.chunk.usage, - ), - }) - continue - } - if (sourceEvent.type === 'assistant/message') { - const index = ordinaryByStep.get( - requestKey(sourceEvent.data.turn, sourceEvent.data.step), - ) - const request = index === undefined ? undefined : requests[index] - updateAssistant(index, { - completedAt: sourceEvent.time, - status: 'complete', - resultSeq: sourceEvent.seq, - provenance: { - provider: sourceEvent.data.message.source.provider, - model: sourceEvent.data.message.source.model, - }, - ...(request?.purpose === 'assistant' - && request.usage !== undefined - || sourceEvent.data.usage === undefined - ? {} - : { usage: sourceEvent.data.usage }), - }) - continue - } - if (sourceEvent.type === 'step/end') { - const key = requestKey(sourceEvent.data.turn, sourceEvent.data.step) - const index = ordinaryByStep.get(key) - const request = index === undefined ? undefined : requests[index] - if (request?.purpose === 'assistant' && request.status === 'running') { - updateAssistant(index, { - completedAt: sourceEvent.time, - status: 'error', - }) - } - if (activeStep === key) activeStep = undefined - continue - } - if (sourceEvent.type === 'llm/retry') { - const data = sourceEvent.data - updateAssistant(ordinaryByStep.get(requestKey(data.turn, data.step)), { - status: 'error', - error: displayFailureMessage(data.failure), - retry: data.retry, - ...data.mode === 'normal' ? { maxRetries: data.maxRetries } : {}, - retryDelayMs: data.delayMs, - }) - continue - } - if (sourceEvent.type === 'turn/end') { - const lastStep = lastStepByTurn.get(sourceEvent.data.turn) - if (sourceEvent.data.reason.kind === 'error') { - updateAssistant(lastStep === undefined ? undefined : ordinaryByStep.get(lastStep), { - status: 'error', - error: displayFailureMessage(sourceEvent.data.reason.error), - }) - } - lastStepByTurn.delete(sourceEvent.data.turn) - continue - } - - if (sourceEvent.type === 'session/end-seed' && activeCompaction !== undefined) { - updateCompaction(activeCompaction, { - completedAt: sourceEvent.time, - status: 'error', - error: 'Compaction was interrupted before completion.', - }) - activeCompaction = undefined - continue - } - if (sourceEvent.type === 'compact/start') { - activeCompaction = requests.length - requests.push({ - purpose: 'compaction', - startSeq: sourceEvent.seq, - turn: sourceEvent.data.turn, - step: 0, - startedAt: sourceEvent.time, - completedAt: null, - status: 'running', - }) - continue - } - if (sourceEvent.type === 'compact/summary' && activeCompaction !== undefined) { - const data = sourceEvent.data - updateCompaction(activeCompaction, { - resultSeq: sourceEvent.seq, - summary: data.summary, - ...(data.rawOutput === undefined ? {} : { rawOutput: data.rawOutput }), - provenance: { - provider: data.provider, - model: data.model, - }, - requestConfig: { - provider: data.provider, - model: data.model, - purpose: 'compaction', - ...(data.maxTokens === undefined ? {} : { maxTokens: data.maxTokens }), - }, - ...(data.usage === undefined ? {} : { usage: data.usage }), - }) - continue - } - if ( - sourceEvent.type === 'user/message' - && activeCompaction !== undefined - && isCompactionSource(sourceEvent.data.source) - ) { - updateCompaction(activeCompaction, { replacementSeq: sourceEvent.seq }) - continue - } - if (sourceEvent.type !== 'compact/end' || activeCompaction === undefined) continue - updateCompaction(activeCompaction, { - completedAt: sourceEvent.time, - status: sourceEvent.data.error === undefined ? 'complete' : 'error', - ...(sourceEvent.data.error === undefined ? {} : { error: sourceEvent.data.error }), - }) - activeCompaction = undefined - } - - return requests.sort((left, right) => left.startSeq - right.startSeq) -} - -function isCompactionSource(source: unknown): boolean { - return typeof source === 'object' - && source !== null - && 'kind' in source - && source.kind === 'plugin' - && 'plugin' in source - && source.plugin === 'compact' -} diff --git a/packages/client/runtime/tests/history-fold.spec.ts b/packages/client/runtime/tests/history-fold.spec.ts deleted file mode 100644 index 2f15bc9c92..0000000000 --- a/packages/client/runtime/tests/history-fold.spec.ts +++ /dev/null @@ -1,232 +0,0 @@ -import { createMessage, createUserMessage } from '@deepseek-ai/dsh-llm' -import type { SessionEvent } from '@deepseek-ai/dsh-session/types' -import { describe, expect, it } from 'vitest' -import { projectConversationHistory } from '../src/client/session-history/history-fold.ts' -import { compactHistoryInspectionEntries } from '../src/client/sessions/history.ts' -import { inspectRequests } from '../src/client/sessions/request-inspection.ts' -import { ev } from './event-script.ts' - -const at = (seq: number, event: Record): SessionEvent => - ({ seq, time: 1_700_000_000_000 + seq, ...event }) as unknown as SessionEvent - -describe('projectConversationHistory', () => { - it('names an injected context node from its durable source, like the live adapter', () => { - // The fold declares its own node mapping (jscpd:ignore in the source), so - // the source projection is pinned on both sides independently. - const injected = at(0, { - type: 'user/message', - surfaceOp: 'append', - data: createUserMessage({ - content: [{ type: 'text', text: '' }], - // A plugin source, because the client program does not see the host - // packages that merge richer source kinds; those arms are pinned in - // context-provenance.spec.ts. - source: { kind: 'plugin', plugin: 'dsh-tool-skill', form: 'catalog' }, - }), - }) - const { contexts } = projectConversationHistory([{ event: injected }]) - expect(contexts[contexts.length - 1]?.nodes).toMatchObject([{ - kind: 'context', - seq: 0, - provenance: { role: 'inject', label: 'dsh-tool-skill' }, - form: 'catalog', - }]) - }) - - it('projects next-step human input as durable steering', () => { - const steering = createUserMessage({ - content: [{ type: 'text', text: 'change course' }], - source: { kind: 'user' }, - }) - const events = [ - at(0, { type: 'agent/inbox/spliced', data: { - target: 'next-step', start: 0, inserted: [steering], - } }), - at(1, { type: 'agent/inbox/spliced', data: { - target: 'next-step', start: 0, removedCount: 1, inserted: [], - } }), - at(2, { type: 'user/message', surfaceOp: 'append', data: steering }), - ] - const projection = projectConversationHistory(events.map(event => ({ event }))) - expect(projection.eventNodes).toMatchObject([{ - kind: 'steering', messageId: steering.id, seq: 2, - }]) - }) - - it('projects a high-sequence history window without synthesizing its unloaded prefix', () => { - const baseSeq = 400_000 - const events = [ - ev.user(baseSeq, 'loaded tail'), - at(baseSeq + 1, { - type: 'assistant/message', - surfaceOp: { op: 'replace', start: baseSeq, end: baseSeq }, - sourceEventSeqs: [baseSeq], - data: { - turn: 80, - step: 1, - message: createMessage({ - role: 'assistant', - content: [{ type: 'text', text: 'tail summary' }], - source: { kind: 'model', provider: 'fake', model: 'fake' }, - }), - }, - }), - ] - - const projection = projectConversationHistory(events.map(event => ({ event }))) - expect(projection.eventNodes.map(node => node.seq)).toEqual([baseSeq, baseSeq + 1]) - expect(projection.contexts.map(context => ({ - originSeq: context.originSeq, - nodes: context.nodes.map(node => node.seq), - }))).toEqual([ - { originSeq: undefined, nodes: [baseSeq] }, - { originSeq: baseSeq + 1, nodes: [baseSeq + 1] }, - ]) - }) - - it('projects frozen surface generations without widening the core live surface', () => { - const events = [ - ev.user(0, 'a'), - ev.user(1, 'b'), - at(2, { - type: 'assistant/message', - surfaceOp: { op: 'replace', start: 0, end: 0 }, - sourceEventSeqs: [0], - data: { - turn: 1, - step: 1, - message: createMessage({ - role: 'assistant', - content: [{ type: 'text', text: 'summary' }], - source: { kind: 'model', provider: 'fake', model: 'fake' }, - }), - }, - }), - at(3, { - type: 'assistant/message', - surfaceOp: { op: 'replace', start: 2, end: 1 }, - sourceEventSeqs: [2, 1], - data: { - turn: 1, - step: 2, - message: createMessage({ - role: 'assistant', - content: [{ type: 'text', text: 'summary 2' }], - source: { kind: 'model', provider: 'fake', model: 'fake' }, - }), - }, - }), - ] - - expect(projectConversationHistory(events.map(event => ({ event }))).contexts.map(context => ({ - id: context.id, - parentId: context.parentId, - originSeq: context.originSeq, - nodes: context.nodes.map(node => node.seq), - }))).toEqual([ - { id: 0, parentId: undefined, originSeq: undefined, nodes: [0, 1] }, - { id: 1, parentId: 0, originSeq: 2, nodes: [2, 1] }, - { id: 2, parentId: 1, originSeq: 3, nodes: [3] }, - ]) - }) - - it('projects assistant timing and the active request header from history', () => { - const projection = projectConversationHistory([ - ev.stepStart(0, 1, 2), - at(1, { type: 'request/header', data: { - reason: 'initial', - header: { - config: { provider: 'fake', model: 'first' }, - tools: [], - }, - } }), - ev.chunkStart(2, 1, 2), - ev.chunkText(3, 1, 'token', 2), - ev.assistant(4, 1, 'done', 2), - ev.stepStart(5, 2, 1), - ev.chunkText(6, 2, 'next', 1), - ev.assistant(7, 2, 'next done', 1), - ].map(event => ({ event }))) - - expect(projection.eventNodes[0]).toMatchObject({ - kind: 'assistant', - timing: { - stepStartTime: 1_700_000_000_000, - firstTokenTime: 1_700_000_000_003, - completedTime: 1_700_000_000_004, - }, - requestConfig: { provider: 'fake', model: 'first' }, - }) - - expect(projection.eventNodes.at(-1)).toMatchObject({ - timing: { - stepStartTime: 1_700_000_000_005, - firstTokenTime: 1_700_000_000_006, - completedTime: 1_700_000_000_007, - }, - requestConfig: { provider: 'fake', model: 'first' }, - }) - }) - - it('projects nested dispatches onto settled and interrupted history calls', () => { - const projection = projectConversationHistory([ - ev.turnStart(0, 1), - ev.toolCall(1, 1, 'settled', 'run_code', '{}'), - ev.codeDispatchStart(2, 'settled', 1, 'run_code', { code: 'nested' }), - ev.codeDispatchStart(3, 'settled:code:1', 1, 'read', { path: 'a.txt' }), - ev.codeDispatch(4, 'settled:code:1', 1, 'read', { path: 'a.txt' }, 'alpha'), - ev.codeDispatch(5, 'settled', 1, 'run_code', { code: 'nested' }, 'alpha'), - ev.toolResult(6, 1, 'settled', 'done'), - ev.turnEnd(7, 1), - ev.turnStart(8, 2), - ev.toolCall(9, 2, 'interrupted', 'run_code', '{}'), - ev.codeDispatchStart(10, 'interrupted', 1, 'bash', { command: 'sleep 1' }), - ev.turnEnd(11, 2, 'aborted'), - ].map(event => ({ event }))) - - const settled = { - callId: 'settled', - subCalls: [{ - callId: 'settled:code:1', - subCalls: [{ callId: 'settled:code:1:code:1', call: { name: 'read' } }], - }], - } - expect(projection.eventNodes).toMatchObject([settled]) - expect(projection.contexts[0]?.nodes).toMatchObject([settled]) - expect(projection.interruptedNodes).toMatchObject([{ - callId: 'interrupted', - subCalls: [{ callId: 'interrupted:code:1', name: 'bash' }], - }]) - }) - - it('drops completed token payloads without changing inspection projections', () => { - const events = [ - ev.user(0, 'before'), - ev.stepStart(1, 1, 0), - ev.chunkStart(2, 1), - ev.chunkText(3, 1, ''), - ev.chunkText(4, 1, 'first'), - ev.chunkText(5, 1, ' discarded'), - at(6, { type: 'assistant/chunk', data: { - turn: 1, - step: 0, - chunk: { type: 'usage', usage: { inputTokens: 4, outputTokens: 2 } }, - } }), - ev.assistant(7, 1, 'first discarded'), - ev.compactSummary(8, 'summary', 0, 7), - ev.compactCheckpoint(9, 8, 0, 7), - ev.stepStart(10, 2, 0), - ev.chunkStart(11, 2), - ev.chunkText(12, 2, 'interrupted'), - ev.turnEnd(13, 2, 'aborted'), - ] - const raw = events.map(event => ({ event })) - const compacted = compactHistoryInspectionEntries(raw) - - expect(compacted.map(entry => entry.event.seq)).toEqual([ - 0, 1, 4, 6, 7, 8, 9, 10, 11, 12, 13, - ]) - expect(projectConversationHistory(compacted)).toEqual(projectConversationHistory(raw)) - expect(inspectRequests(compacted)).toEqual(inspectRequests(raw)) - }) -}) diff --git a/packages/client/runtime/tests/request-inspection.spec.ts b/packages/client/runtime/tests/request-inspection.spec.ts deleted file mode 100644 index 031c2f4b45..0000000000 --- a/packages/client/runtime/tests/request-inspection.spec.ts +++ /dev/null @@ -1,319 +0,0 @@ -import { describe, expect, it } from 'vitest' -import type { HistoryEntry } from '@deepseek-ai/dsh-client-connection/client' -import { createAssistantMessage, createUserMessage } from '@deepseek-ai/dsh-llm' -import type { SessionEvent } from '@deepseek-ai/dsh-session/types' -import { inspectRequests } from '../src/client/sessions/request-inspection.ts' - -const at = (seq: number, type: string, data: unknown): SessionEvent => - ({ seq, time: 1_700_000_000_000 + seq, type, data }) as SessionEvent - -const entriesOf = (events: readonly SessionEvent[]): HistoryEntry[] => - events.map(event => ({ event })) - -describe('inspectRequests', () => { - it('projects ordinary and compaction calls into one chronological request stream', () => { - const events = [ - at(0, 'step/start', { turn: 1, step: 1 }), - at(1, 'request/header', { - reason: 'initial', - header: { - config: { provider: 'fake', model: 'model' }, - system: 'system', - tools: [{ - name: 'read', - description: 'Read a file.', - parameters: { type: 'object' }, - }], - }, - }), - at(2, 'tool/call', { - turn: 1, - step: 1, - callId: 'call-1', - name: 'read', - arguments: '{}', - }), - at(3, 'assistant/message', { - turn: 1, - step: 1, - message: createAssistantMessage({ - content: [{ type: 'text', text: 'done' }], - source: { provider: 'fake', model: 'model' }, - }), - usage: { inputTokens: 5, outputTokens: 2 }, - }), - at(4, 'step/end', { turn: 1, step: 1 }), - at(5, 'compact/start', { turn: 1 }), - at(6, 'compact/summary', { - summary: [{ type: 'text', text: 'summary' }], - rawOutput: [ - { type: 'reasoning', text: 'thought' }, - { type: 'text', text: 'summary' }, - ], - provider: 'fake', - model: 'compact-model', - usage: { inputTokens: 8, outputTokens: 3 }, - }), - at(7, 'user/message', createUserMessage({ - content: [{ type: 'text', text: 'checkpoint' }], - source: { kind: 'plugin', plugin: 'compact' }, - })), - at(8, 'compact/end', { turn: 1 }), - ] - const snapshot = inspectRequests(entriesOf(events)) - expect(snapshot.requests).toMatchObject([ - { - purpose: 'assistant', - startSeq: 0, - resultSeq: 3, - status: 'complete', - prompt: { - config: { provider: 'fake', model: 'model' }, - system: 'system', - }, - promptChange: { seq: 1, kind: 'initial' }, - }, - { - purpose: 'compaction', - startSeq: 5, - resultSeq: 6, - replacementSeq: 7, - status: 'complete', - summary: [{ type: 'text', text: 'summary' }], - }, - ]) - expect(snapshot.callSchemas.get('call-1')?.name).toBe('read') - }) - - it('does not promote a truncated resume or change header to the initial prompt', () => { - for (const reason of ['resume', 'change'] as const) { - const snapshot = inspectRequests(entriesOf([ - at(10, 'step/start', { turn: 3, step: 1 }), - at(11, 'request/header', { - reason, - header: { - config: { provider: 'fake', model: 'model' }, - system: 'tail-window prompt', - }, - }), - ])) - - expect(snapshot.requests[0]).toMatchObject({ - purpose: 'assistant', - prompt: { system: 'tail-window prompt' }, - }) - expect(snapshot.requests[0]).not.toHaveProperty('promptChange') - } - }) - - it('classifies a prompt change once the preceding header is loaded', () => { - const snapshot = inspectRequests(entriesOf([ - at(0, 'step/start', { turn: 1, step: 1 }), - at(1, 'request/header', { - reason: 'initial', - header: { - config: { provider: 'fake', model: 'model' }, - system: 'before', - }, - }), - at(2, 'step/start', { turn: 1, step: 2 }), - at(3, 'request/header', { - reason: 'change', - header: { - config: { provider: 'fake', model: 'model' }, - system: 'after', - }, - }), - ])) - - expect(snapshot.requests[1]).toMatchObject({ - promptChange: { - seq: 3, - kind: 'system', - previous: { system: 'before' }, - }, - }) - }) - - it('preserves a standalone compaction owner without widening assistant turns', () => { - const snapshot = inspectRequests(entriesOf([ - at(0, 'compact/start', { turn: null }), - at(1, 'compact/summary', { - summary: [{ type: 'text', text: 'standalone summary' }], - provider: 'fake', - model: 'compact-model', - }), - at(2, 'compact/end', { turn: null }), - at(3, 'step/start', { turn: 2, step: 1 }), - ])) - - const [compaction, assistant] = snapshot.requests - expect(compaction).toMatchObject({ - purpose: 'compaction', - turn: null, - step: 0, - status: 'complete', - }) - expect(assistant).toMatchObject({ - purpose: 'assistant', - turn: 2, - step: 1, - status: 'running', - }) - if (assistant?.purpose === 'assistant') { - const turn: number = assistant.turn - expect(turn).toBe(2) - } - }) - - it('interrupts an orphaned compaction at end-seed before projecting a new attempt', () => { - const snapshot = inspectRequests(entriesOf([ - at(0, 'compact/start', { turn: null }), - at(1, 'session/end-seed', {}), - at(2, 'compact/start', { turn: null }), - at(3, 'compact/summary', { - summary: [{ type: 'text', text: 'replacement summary' }], - provider: 'fake', - model: 'compact-model', - }), - at(4, 'compact/end', { turn: null }), - ])) - - expect(snapshot.requests).toMatchObject([ - { - purpose: 'compaction', - startSeq: 0, - status: 'error', - completedAt: 1_700_000_000_001, - error: 'Compaction was interrupted before completion.', - }, - { - purpose: 'compaction', - startSeq: 2, - status: 'complete', - completedAt: 1_700_000_000_004, - summary: [{ type: 'text', text: 'replacement summary' }], - }, - ]) - }) - - it('captures schemas for nested tool dispatches from the active request header', () => { - const snapshot = inspectRequests(entriesOf([ - at(0, 'request/header', { - reason: 'initial', - header: { - config: { provider: 'fake', model: 'model' }, - tools: [{ - name: 'read', - description: 'Read a file.', - parameters: { type: 'object' }, - }], - }, - }), - at(1, 'tool/code-dispatch-start', { - parentCallId: 'parent', - subCallId: 'nested', - name: 'read', - arguments: {}, - }), - ])) - - expect(snapshot.callSchemas.get('nested')?.name).toBe('read') - }) - - it('keeps chunk-reported usage through request failure and prefers it to message fallback', () => { - const chunkUsage = { inputTokens: 21, outputTokens: 3 } - const retryUsage = { - inputTokens: 5, - outputTokens: 2, - cacheReadTokens: 8, - reasoningTokens: 1, - } - const snapshot = inspectRequests(entriesOf([ - at(0, 'step/start', { turn: 1, step: 1 }), - at(1, 'assistant/chunk', { - turn: 1, - step: 1, - chunk: { type: 'usage', usage: chunkUsage }, - }), - at(2, 'llm/retry', { - turn: 1, - step: 1, - retry: 1, - maxRetries: 2, - delayMs: 100, - failure: { message: 'rate limited' }, - }), - at(3, 'assistant/chunk', { - turn: 1, - step: 1, - chunk: { type: 'usage', usage: retryUsage }, - }), - at(4, 'assistant/message', { - turn: 1, - step: 1, - message: createAssistantMessage({ - content: [{ type: 'text', text: 'recovered' }], - source: { provider: 'fake', model: 'model' }, - }), - usage: { inputTokens: 1, outputTokens: 1 }, - }), - ])) - - expect(snapshot.requests[0]).toMatchObject({ - status: 'complete', - usage: { - inputTokens: 26, - outputTokens: 5, - cacheReadTokens: 8, - reasoningTokens: 1, - }, - }) - }) - - it('keeps provider credential fragments out of projected request errors', () => { - const snapshot = inspectRequests(entriesOf([ - at(0, 'step/start', { turn: 1, step: 1 }), - at(1, 'turn/end', { - turn: 1, reason: { kind: 'error', error: { - code: 'AUTH', - message: 'Authentication Fails, Your api key: sk-preview-secret is invalid', - }, - }, - }), - at(2, 'step/start', { turn: 2, step: 1 }), - at(3, 'turn/end', { - turn: 2, reason: { kind: 'error', error: { message: 'plugin exploded', code: 'UNKNOWN' } }, - }), - ])) - - expect(snapshot.requests).toMatchObject([ - { status: 'error', error: 'API key is invalid' }, - { status: 'error', error: 'plugin exploded' }, - ]) - }) - - it('treats a scrubbed durable-fixture tool catalog as unavailable', () => { - const snapshot = inspectRequests(entriesOf([ - at(0, 'step/start', { turn: 1, step: 1 }), - at(1, 'request/header', { - reason: 'initial', - header: { - config: { provider: 'fake', model: 'model' }, - tools: '{{tools}}', - }, - }), - at(2, 'tool/call', { - turn: 1, - step: 1, - callId: 'call-1', - name: 'read', - arguments: '{}', - }), - ])) - - expect(snapshot.callSchemas).toEqual(new Map()) - const [request] = snapshot.requests - expect(request?.purpose === 'assistant' ? request.prompt?.tools : undefined).toEqual([]) - }) -}) diff --git a/packages/client/runtime/tests/session-history-source.spec.ts b/packages/client/runtime/tests/session-history-source.spec.ts deleted file mode 100644 index 2bc0aa87af..0000000000 --- a/packages/client/runtime/tests/session-history-source.spec.ts +++ /dev/null @@ -1,180 +0,0 @@ -import { afterEach, describe, expect, it, vi } from 'vitest' -import type { SessionEvent } from '@deepseek-ai/dsh-session/types' -import type { SessionId } from '@deepseek-ai/dsh-client-connection/client' -import { SessionHistorySource } from '../src/client/session-history/source.ts' -import { FakeApiClient, deferred, err, ok } from './fake-api.ts' -import { entries, ev, plainTurn } from './event-script.ts' - -const SID = 'history-s1' as SessionId - -afterEach(() => { - vi.unstubAllGlobals() -}) - -function histResponse(events: SessionEvent[], hasMore = false) { - return Promise.resolve(ok({ events: entries(events) as never[], hasMore })) -} - -describe('SessionHistorySource', () => { - it('loads the tail first and prepends older pages on demand', async () => { - const pages = [ - plainTurn(0, 0, '最早问', '最早答'), - plainTurn(6, 1, '中间问', '中间答'), - plainTurn(12, 2, '最新问', '最新答'), - ] - const api = new FakeApiClient() - api.onHistory = (payload) => { - if (payload.beforeSeq === undefined) return histResponse(pages[2]!, true) - if (payload.beforeSeq === 12) return histResponse(pages[1]!, true) - return histResponse(pages[0]!, false) - } - const source = new SessionHistorySource(SID, api) - - await source.loadTail() - - expect(api.callsOf('session.history')).toHaveLength(1) - expect(source.getSnapshot().hasMore).toBe(true) - expect(source.getSnapshot().baseSeq).toBe(12) - expect(source.getSnapshot().inspection.eventNodes.map(node => node.seq)) - .toEqual([13, 15]) - - expect(await source.loadOlder()).toBe(true) - expect(await source.loadOlder()).toBe(true) - expect(await source.loadOlder()).toBe(false) - - expect(api.callsOf('session.history')).toHaveLength(3) - expect(source.getSnapshot().hasMore).toBe(false) - expect(source.getSnapshot().baseSeq).toBe(0) - expect(source.getSnapshot().inspection.eventNodes.map(node => node.seq)) - .toEqual([1, 3, 7, 9, 13, 15]) - }) - - it('pins a lazy inspection to the entries in its source snapshot', async () => { - const api = new FakeApiClient() - api.onHistory = () => histResponse(plainTurn(0, 0, '问', '答')) - const source = new SessionHistorySource(SID, api) - await source.loadTail() - const before = source.getSnapshot() - - source.handleMuxFrame({ - type: 'session/event', - sessionId: SID, - event: ev.user(6, 'later'), - }) - - expect(before.inspection.eventNodes.map(node => node.seq)).toEqual([1, 3]) - expect(source.getSnapshot().inspection.eventNodes.map(node => node.seq)) - .toEqual([1, 3, 6]) - }) - - it('publishes multiple assistant chunks once per browser frame', async () => { - const api = new FakeApiClient() - api.onHistory = () => histResponse(plainTurn(0, 0, '问', '答')) - const source = new SessionHistorySource(SID, api) - await source.loadTail() - const frames: FrameRequestCallback[] = [] - vi.stubGlobal('requestAnimationFrame', (callback: FrameRequestCallback) => { - frames.push(callback) - return frames.length - }) - let notifications = 0 - const unsubscribe = source.subscribe(() => { notifications++ }) - const before = source.getSnapshot().inspection - const finalizedNodes = before.eventNodes - const requests = before.requests - const contexts = before.contexts - - for (const event of [ - ev.chunkStart(6, 1), - ev.chunkText(7, 1, 'stream '), - ev.chunkText(8, 1, 'content'), - ]) { - source.handleMuxFrame({ - type: 'session/event', - sessionId: SID, - event, - }) - } - - expect(frames).toHaveLength(1) - expect(notifications).toBe(0) - frames[0]?.(0) - await Promise.resolve() - - expect(notifications).toBe(1) - const streamed = source.getSnapshot().inspection - expect(streamed.eventNodes).toBe(finalizedNodes) - expect(streamed.requests).toBe(requests) - expect(streamed.contexts).toBe(contexts) - expect(streamed.partial?.blocks).toEqual([ - { kind: 'text', text: 'stream content' }, - ]) - - source.handleMuxFrame({ - type: 'session/event', - sessionId: SID, - event: ev.chunkText(9, 1, ' then final'), - }) - source.handleMuxFrame({ - type: 'session/event', - sessionId: SID, - event: ev.assistant(10, 1, 'stream content then final'), - }) - await Promise.resolve() - - expect(notifications).toBe(2) - const finalized = source.getSnapshot().inspection - expect(finalized.eventNodes).not.toBe(finalizedNodes) - expect(finalized.partial).toBeNull() - frames[1]?.(0) - await Promise.resolve() - expect(notifications).toBe(2) - unsubscribe() - }) - - it('stops loading when an older page fails to advance', async () => { - const api = new FakeApiClient() - api.onHistory = payload => payload.beforeSeq === undefined - ? histResponse(plainTurn(6, 1, '新问', '新答'), true) - : Promise.resolve(err({ - code: 'internal', - message: 'page unavailable', - details: {}, - })) - const source = new SessionHistorySource(SID, api) - - await source.loadTail() - expect(await source.loadOlder()).toBe(false) - - expect(api.callsOf('session.history')).toHaveLength(2) - expect(source.getSnapshot().hasMore).toBe(true) - }) - - it('finishes an already started older page after consumer cancellation', async () => { - const middle = deferred>>() - const olderStarted = deferred() - const api = new FakeApiClient() - api.onHistory = (payload) => { - if (payload.beforeSeq === undefined) { - return histResponse(plainTurn(12, 2, '最新问', '最新答'), true) - } - olderStarted.resolve(undefined) - return middle.promise - } - const source = new SessionHistorySource(SID, api) - const controller = new AbortController() - await source.loadTail(controller.signal) - const complete = source.loadOlder(controller.signal) - await olderStarted.promise - controller.abort() - middle.resolve(ok({ - events: entries(plainTurn(6, 1, '中间问', '中间答')) as never[], - hasMore: true, - })) - - expect(await complete).toBe(true) - - expect(api.callsOf('session.history')).toHaveLength(2) - expect(source.getSnapshot().hasMore).toBe(true) - }) -}) diff --git a/scripts/gen-cordis-catalog.ts b/scripts/gen-cordis-catalog.ts index 79419be5ed..4a26b80c28 100644 --- a/scripts/gen-cordis-catalog.ts +++ b/scripts/gen-cordis-catalog.ts @@ -132,7 +132,6 @@ export const SERVICE_WALK_EXEMPTIONS: Record = { models: 'client-side interface-typed browser service — packages/client/ui-model/README.md owns the surface', modules: 'client-side interface-typed browser service — packages/client/modules/README.md owns the surface', remote: 'client-side interface-typed gateway accessor (ClientRemote) — packages/api/gateway/README.md owns the surface', - sessionHistory: 'client-side interface-typed browser service — packages/client/runtime/README.md owns the surface', slash: 'client-side interface-typed browser service — packages/client/ui-slash/README.md owns the surface', slots: 'client-side interface-typed browser service — packages/client/runtime/README.md owns the surface', theme: 'client-side interface-typed browser service — packages/client/ui-theme/README.md owns the surface', From a342b329e358fdb23274fb6c086d5180e8aed9a1 Mon Sep 17 00:00:00 2001 From: imccyu <276526105+imccyu@users.noreply.github.com> Date: Mon, 10 Aug 2026 19:05:23 +0800 Subject: [PATCH 23/36] docs(client): document trajectory conversation assembly --- ...lient-conversation-node-assembly.i18n.yaml | 4 +- ...08-09-client-conversation-node-assembly.md | 21 +++++----- ...09-client-conversation-node-assembly.zh.md | 21 +++++----- ...-27-trajectory-inspection-ledger.i18n.yaml | 4 +- ...2026-07-27-trajectory-inspection-ledger.md | 10 ++--- ...6-07-27-trajectory-inspection-ledger.zh.md | 10 ++--- ...b-context-source-and-steer-marks.i18n.yaml | 4 +- ...8-04-web-context-source-and-steer-marks.md | 4 +- ...4-web-context-source-and-steer-marks.zh.md | 4 +- ...6-07-24-web-gui-browser-e2e-lane.i18n.yaml | 4 +- .../2026-07-24-web-gui-browser-e2e-lane.md | 2 +- .../2026-07-24-web-gui-browser-e2e-lane.zh.md | 2 +- packages/client/runtime/README.i18n.yaml | 4 +- packages/client/runtime/README.md | 11 +++--- packages/client/runtime/README.zh.md | 11 +++--- packages/client/runtime/package.json | 1 - .../src/client/contract/conversation.ts | 2 +- .../client/sessions/conversation-assembler.ts | 2 +- .../ui-conversation/tests/chat-view.spec.tsx | 3 +- .../src/client/turn-deliverables.ts | 2 - .../tests/produced-files.spec.tsx | 2 +- .../client/ui-trajectory/README.i18n.yaml | 4 +- packages/client/ui-trajectory/README.md | 2 +- packages/client/ui-trajectory/README.zh.md | 2 +- .../client/trajectory-assistant-definition.ts | 32 +++++++++------- .../trajectory-compaction-definition.ts | 38 ++++++++++--------- .../client/trajectory-definition-common.ts | 16 +++++++- .../client/trajectory-message-definitions.ts | 32 +++++++++------- .../trajectory-request-header-definition.ts | 12 ++++-- .../src/client/trajectory-snapshot-builder.ts | 18 +++++---- .../src/client/trajectory-tool-definition.ts | 6 ++- .../client/ui-trajectory/tests/views.spec.tsx | 7 ++-- pnpm-lock.yaml | 3 -- 33 files changed, 161 insertions(+), 139 deletions(-) diff --git a/.agents/notes/implemented/architecture/2026-08-09-client-conversation-node-assembly.i18n.yaml b/.agents/notes/implemented/architecture/2026-08-09-client-conversation-node-assembly.i18n.yaml index b76951347b..1dec922826 100644 --- a/.agents/notes/implemented/architecture/2026-08-09-client-conversation-node-assembly.i18n.yaml +++ b/.agents/notes/implemented/architecture/2026-08-09-client-conversation-node-assembly.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/architecture/2026-08-09-client-conversation-node-assembly.md -2026-08-09-client-conversation-node-assembly.md: 16a39539064644e5467f701789a7e2ef1f7ff172 -2026-08-09-client-conversation-node-assembly.zh.md: 0e0fbdf8f3320393022528e6e3fe2cf0d492a1d3 +2026-08-09-client-conversation-node-assembly.md: 1d5fd20bfa8c3b370f736937d54a668ca7f19ca3 +2026-08-09-client-conversation-node-assembly.zh.md: 6f0acc448950cdedcb249ada8cfd931a21765b3e diff --git a/.agents/notes/implemented/architecture/2026-08-09-client-conversation-node-assembly.md b/.agents/notes/implemented/architecture/2026-08-09-client-conversation-node-assembly.md index 16a3953906..1d5fd20bfa 100644 --- a/.agents/notes/implemented/architecture/2026-08-09-client-conversation-node-assembly.md +++ b/.agents/notes/implemented/architecture/2026-08-09-client-conversation-node-assembly.md @@ -148,7 +148,7 @@ The Assembler verifies `node.key === context.key` and `node.target === target`. `current` lets a Definition distinguish "never materialized" from "already materialized and now hidden." Assistant retry and Turn Error suppression use it to avoid illegal Node withdrawal. -A Definition may branch by target to construct different data, while matching, Context identity, and State remain target-neutral. This change registers only the `chat` builder; Trajectory remains on its independent `session-history` fold until it gains a registered target. +A Definition owns at most one view target; state-only Definitions omit both `target` and `buildViewNode()`. Chat and Trajectory register separate business Definitions even when they recognize the same durable Event family, while the shared Assembler supplies the same matching, replay, Location, and publication mechanics to both targets. #### No generic `end()` @@ -328,7 +328,7 @@ When business logic deliberately changes a materialized Node to hidden, it leave The concrete Tool renderer remains governed by the [`ui-tool ownership decision`](2026-08-08-client-tool-presentation-ownership.md). Tool Definition supplies recursive root/subcall data, and `ui-tool` dispatches concrete presentation by the Tool-name keyed slot. -Trajectory has no registered target and does not consume the Chat Builder's legacy slice. Its activated `SessionHistoryInspection` keeps an independent history fold, while the ordinary Session snapshot no longer runs a second transcript fold. The Chat Builder retains its legacy slice for StatsLine and the top-level public compatibility fields; a future Trajectory migration does not change the Event Definition, Context, Reader, or Location contracts. +Trajectory registers its own target and business Definitions against the same Assembler and Session event window as Chat. Its target builder preserves the stage-oriented read model without consuming the Chat Builder's legacy slice or running an independent history fold. The Chat Builder retains its legacy slice for StatsLine and the top-level public compatibility fields; target-specific Definitions do not change the shared Context, Reader, or Location contracts. ## Runtime and render path @@ -339,20 +339,17 @@ Session Event window -> Context matches + State + Location -> Definition.buildLocationData(step -> turn) -> StepLocation.data / TurnLocation.data - -> Definition.buildViewNode(target = chat) - -> ChatSnapshotBuilder - -> order[] + keyed Node store + Location index + timeline - -> ChatView - -> ChatNodeSeat(key) - -> conversation.chat.node(entryKey = node.kind, hookContext = key) - -> slot-level useTurnData(businessKey) + -> Definition.buildViewNode() for its declared target + -> target View Builder + -> chat: ChatSnapshotBuilder -> ChatView -> keyed ChatNodeSeat + -> trajectory: TrajectorySnapshotBuilder -> stages/layout/table ``` ## Verification Runtime tests pin Definition lifecycle registration, exact-ID append, update-before-start collection followed by forward replay after start, prepend identity, Reader window-gap repair, transitive dependencies, Location closure, Step→Turn data phase order, Location data replacement, publication cadence, illegal withdrawal, and per-target Builders. -Conversation tests cover every built-in Definition, Assistant Step data, Turn Tail and Deliverables Turn data, Chat ordering and structural sharing, selector isolation, Assistant and Tool running-to-settled identity, nested Code Dispatch, steering, Compaction, Retry, interruption, load-older anchoring, and slot dispatch. +Conversation tests cover every built-in Chat Definition, Assistant Step data, Turn Tail and Deliverables Turn data, Chat ordering and structural sharing, selector isolation, Assistant and Tool running-to-settled identity, nested Code Dispatch, steering, Compaction, Retry, interruption, load-older anchoring, and slot dispatch. Trajectory tests cover its independently registered Message, Assistant, Tool, Compaction, Request-header, and boundary Definitions together with the preserved stage-oriented view model. Slot type/runtime tests pin required parent-provided common inject, the `hookContext` type, Hook isolation across Node contexts, stable factory/Hook identity, and the absence of business-renderer rerenders for unrelated Session publications. Existing entry-owned Observable Hook tests continue to pin the path that does not use a contextual factory. @@ -382,7 +379,7 @@ History-path tests cover complete replace, non-overlapping prepend, overlapping- **Add generic `end()`, prepared, or window-reset lifecycles.** Rejected: businesses have different completion conditions, and a pagination gap is not a business lifecycle. Business Events update State, Location close triggers replay/build, and Reader dependencies own pagination invalidation. -**Register separate Event Definitions for Chat and Trajectory.** Rejected: identity, State, and Location are target-neutral. `buildViewNode(target)` and each Builder express view differences; Trajectory's independent history fold remains until it registers its own Builder. +**Reuse one Event Definition across Chat and Trajectory by branching in `buildViewNode(target)`.** Rejected: the views require different business State and intermediate records, so a shared Definition would make each package carry the other's conditions and payloads. Separate target-owned Definitions keep those choices local while sharing the Assembler's ingestion and lifecycle contracts. **Add a generic layout model above final business Nodes.** Rejected: activity, tail candidacy, and layout enums would centralize current Chat business semantics in the engine again. Final Nodes carry renderer-required data directly and share only identity, ordering, and Location facts. @@ -406,4 +403,4 @@ Steps and Turns become stable homes for cross-business aggregates. Turn Tail and The cost is new Runtime contracts for Registry, Assembler, Location data, dependency replay, and per-target Builders, plus parent-owned common inject and per-occurrence `hookContext` in UI Slots. Definition authors must understand stable IDs, unique starts, forward replay, Step→Turn publication order, read-only Reader access, and the prohibition on Node withdrawal. -`useTurnData()` does not revoke the standard `useSession` capability from session-scoped renderers, so this boundary relies on API guidance and tests rather than capability isolation. Registry changes remain low-frequency full rebuilds; the Chat Builder still maintains a legacy slice for StatsLine and the top-level public fields, Trajectory still owns an independent history fold, and built-in Definitions currently remain centralized in `ui-conversation`. These compatibility boundaries do not return business interpretation to Session. +`useTurnData()` does not revoke the standard `useSession` capability from session-scoped renderers, so this boundary relies on API guidance and tests rather than capability isolation. Registry changes remain low-frequency full rebuilds; the Chat Builder still maintains a legacy slice for StatsLine and the top-level public fields, while Trajectory owns target-specific Definitions and a Builder over the shared Session window. Built-in Definitions remain in their respective UI packages, and these compatibility boundaries do not return business interpretation to Session. diff --git a/.agents/notes/implemented/architecture/2026-08-09-client-conversation-node-assembly.zh.md b/.agents/notes/implemented/architecture/2026-08-09-client-conversation-node-assembly.zh.md index 0e0fbdf8f3..6f0acc4489 100644 --- a/.agents/notes/implemented/architecture/2026-08-09-client-conversation-node-assembly.zh.md +++ b/.agents/notes/implemented/architecture/2026-08-09-client-conversation-node-assembly.zh.md @@ -148,7 +148,7 @@ Assembler 校验 Node `key === context.key` 且 Node `target === target`。业 `current` 让 Definition 区分“从未生成”与“已经生成后需要隐藏”。Assistant retry 和 Turn Error suppression 使用它避免非法的 Node 撤回。 -Definition 可以针对 target 分支构造不同 data,但匹配、Context identity 和 State 保持 target-neutral。本次只注册 `chat` builder;在拥有注册 target 之前,Trajectory 继续使用独立的 `session-history` fold。 +一个 Definition 最多拥有一个 view target;仅维护状态的 Definition 同时省略 `target` 与 `buildViewNode()`。即使 Chat 与 Trajectory 识别同一持久 Event 族,它们也分别注册自己的业务 Definition;共享 Assembler 则为两个 target 提供相同的匹配、replay、Location 与发布机制。 #### 不提供通用 `end()` @@ -328,7 +328,7 @@ Assistant streaming 到 final、Tool running 到 settled 只更新同一个 Seat 具体 Tool renderer 仍由 [`ui-tool ownership decision`](2026-08-08-client-tool-presentation-ownership.md) 约束。Tool Definition 只交付递归 root/subcall data,`ui-tool` 再按 Tool name keyed slot 分发具体表现。 -Trajectory 尚未注册 target,也不消费 Chat Builder 的 legacy slice。它已激活的 `SessionHistoryInspection` 继续维护独立 history fold,而普通 Session snapshot 不再运行第二套 transcript fold。Chat Builder 为 StatsLine 和顶层公共兼容字段保留 legacy slice;未来迁移 Trajectory 不改变 Event Definition、Context、Reader 或 Location 契约。 +Trajectory 针对与 Chat 相同的 Assembler 和 Session 事件窗口注册自己的 target 与业务 Definition。它的 target builder 保留 stage-oriented read model,既不消费 Chat Builder 的 legacy slice,也不运行独立 history fold。Chat Builder 为 StatsLine 和顶层公共兼容字段保留 legacy slice;target 专属 Definition 不改变共享的 Context、Reader 或 Location 契约。 ## Runtime and render path @@ -339,20 +339,17 @@ Session Event window -> Context matches + State + Location -> Definition.buildLocationData(step -> turn) -> StepLocation.data / TurnLocation.data - -> Definition.buildViewNode(target = chat) - -> ChatSnapshotBuilder - -> order[] + keyed Node store + Location index + timeline - -> ChatView - -> ChatNodeSeat(key) - -> conversation.chat.node(entryKey = node.kind, hookContext = key) - -> slot-level useTurnData(businessKey) + -> Definition.buildViewNode() for its declared target + -> target View Builder + -> chat: ChatSnapshotBuilder -> ChatView -> keyed ChatNodeSeat + -> trajectory: TrajectorySnapshotBuilder -> stages/layout/table ``` ## Verification Runtime tests 固定 Definition 生命周期注册、exact-ID append、update-before-start 收集与 start 后正序 replay、prepend identity、Reader window-gap 修复、传递依赖、Location closure、Step→Turn data phase order、Location data replacement、publication cadence、非法撤回和 per-target Builder。 -Conversation tests 覆盖全部内建 Definition、Assistant Step data、Turn Tail 与 Deliverables Turn data、Chat 排序和结构共享、selector isolation、Assistant/Tool running-to-settled identity、nested Code Dispatch、steering、Compaction、Retry、interruption、load-older anchoring 和 slot dispatch。 +Conversation tests 覆盖全部内建 Chat Definition、Assistant Step data、Turn Tail 与 Deliverables Turn data、Chat 排序和结构共享、selector isolation、Assistant/Tool running-to-settled identity、nested Code Dispatch、steering、Compaction、Retry、interruption、load-older anchoring 和 slot dispatch。Trajectory tests 则覆盖它独立注册的 Message、Assistant、Tool、Compaction、Request-header 与 boundary Definition,以及继续保留的 stage-oriented view model。 Slot type/runtime tests 固定父注册必须提供声明的 common inject、`hookContext` 类型、不同 Node context 的 Hook 隔离、factory/Hook identity 稳定,以及无关 Session publication 不重渲染业务 renderer。原 entry-owned Observable Hook 测试继续固定未使用 contextual factory 的路径。 @@ -382,7 +379,7 @@ Assembled Web snapshot、GUI 和浏览器场景覆盖真实 plugin graph。浏 **增加通用 `end()`、prepared 或 window reset 生命周期。** 拒绝:不同业务完成条件不同,分页缺口也不是业务生命周期。业务 Event 更新 State,Location close 触发 replay/build,Reader dependency 负责补页失效。 -**为 Chat 与 Trajectory 注册两套 Event Definition。** 拒绝:identity、State 和 Location 与 target 无关。视图差异由 `buildViewNode(target)` 和各自 Builder 表达;Trajectory 在注册自己的 Builder 之前继续使用独立 history fold。 +**在同一个 Event Definition 内通过 `buildViewNode(target)` 为 Chat 与 Trajectory 分支。** 拒绝:两种视图需要不同的业务 State 与中间记录,共用 Definition 会迫使每个 package 携带另一边的条件与 payload。target 自有的 Definition 把这些选择留在本地,同时复用 Assembler 的摄入与生命周期契约。 **在最终业务 Node 上再叠一层通用 layout model。** 拒绝:activity、tail candidacy 和 layout enum 会把当前 Chat 的业务语义重新集中到引擎。最终 Node 直接携带 renderer 所需 data,只共享 identity、排序和 Location 事实。 @@ -406,4 +403,4 @@ Step/Turn 成为业务间共享聚合的稳定宿主。Turn Tail 和 Deliverable 代价是 Runtime 新增 Registry、Assembler、Location data、依赖重放和 per-target Builder 契约,UI Slots 也新增 parent-owned common inject 与 per-occurrence `hookContext`。Definition 作者必须理解稳定 ID、唯一 start、正序 replay、Step→Turn 发布顺序、只读 Reader 和 Node 不撤回规则。 -`useTurnData()` 不撤销 session-scoped renderer 的标准 `useSession`,因此该边界依靠 API 引导和测试,而不是能力隔离。Registry 变化仍是低频完整 rebuild;Chat Builder 继续为 StatsLine 和顶层公共字段维护 legacy slice,Trajectory 继续拥有独立 history fold,内建 Definitions 暂时集中在 `ui-conversation`。这些是兼容边界,不把业务解释权交还给 Session。 +`useTurnData()` 不撤销 session-scoped renderer 的标准 `useSession`,因此该边界依靠 API 引导和测试,而不是能力隔离。Registry 变化仍是低频完整 rebuild;Chat Builder 继续为 StatsLine 和顶层公共字段维护 legacy slice,Trajectory 则在共享 Session 窗口上拥有 target 专属 Definition 与 Builder。内建 Definition 分别留在所属 UI package;这些兼容边界不把业务解释权交还给 Session。 diff --git a/.agents/notes/implemented/feature/2026-07-27-trajectory-inspection-ledger.i18n.yaml b/.agents/notes/implemented/feature/2026-07-27-trajectory-inspection-ledger.i18n.yaml index b73a552168..1e7284378c 100644 --- a/.agents/notes/implemented/feature/2026-07-27-trajectory-inspection-ledger.i18n.yaml +++ b/.agents/notes/implemented/feature/2026-07-27-trajectory-inspection-ledger.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-07-27-trajectory-inspection-ledger.md -2026-07-27-trajectory-inspection-ledger.md: a905e65942365c17b7513028b275288c82428221 -2026-07-27-trajectory-inspection-ledger.zh.md: a8dcfa97a89f3adc6ab540f3d6cc5020cbefb53f +2026-07-27-trajectory-inspection-ledger.md: c09213d35e984ca717d283d45259f61d413407a3 +2026-07-27-trajectory-inspection-ledger.zh.md: 9d2c615dea5b0774201118a0b0abb9862a228690 diff --git a/.agents/notes/implemented/feature/2026-07-27-trajectory-inspection-ledger.md b/.agents/notes/implemented/feature/2026-07-27-trajectory-inspection-ledger.md index a905e65942..c09213d35e 100644 --- a/.agents/notes/implemented/feature/2026-07-27-trajectory-inspection-ledger.md +++ b/.agents/notes/implemented/feature/2026-07-27-trajectory-inspection-ledger.md @@ -16,16 +16,16 @@ Trajectory has to make prose, machine payloads, token usage, timing, and nested - Event kind and content form the two stable columns. Role tags align toward the content, nested subtools receive a small indentation, and CSS truncation preserves the available preview width. Token usage and duration stay in the inspector. - Product prose uses the existing sans stack. Turn ids, token counts, durations, tool calls, raw payloads, and other machine data use the existing code stack. - Existing theme tokens own both light and dark rendering. Neutral borders and surfaces form the structure; distinct low-emphasis role hues support scanning without carrying success or failure meaning, while business blue identifies selection, links, and focus. -- The client runtime exposes a read-only history source independent from Session and SessionManager. Each activated source owns its raw entries, paging, live gap repair, and reconnect rebuild; the ordinary conversation snapshot remains the folded Chat projection. Trajectory opens the source's tail while mounted and requests one older page when the user reaches the loaded range's top, then lazily derives event order, context lineage, schema index, and Requests instead of imposing those structures on every conversation consumer. +- Session owns one contiguous Event window, paging state, live gap repair, and reconnect rebuild. Chat and Trajectory register separate business Definitions against the shared `ConversationNodeAssembler`; Trajectory reads its target snapshot from `Session.views` and requests one older Session page when the user reaches the loaded range's top. Its Definitions and target builder derive event order, context lineage, schema index, and Requests without making those structures part of the Chat snapshot. - Ordinary generation and compaction calls form one chronological Request projection, distinguished by purpose rather than separate collections. Effective prompt state and its change ride the Request that introduced them; compaction and prompt changes are not independent inspection entities. Request numbering and cumulative usage cover the loaded history window and expand as older pages arrive. - Call schemas come from the active recorded Request header. Keyless snapshot fixtures deliberately replace that catalog with the non-array `{{tools}}` token, which the durable inspection boundary treats as unavailable instead of attempting to project or fabricate schemas. - Selecting a record or Request opens an inspector inside Trajectory. Tabs and Summary sections follow the selected entity: Markdown messages expose rendered content, source fields, provider/model fields, and hierarchy views; tools add JSON payload/result and schema views; Requests add options, usage, timing, and result navigation. Scrollable Summary regions keep their scrollbar thumbs transparent until hover or `focus-within`, while retaining the scrollbar reservation and scroll behavior. Images render as media rather than serialized data. - Turn folding removes all rows after its first record and replaces them with a compact step/tool-call count; Assistant folding applies the same interaction to its tool-call descendants. Global controls fold or expand both levels. -- A long ledger initially positions the loaded tail at the bottom and mounts only the viewport's row window plus bounded overscan. Request-only separators join the next measurable virtual item, with a terminal separator retaining its own fixed clearance, so the virtualizer never owns a zero-height item. Semantic DOM-safe row keys and ARIA indexes expose identity independently from mount position. A tail with known older history virtualizes immediately even when its loaded projection is below the ordinary row threshold. Stable-key virtualizer anchoring preserves the visible item across prepends and appends; the manual scroll-height fallback applies only when completing pagination disables virtualization. Selection, timeline focus, folding, search, and bottom following address records by stable event or tool-call identity rather than requiring their DOM rows to exist. An explicit loading row covers records until initial positioning finishes and while an older page is pending. The raw window base sequence detects a prepend even when a page adds no surface-visible node. +- A long ledger initially positions the loaded tail at the bottom and mounts only the viewport's row window plus bounded overscan. Request-only separators join the next measurable virtual item, with a terminal separator retaining its own fixed clearance, so the virtualizer never owns a zero-height item. Semantic DOM-safe row keys and ARIA indexes expose identity independently from mount position. A tail with known older history virtualizes immediately even when its loaded projection is below the ordinary row threshold. Stable-key virtualizer anchoring preserves the visible item across prepends and appends; the manual scroll-height fallback applies only when completing pagination disables virtualization. Selection, timeline focus, folding, search, and bottom following address records by stable event or tool-call identity rather than requiring their DOM rows to exist. An explicit loading row covers records until initial positioning finishes and while an older Session page is pending. - The separate Waterfall tab is removed. A fixed Overview above the ledger projects every loaded record with known `startedAt` onto three semantic timing lanes using its own duration. While an older prefix remains unloaded and the viewport includes the loaded domain's start, a neutral ellipsis control covers the truncated edge and loads one earlier page without assigning unknown history a fabricated duration; hovering that control suppresses the ordinary timeline cursor. Finalized Assistant spans divide the recorded interval at the first non-empty token delta, so distinct TTFT and decoding colors retain their actual ratio; incomplete timing falls back to one Assistant color. Hovering for 500 ms exposes exact start/end, total duration, TTFT, and decoding time without relying on the browser's native tooltip delay. Dragging left or right commits an inclusive interval filter: any record whose active interval overlaps either boundary remains visible, records without known timing leave the focused ledger, and clearing the selection restores the full branch. Wheel gestures zoom the time domain. A right-button click clears the interval selection; dragging instead pans an already zoomed viewport without mutating it. The Overview keeps the full time domain while focused so the selection can be resized or cleared without losing orientation. - Live history updates retain the ledger's bottom position only while the user is already following its tail. Scrolling upward clears that follow state, so streamed chunks and newly appended records do not interrupt inspection of earlier rows. Tail following and virtualizer measurement react to row keys and heights rather than content identity, so text-only stream frames neither discard the measurement cache nor repeat a DOM scroll write. -- Token streaming reuses the finalized history inspection, layout, Request numbering, Overview projection, and search results. A frame appends only the current partial Assistant cells and searches that partial when a query is active; text and reasoning deltas do not re-fold or rescan the loaded prefix, while message completion, tool lifecycle, compaction, rewrites, and other structural events rebuild the affected projections. Before those rebuilds, the inspection ledger drops completed-step token payloads that no projection reads while retaining the first visible token for timing, every usage chunk for accounting, and every chunk from unfinished or interrupted steps; the independent history source retains the raw entries. -- History folding rebases only the loaded surface events into a compact contiguous input for the canonical surface manager, then maps its nodes back to absolute session sequences. Structural events therefore retain canonical replacement validation without replaying token chunks or materializing synthetic events for unloaded sequences. +- Token streaming updates only the matching Trajectory Assistant Context, while publication is coalesced to at most once per animation frame. The target snapshot preserves the existing stage, layout, Request numbering, Overview, and search inputs; completed Assistant State retains assembled blocks, timing, and usage rather than every raw chunk payload, while Session keeps the raw Event window. +- Each Trajectory Definition extracts a stable ID from the current Event, and the shared Assembler replays only Contexts affected by matching, Location, or Reader changes. Older Session pages prepend into the same engine window; the Trajectory target builder converts its materialized Nodes into the existing stage-oriented snapshot consumed by the ledger. - Trajectory opts into a conversation-owned composer overlay through `data-conversation-composer-overlay`. `ConversationRoot` positions the composer seat and publishes its live height; Trajectory keeps the ledger at full height and reserves that height plus 16 px inside its vertical table and inspector scrollers. Those panes adapt to the available width instead of exposing horizontal scrollbars beneath the overlay. - This local inspector remains independent from the conversation-wide Chat details column. At narrow widths it overlays the ledger and remains dismissible by keyboard or pointer. @@ -53,4 +53,4 @@ Trajectory has to make prose, machine payloads, token usage, timing, and nested ## Consequences -Trajectory shows more useful records per viewport while retaining Turn and Request orientation. Context rewrites and compactions remain inline with their surrounding history, while a rewind begins a successor branch that inherits only the retained prefix. The floating composer leaves the ledger visible to the viewport edge without covering its final rows or hiding horizontal controls. The main ledger omits token usage and duration so content receives the available width; the local inspector exposes those facts together with full payloads, provider/model and source fields, schemas, and request timing. The Overview uses recorded start/duration and token-boundary facts without fabricating live elapsed time, and its inclusive focus behavior matches the interaction users already know from Chrome DevTools Network. Tail-first paging bounds initial transport and projection work, virtualization bounds mounted row elements, incremental partial projection removes loaded-history length from ordinary token-frame work, and completed-step chunk compaction makes structural rebuilds proportional to inspection-relevant entries rather than the raw token count. Focused component tests pin tail-first paging, prepend anchoring and identity retention, the virtual window, tail following, content-only streaming without repeated scroll writes, streaming structural sharing, high-sequence window folding, timing projection, delayed detail disclosure, folding, record and interval selection, entity-specific tabs, and running/error semantics. A real-browser long-ledger contract pins stable prepend geometry, bounded mounting, top/middle/bottom reachability, and bounded scroll writes across a paced stream; the assembled Web snapshot pins the ledger, Overview timing details, composer overlay geometry, and inspector through the real client composition. +Trajectory shows more useful records per viewport while retaining Turn and Request orientation. Context rewrites and compactions remain inline with their surrounding history, while a rewind begins a successor branch that inherits only the retained prefix. The floating composer leaves the ledger visible to the viewport edge without covering its final rows or hiding horizontal controls. The main ledger omits token usage and duration so content receives the available width; the local inspector exposes those facts together with full payloads, provider/model and source fields, schemas, and request timing. The Overview uses recorded start/duration and token-boundary facts without fabricating live elapsed time, and its inclusive focus behavior matches the interaction users already know from Chrome DevTools Network. Tail-first paging bounds initial transport work, virtualization bounds mounted row elements, exact-ID dispatch avoids re-folding unrelated business Contexts, and animation-frame publication caps streaming snapshot frequency. The retained stage-oriented target builder may still perform work proportional to the loaded materialized Nodes for a publication; this migration does not add a stronger Trajectory-specific complexity guarantee. Focused component tests pin tail-first paging, prepend anchoring and identity retention, the virtual window, tail following, content-only streaming without repeated scroll writes, timing projection, delayed detail disclosure, folding, record and interval selection, entity-specific tabs, and running/error semantics. A real-browser long-ledger contract pins stable prepend geometry, bounded mounting, top/middle/bottom reachability, and bounded scroll writes across a paced stream; the assembled Web snapshot pins the ledger, Overview timing details, composer overlay geometry, and inspector through the real client composition. diff --git a/.agents/notes/implemented/feature/2026-07-27-trajectory-inspection-ledger.zh.md b/.agents/notes/implemented/feature/2026-07-27-trajectory-inspection-ledger.zh.md index a8dcfa97a8..9d2c615dea 100644 --- a/.agents/notes/implemented/feature/2026-07-27-trajectory-inspection-ledger.zh.md +++ b/.agents/notes/implemented/feature/2026-07-27-trajectory-inspection-ledger.zh.md @@ -16,16 +16,16 @@ Status: implemented - 事件类型与内容构成两个稳定列。角色标签朝内容侧对齐,嵌套子工具略微缩进,内容预览使用 CSS 截断以适应可用宽度。token 用量和耗时留在检查器中。 - 产品正文使用现有无衬线字体栈。轮次 id、token 数、耗时、工具调用、原始载荷和其他机器数据使用现有代码字体栈。 - 现有主题 token 同时负责亮色和暗色渲染。中性边框与表面构成整体结构;区分度较低的角色色帮助扫读而不表达成功或失败语义,业务蓝色则标识选择状态、链接和焦点。 -- 客户端运行时提供独立于 Session 和 SessionManager 的只读历史数据源。每个已激活的数据源自行拥有原始条目、分页、实时缺口修复和重连重建;普通会话快照仍然只是 Chat 所需的折叠投影。Trajectory 在挂载期间打开该数据源的尾部,当用户到达已加载范围顶部时请求一页更早的历史,再按需派生事件顺序、上下文谱系、schema 索引和请求,避免让所有会话消费方承担这些结构。 +- Session 统一拥有一份连续 Event 窗口、分页状态、实时缺口修复与重连重建。Chat 与 Trajectory 针对共享的 `ConversationNodeAssembler` 分别注册业务 Definition;Trajectory 从 `Session.views` 读取自己的 target snapshot,并在用户到达已加载范围顶部时请求一页更早的 Session 历史。它的 Definition 与 target builder 派生事件顺序、上下文谱系、schema 索引和请求,无须把这些结构放进 Chat snapshot。 - 普通生成调用与压缩调用形成一条按时间排序的请求投影,以用途区分而不是放入不同集合。生效的提示词状态及其变化附着在引入它们的请求上;压缩和提示词变化都不是独立检查实体。请求编号和累计用量覆盖已加载的历史窗口,并随更早页面到达而扩展。 - 调用 schema 来自当前生效且已记录的请求头。无密钥快照 fixture(测试前置数据)有意将该目录替换为非数组 token `{{tools}}`,持久化检查边界会将其视为不可用,而不是尝试投影或虚构 schema。 - 选择记录或请求后,Trajectory 内部会打开检查器,其标签页和概述区域随实体类型变化:Markdown 消息提供渲染内容、来源字段、提供方/模型字段和层级视图;工具提供 JSON 载荷/结果和 schema 视图;请求提供选项、用量、计时和结果跳转。可滚动的概述区域默认保持滚动条滑块透明,直到悬停或 `focus-within` 时才显示,同时保留滚动条预留空间和滚动行为。图片以媒体形式渲染,而不是显示为序列化数据。 - 折叠轮次时保留其第一条记录,并用紧凑的步骤数和工具调用数替换后续所有行;折叠助手时对其工具调用后代应用相同操作。全局控件会折叠或展开这两个层级。 -- 长记录表初始时将已加载尾部置于底部,只挂载视口对应的行窗口及有界的额外缓冲行。仅含请求的分隔行并入下一个具备可测高度的虚拟项,末尾分隔行则保留固定留白,因此虚拟化器不会管理零高度项。可安全用于 DOM 的语义行键与 ARIA 索引使标识不依赖挂载位置。只要已知尾部之前仍有更早历史,即使当前已加载投影低于常规行数阈值,也会立即启用虚拟化。基于稳定键的虚拟化器锚定会在向前补页和尾部追加时保留当前可见项;只有分页完成导致虚拟化停用时,才使用手动滚动高度兜底。选择、时间线聚焦、折叠、搜索和末尾跟随均按稳定的事件或工具调用标识定位,不要求对应 DOM 行已存在。初始定位完成前以及更早页面仍在等待时,明确的加载行会遮住真实记录。原始窗口的基准序号即使在一页未增加任何 surface 可见节点时,也能检测到这次向前补页。 +- 长记录表初始时将已加载尾部置于底部,只挂载视口对应的行窗口及有界的额外缓冲行。仅含请求的分隔行并入下一个具备可测高度的虚拟项,末尾分隔行则保留固定留白,因此虚拟化器不会管理零高度项。可安全用于 DOM 的语义行键与 ARIA 索引使标识不依赖挂载位置。只要已知尾部之前仍有更早历史,即使当前已加载投影低于常规行数阈值,也会立即启用虚拟化。基于稳定键的虚拟化器锚定会在向前补页和尾部追加时保留当前可见项;只有分页完成导致虚拟化停用时,才使用手动滚动高度兜底。选择、时间线聚焦、折叠、搜索和末尾跟随均按稳定的事件或工具调用标识定位,不要求对应 DOM 行已存在。初始定位完成前以及更早 Session 页面仍在等待时,明确的加载行会遮住真实记录。 - 移除独立的 waterfall(瀑布式事件)标签页。固定在记录表上方的 Overview 区域将所有 `startedAt` 已知的已加载记录按各自耗时投影到三条语义计时轨道。仍有更早前缀尚未加载且 viewport 包含已加载时间域起点时,中性的省略号控件会遮住截断边缘并加载一页更早历史,而不会为未知历史虚构耗时;悬停在该控件上会隐藏普通的时间线光标。已完成的助手时间条以首个非空 token 增量为分界,用不同颜色按真实比例表示 TTFT 与解码时间;计时不完整时退化为单一助手色。悬停 500 ms 后会显示精确起止时刻、总耗时、TTFT 和解码时间,而不依赖浏览器原生 tooltip 的延迟。向左或向右拖动会提交包含边界的区间筛选:任何活动区间与所选区间任一边界重叠的记录都会保留,计时未知的记录会从聚焦后的记录表中移除,清除选择则恢复完整分支。滚轮手势用于缩放时间域。右键单击会清除区间选择;右键拖动则只会平移已放大的 viewport,不会改变该选区。聚焦后,Overview 区域仍保留完整时间范围,以便在不失去方位的情况下调整或清除选择。 - 实时历史更新仅在用户已经跟随记录表末尾时保留底部位置。向上滚动会清除跟随状态,因此流式分块和新追加的记录不会打断对旧记录的检查。末尾跟随与虚拟化器测量仅响应行键和高度,而非内容标识,因此仅含文本的流式帧既不会丢弃测量缓存,也不会重复执行 DOM 滚动写入。 -- token 流式输出会复用已完成历史的检查结果、布局、请求编号、Overview 投影和搜索结果。每个帧只追加当前未完成助手的单元格,并在查询处于激活状态时搜索这部分内容;文本与推理(reasoning)增量不会重新折叠或扫描已加载前缀,而消息完成、工具生命周期、压缩、`rewrite` 及其他结构事件会重建受影响的投影。在这些投影重建前,检查记录表会丢弃已完成步骤中没有任何投影读取的 token 载荷,但会保留首个可见 token 用于计时、保留所有用量分片用于核算,并保留未完成或中断步骤的所有分片;独立历史数据源仍保留原始条目。 -- 历史折叠只把已加载的 surface 事件重新编号为紧凑连续的输入并交给规范 surface manager,再将其节点映射回会话绝对序号。因此,结构事件会保留规范的替换校验,而无需重放 token 分片,也不会为未加载的序号实体化合成事件。 +- token 流式输出只更新命中的 Trajectory Assistant Context,发布则合并为每个 animation frame 最多一次。target snapshot 继续提供既有 stage、layout、请求编号、Overview 与搜索输入;已完成的 Assistant State 只保留组装后的 blocks、计时与 usage,不保留每条原始 chunk payload,而 Session 继续保存原始 Event 窗口。 +- 每个 Trajectory Definition 都从当前 Event 提取稳定 ID,共享 Assembler 只 replay 因 Match、Location 或 Reader 变化而受影响的 Context。更早 Session 页面 prepend 到同一个引擎窗口;Trajectory target builder 再把已物化 Node 转换为记录表继续消费的 stage-oriented snapshot。 - Trajectory 通过 `data-conversation-composer-overlay` 启用由会话持有的 composer 浮层模式。`ConversationRoot` 负责定位 composer seat 并发布其实时高度;Trajectory 让记录表保持全高,并在记录表与检查器的纵向滚动容器内预留该高度加 16 px。这两个窗格会根据可用宽度自适应,而不会在浮层下方暴露横向滚动条。 - 此局部检查器与会话级 Chat 详情栏相互独立。在窄屏下,检查器会覆盖记录表,并且仍可通过键盘或指针关闭。 @@ -53,4 +53,4 @@ Status: implemented ## 后果 -轨迹视图在保留轮次与请求定位的同时,每个视口可以显示更多有效记录。上下文 `rewrite` 与压缩保持在周边历史中的原始位置,`rewind` 则建立仅继承保留前缀的后继分支。浮动 composer 让记录表一直显示到视口边缘,同时不会遮住最后几行,也不会隐藏横向控件。主记录表省略 token 用量和耗时,让内容获得可用宽度;局部检查器展示这些数据以及完整载荷、提供方/模型字段、来源字段、schema 和请求计时。Overview 区域使用记录的开始时间、耗时与 token 边界数据,而不虚构实时流逝时间,其包含边界的聚焦行为与用户熟悉的 Chrome DevTools Network 交互一致。尾部优先分页限制初始传输和投影工作量,虚拟化限制已挂载的行元素数量,未完成部分的增量投影让普通 token 帧的工作量不再随已加载历史长度增长,而已完成步骤的分片压缩则让结构重建的工作量与检查所需条目数量成正比,而非与原始 token 数量成正比。针对性组件测试锁定尾部优先分页、向前补页锚定与标识保持、虚拟窗口、末尾跟随、仅含内容的流式输出不会重复写入滚动位置、流式输出的结构共享、高序号窗口折叠、计时投影、延迟展示详情、折叠、记录与区间选择、实体特定标签页和运行/错误语义。真实浏览器中的长记录表约定锁定向前补页时稳定的几何位置、有界挂载、顶部/中部/底部可达性,以及按节奏进行的流式输出中有界的滚动写入;组装后的 Web 快照则通过真实客户端组合锁定记录表、Overview 计时详情、composer 浮层几何形状与检查器。 +轨迹视图在保留轮次与请求定位的同时,每个视口可以显示更多有效记录。上下文 `rewrite` 与压缩保持在周边历史中的原始位置,`rewind` 则建立仅继承保留前缀的后继分支。浮动 composer 让记录表一直显示到视口边缘,同时不会遮住最后几行,也不会隐藏横向控件。主记录表省略 token 用量和耗时,让内容获得可用宽度;局部检查器展示这些数据以及完整载荷、提供方/模型字段、来源字段、schema 和请求计时。Overview 区域使用记录的开始时间、耗时与 token 边界数据,而不虚构实时流逝时间,其包含边界的聚焦行为与用户熟悉的 Chrome DevTools Network 交互一致。尾部优先分页限制初始传输工作,虚拟化限制已挂载的行元素数量,精确 ID 分发避免重新 fold 无关业务 Context,animation-frame 发布则限制流式 snapshot 频率。保留的 stage-oriented target builder 在一次发布中仍可能执行与已加载物化 Node 数量成比例的工作;本次迁移不额外承诺更强的 Trajectory 专属复杂度。针对性组件测试锁定尾部优先分页、向前补页锚定与标识保持、虚拟窗口、末尾跟随、仅含内容的流式输出不会重复写入滚动位置、计时投影、延迟展示详情、折叠、记录与区间选择、实体特定标签页和运行/错误语义。真实浏览器中的长记录表约定锁定向前补页时稳定的几何位置、有界挂载、顶部/中部/底部可达性,以及按节奏进行的流式输出中有界的滚动写入;组装后的 Web 快照则通过真实客户端组合锁定记录表、Overview 计时详情、composer 浮层几何形状与检查器。 diff --git a/.agents/notes/implemented/feature/2026-08-04-web-context-source-and-steer-marks.i18n.yaml b/.agents/notes/implemented/feature/2026-08-04-web-context-source-and-steer-marks.i18n.yaml index 86b48310e7..362aef352f 100644 --- a/.agents/notes/implemented/feature/2026-08-04-web-context-source-and-steer-marks.i18n.yaml +++ b/.agents/notes/implemented/feature/2026-08-04-web-context-source-and-steer-marks.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-04-web-context-source-and-steer-marks.md -2026-08-04-web-context-source-and-steer-marks.md: 01bdca873a847f70b4b8632b961e01e099ae4f04 -2026-08-04-web-context-source-and-steer-marks.zh.md: b6a9cc5692826b402b5a08ec65a5c8fc3c547b6b +2026-08-04-web-context-source-and-steer-marks.md: d4fee3ee25aceaf05106d6bd1bdb73e7c51c3f78 +2026-08-04-web-context-source-and-steer-marks.zh.md: 8e0ffa6c15ea7506e1aaed9f0b142925727856aa diff --git a/.agents/notes/implemented/feature/2026-08-04-web-context-source-and-steer-marks.md b/.agents/notes/implemented/feature/2026-08-04-web-context-source-and-steer-marks.md index 01bdca873a..d4fee3ee25 100644 --- a/.agents/notes/implemented/feature/2026-08-04-web-context-source-and-steer-marks.md +++ b/.agents/notes/implemented/feature/2026-08-04-web-context-source-and-steer-marks.md @@ -14,13 +14,13 @@ The distinctions are already durable. Every producer must supply a merge-extensi The transcript names all three roles a non-prompt message can play — injected context, recalled session, and steering. -`TranscriptAdapter` and the history fold attach a `provenance` view containing the producer role and label to every `ContextMessageNode`; `contextProvenance()` computes it from the durable source alone. It returns a `role` (`inject`, or `recall` for a cross-session snapshot) and a `label` naming the producer. `ContextInjectionRow` titles itself from the role and shows the label beside that title in `ToolRow`'s summary geometry, so the collapsed row already answers what was added and by whom; the 141px scrollport and truncation bound are unchanged from the [archived disclosure decision](../../archived/feature/2026-07-30-web-context-injection-disclosure.md). What renders inside that scrollport is chosen by the independent form axis added in the [context form decision](2026-08-05-context-form-vocabulary.md). +The Chat Message Definition attaches a `provenance` view containing the producer role and label to every `ContextMessageNode`; `contextProvenance()` computes it from the durable source alone. It returns a `role` (`inject`, or `recall` for a cross-session snapshot) and a `label` naming the producer. `ContextInjectionRow` titles itself from the role and shows the label beside that title in `ToolRow`'s summary geometry, so the collapsed row already answers what was added and by whom; the 141px scrollport and truncation bound are unchanged from the [archived disclosure decision](../../archived/feature/2026-07-30-web-context-injection-disclosure.md). What renders inside that scrollport is chosen by the independent form axis added in the [context form decision](2026-08-05-context-form-vocabulary.md). **The label is read out of the log, never from a client-side table of producer names.** `workspace-instructions` is named by the distinct instruction paths it reconciled, `session-reference` by the titles of the sessions it read, a plugin source by its logged plugin id, and any other source by its own `kind` — the documented default arm for a merge-extensible union. A source carrying no readable kind degrades to an unnamed injection. A new or renamed producer is therefore identifiable without a client release, no label can go stale against the code, and a resumed, forked, or foreign log projects exactly like a live session. `recall` covers `session-reference` because that is the one shipped source that lifts another session's material into this one. No Web leaf mounts `dsh-session-reference` today — it had only a terminal host — so the arm exists for log portability rather than for a bundled producer, and it is exercised by unit coverage rather than an assembled Web scenario. -`MessageItem` captions durable and pending steering bubbles with `插话`. The runtime replays durable `agent/inbox/spliced` events and projects a user-origin `user/message` as `SteeringMessageNode` when that same message identity was claimed from `next-step`; a queued-turn claim stays a `UserMessageNode`, and a non-user next-step message stays context. This reverses one clause of the [archived no-steer decision](../../archived/simplification/2026-07-31-web-ui-no-steer-entry-or-interjection-chrome.md), which removed the badge because the composer could not steer and the label named a gesture users could not perform. The composer gained a Steer gesture afterwards without amending that note; this decision supplies the product decision its reintroduction clause required, and corrects the stale facts left in it. The caption is the only steering chrome here: composer modes, the Queue dock's strict-steer action, and pending-steering lifecycle stay with their own owners. +`MessageItem` captions durable and pending steering bubbles with `插话`. The Chat Inbox and Message Definitions replay durable `agent/inbox/spliced` events and project a user-origin `user/message` as `SteeringMessageNode` when that same message identity was claimed from `next-step`; a queued-turn claim stays a `UserMessageNode`, and a non-user next-step message stays context. This reverses one clause of the [archived no-steer decision](../../archived/simplification/2026-07-31-web-ui-no-steer-entry-or-interjection-chrome.md), which removed the badge because the composer could not steer and the label named a gesture users could not perform. The composer gained a Steer gesture afterwards without amending that note; this decision supplies the product decision its reintroduction clause required, and corrects the stale facts left in it. The caption is the only steering chrome here: composer modes, the Queue dock's strict-steer action, and pending-steering lifecycle stay with their own owners. ## Alternatives considered diff --git a/.agents/notes/implemented/feature/2026-08-04-web-context-source-and-steer-marks.zh.md b/.agents/notes/implemented/feature/2026-08-04-web-context-source-and-steer-marks.zh.md index b6a9cc5692..8e0ffa6c15 100644 --- a/.agents/notes/implemented/feature/2026-08-04-web-context-source-and-steer-marks.zh.md +++ b/.agents/notes/implemented/feature/2026-08-04-web-context-source-and-steer-marks.zh.md @@ -14,13 +14,13 @@ Status: implemented transcript 为非提示消息可能承担的三种角色分别命名:注入上下文、召回会话、steering。 -`TranscriptAdapter` 与历史折叠为每个 `ContextMessageNode` 附加一份包含生产者角色和名称的 `provenance` 视图;`contextProvenance()` 仅依据持久来源计算该视图。它返回 `role`(`inject`,跨会话快照则为 `recall`)与命名生产者的 `label`。`ContextInjectionRow` 以角色作为标题,并按 `ToolRow` 摘要的几何在标题旁展示该名称,因此折叠态就已经回答了「注入了什么、由谁注入」;141px 滚动视口与截断上限沿用[已归档的展开项决策](../../archived/feature/2026-07-30-web-context-injection-disclosure.md),未作改动。视口里渲染什么,则由[上下文形态决策](2026-08-05-context-form-vocabulary.md)引入的、相互独立的形态轴决定。 +Chat Message Definition 为每个 `ContextMessageNode` 附加一份包含生产者角色和名称的 `provenance` 视图;`contextProvenance()` 仅依据持久来源计算该视图。它返回 `role`(`inject`,跨会话快照则为 `recall`)与命名生产者的 `label`。`ContextInjectionRow` 以角色作为标题,并按 `ToolRow` 摘要的几何在标题旁展示该名称,因此折叠态就已经回答了「注入了什么、由谁注入」;141px 滚动视口与截断上限沿用[已归档的展开项决策](../../archived/feature/2026-07-30-web-context-injection-disclosure.md),未作改动。视口里渲染什么,则由[上下文形态决策](2026-08-05-context-form-vocabulary.md)引入的、相互独立的形态轴决定。 **名称从日志中读出,绝不来自客户端维护的生产者名称表。** `workspace-instructions` 以它对账过的去重指令文件路径命名,`session-reference` 以它读取的会话标题命名,插件来源以其记录的插件 id 命名,其余来源则以自身的 `kind` 命名——这正是可合并扩展联合类型有文档记载的默认分支。没有可读 kind 的来源降级为无名注入。于是新增或重命名的生产者无需客户端发版即可辨识,任何名称都不会相对代码变味,恢复、fork 或来自外部的日志与实时会话的投影结果完全一致。 `recall` 覆盖 `session-reference`,因为它是当前唯一会把另一个会话的材料搬进本会话的已发布来源。今天没有任何 Web 叶子挂载 `dsh-session-reference`——它此前只有终端宿主——因此该分支的存在是为了日志可移植性,而不是为了某个已打包的生产方,其覆盖来自单元测试而非组装后的 Web 场景。 -`MessageItem` 为持久与待处理的 steering 气泡加上 `插话` 标注。runtime 会重放持久 `agent/inbox/spliced` 事件;如果一条用户来源的消息以相同身份从 `next-step` 被领取,后续 `user/message` 就投影为 `SteeringMessageNode`。从排队轮次领取的消息仍是 `UserMessageNode`,非用户来源的 next-step 消息仍是上下文。这推翻了[已归档的取消 steer 入口与插话装饰决策](../../archived/simplification/2026-07-31-web-ui-no-steer-entry-or-interjection-chrome.md)中的一条结论。当时移除徽章,是因为 composer 无法 steer,标签指向了用户做不到的动作。此后 composer 获得了 Steer 手势,却没有同步修订那份 note;本决策提供了它在「重新引入」条款中要求的产品决策,并订正了其中留下的过时事实。标注是这里唯一的 steering 装饰:composer 模式、Queue dock 的严格 steer 操作、待处理 steering 的生命周期仍归各自的所有者。 +Chat Inbox 与 Message Definition 会重放持久 `agent/inbox/spliced` 事件;如果一条用户来源的消息以相同身份从 `next-step` 被领取,后续 `user/message` 就投影为 `SteeringMessageNode`。`MessageItem` 为这种持久消息与待处理 steering 气泡加上 `插话` 标注。从排队轮次领取的消息仍是 `UserMessageNode`,非用户来源的 next-step 消息仍是上下文。这推翻了[已归档的取消 steer 入口与插话装饰决策](../../archived/simplification/2026-07-31-web-ui-no-steer-entry-or-interjection-chrome.md)中的一条结论。当时移除徽章,是因为 composer 无法 steer,标签指向了用户做不到的动作。此后 composer 获得了 Steer 手势,却没有同步修订那份 note;本决策提供了它在「重新引入」条款中要求的产品决策,并订正了其中留下的过时事实。标注是这里唯一的 steering 装饰:composer 模式、Queue dock 的严格 steer 操作、待处理 steering 的生命周期仍归各自的所有者。 ## 考虑过的替代方案 diff --git a/.agents/notes/implemented/testing/2026-07-24-web-gui-browser-e2e-lane.i18n.yaml b/.agents/notes/implemented/testing/2026-07-24-web-gui-browser-e2e-lane.i18n.yaml index cc081c72c4..7f86295344 100644 --- a/.agents/notes/implemented/testing/2026-07-24-web-gui-browser-e2e-lane.i18n.yaml +++ b/.agents/notes/implemented/testing/2026-07-24-web-gui-browser-e2e-lane.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/testing/2026-07-24-web-gui-browser-e2e-lane.md -2026-07-24-web-gui-browser-e2e-lane.md: e572929ae6762da6adc2e77e1dba19361beaf670 -2026-07-24-web-gui-browser-e2e-lane.zh.md: 99f86f40ba006c4024f367b73ce52f8679b8d2fd +2026-07-24-web-gui-browser-e2e-lane.md: 6e52d96a8adb5486e8666d65a3425bf5a0aad4a9 +2026-07-24-web-gui-browser-e2e-lane.zh.md: 7598a8edc530a34261799e57ce953edafe44e70e diff --git a/.agents/notes/implemented/testing/2026-07-24-web-gui-browser-e2e-lane.md b/.agents/notes/implemented/testing/2026-07-24-web-gui-browser-e2e-lane.md index e572929ae6..6e52d96a8a 100644 --- a/.agents/notes/implemented/testing/2026-07-24-web-gui-browser-e2e-lane.md +++ b/.agents/notes/implemented/testing/2026-07-24-web-gui-browser-e2e-lane.md @@ -88,7 +88,7 @@ Surveyed AI-chat/agent web UIs and mocking layers (LibreChat, vercel/ai-chatbot - **Follow-up-prompt-after-resume scenario**: the history/live stitch path over the real wire; add as its own scenario when that code changes or regresses. - **Composer steering gesture**: the input locks while running (stop-or-wait), so the steering scenario steers over the wire from the page; `TODO(web-steer-composer)` upgrades the drive step to a real composer gesture when the product grows one. - **Drag session reorder**: `workspace.insertSessionBefore` has no browser scenario; it needs two sessions materialized in one workspace plus synthesized HTML5 drag events. Add it when that surface changes or regresses. The inert session Rename/Fork/Delete and workspace Delete menu rows get scenarios when they gain behavior. -- **Long-history Chat-to-Trajectory Inspect**: the independent inspection source exhausts history after the view opens, while the selected record is addressed by a derived table index that can move as older pages prepend. Short-history Inspect remains covered; the long-history interaction contract excludes this handoff until selection has a stable semantic identity. +- **Long-history Chat-to-Trajectory Inspect**: both views share Session paging, while the selected Trajectory record is addressed by a derived table index that can move as older pages prepend. Short-history Inspect remains covered; the long-history interaction contract excludes this handoff until selection has a stable semantic identity. ## Consequences diff --git a/.agents/notes/implemented/testing/2026-07-24-web-gui-browser-e2e-lane.zh.md b/.agents/notes/implemented/testing/2026-07-24-web-gui-browser-e2e-lane.zh.md index 99f86f40ba..7598a8edc5 100644 --- a/.agents/notes/implemented/testing/2026-07-24-web-gui-browser-e2e-lane.zh.md +++ b/.agents/notes/implemented/testing/2026-07-24-web-gui-browser-e2e-lane.zh.md @@ -88,7 +88,7 @@ Web GUI 以一条真实组装链交付——chromium 页面 → client 插件 bu - **恢复后追问场景**:真实 wire 上的历史/实时缝合路径;当该代码变更或回归时作为独立场景补充。 - **输入框 steering 手势**:输入在运行期间锁定(只能停止或等待),因此 steering 场景从页面走 wire 做 steer;`TODO(web-steer-composer)` 待产品长出真实的输入框手势后,把驱动步骤升级为该手势。 - **拖拽会话重排**:`workspace.insertSessionBefore` 尚无浏览器场景;它需要在同一个工作区里物化两个会话,并合成 HTML5 拖拽事件。当该表面变更或回归时再补充。无行为的会话 Rename/Fork/Delete 和工作区 Delete 菜单行待获得行为后再补充场景。 -- **长历史 Chat 到 Trajectory 的 Inspect**:独立的检查数据源会在视图打开后穷尽历史,而所选记录由一个派生的表格索引定位;随着较早页面前插,该索引可能移动。短历史 Inspect 仍有覆盖;在选中项具有稳定的语义身份之前,长历史交互约定不包含这项交接。 +- **长历史 Chat 到 Trajectory 的 Inspect**:两个视图共用 Session 分页,而所选 Trajectory 记录由一个派生的表格索引定位;随着较早页面前插,该索引可能移动。短历史 Inspect 仍有覆盖;在选中项具有稳定的语义身份之前,长历史交互约定不包含这项交接。 ## 后果 diff --git a/packages/client/runtime/README.i18n.yaml b/packages/client/runtime/README.i18n.yaml index 7dc91083c9..9743f813da 100644 --- a/packages/client/runtime/README.i18n.yaml +++ b/packages/client/runtime/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/client/runtime/README.md -README.md: 1ec6cc38aed1bebff6b6ecb40faee7ae3ba9e412 -README.zh.md: 6602152790a1d433371e27b274a4eb8c9e3cfcd8 +README.md: d84cd793c34242759ad04edf0debb91558ec3dfc +README.zh.md: e7a74c454f24fcec5e797427c21222b1dc258b44 diff --git a/packages/client/runtime/README.md b/packages/client/runtime/README.md index 1ec6cc38ae..d84cd793c3 100644 --- a/packages/client/runtime/README.md +++ b/packages/client/runtime/README.md @@ -2,10 +2,9 @@ English | [中文](README.zh.md) -Client cordis boot and React-free object services: SlotsService wraps SlotCore and supplies renderer data sources; SessionsService owns Session objects and the Chat-facing list, scope, and event-window state; SessionHistoryService lazily owns independent raw-history ledgers for inspection consumers, loading the current tail first and prepending one older page only when its consumer requests it. Each history snapshot exposes the raw window's absolute base sequence so a consumer detects a prepend even when the page adds no surface-visible node. WorkspacesService depends on SessionsService and owns Workspace objects, list/actions, default-target derivation, and the New Session blank-reuse entry (`connectWorkspace`). The runtime fans the shared Host stream into the Session, Workspace, and activated history owners without routing inspection state through Session or SessionManager, and bridges the registry-invalidation frames to typed ctx events (`commands/changed`, `session/preset-changed`, `settings/changed`, `credentials/changed`, `models/changed`) so surface caches refetch without touching the stream. `host/session-preset-changed` also folds its preset into the session row, because the switch's RPC echo reaches only the client that issued it. Client sessions are always Host-born (Session+Agent+cwd in one `session.create`); the client holds no pre-entity session state — a session's Agent scope (the client mirror of host dsh-scope, keyed by the shared agent/session id) is born when its row enters the list mirror and dies with the prune. Each `Session` holds a generic `ProjectionValueStore` seeded from the history-tail `projections` block and updated by `session/projection` frames under higher-seq-wins; domain keys (including `todos`) are read via `projections.faceOf` / `useProjection`, not via `ConversationSnapshot`. The store also publishes one reference-stable whole-value map through `SessionSummary.projectionValues`, allowing global list consumers to reuse the same projections without creating per-session subscriptions. +Client cordis boot and React-free object services: SlotsService wraps SlotCore and supplies renderer data sources; SessionsService owns Session objects, list and scope state, and the shared event window and history paging used by registered conversation view targets. WorkspacesService depends on SessionsService and owns Workspace objects, list/actions, default-target derivation, and the New Session blank-reuse entry (`connectWorkspace`). The runtime fans the shared Host stream into Session and Workspace owners and bridges the registry-invalidation frames to typed ctx events (`commands/changed`, `session/preset-changed`, `settings/changed`, `credentials/changed`, `models/changed`) so surface caches refetch without touching the stream. `host/session-preset-changed` also folds its preset into the session row, because the switch's RPC echo reaches only the client that issued it. Client sessions are always Host-born (Session+Agent+cwd in one `session.create`); the client holds no pre-entity session state — a session's Agent scope (the client mirror of host dsh-scope, keyed by the shared agent/session id) is born when its row enters the list mirror and dies with the prune. Contract: api-contracts v3 §4. Each `Session` holds a generic `ProjectionValueStore` seeded from the history-tail `projections` block and updated by `session/projection` frames under higher-seq-wins; domain keys (including `todos`) are read via `projections.faceOf` / `useProjection`, not via `ConversationSnapshot`. The store also publishes one reference-stable whole-value map through `SessionSummary.projectionValues`, allowing global list consumers to reuse the same projections without creating per-session subscriptions. `bindSettingsScope` is the browser mirror of the Host-side settings owner seam for one domain-owned namespace. It subscribes before starting a nonblocking initial read, publishes a uSES snapshot (status, section value, revision, writability, host/memory mode), serializes `set` writes with the latest known namespace revision, suppresses stale publications, recovers a rejected latest write from Host state, and reaches quiescence on plugin disposal. The default decoder validates each section against the namespace's own serialized wire schema (rehydrated through dsh-client-schema-form), so a domain adds a decoder only to narrow beyond that schema. Loopback pages use the Host settings API; remote pages stay in memory mode. Domain packages own the namespace schema, default, and live service rather than putting product policy in runtime. - ## Slot declaration injection `ctx.slots.inject(name, callback)` makes a full `SlotMap` key the dependency for a contribution whose plugin can activate independently from the declaring entry. It runs `callback` synchronously when the declaration exists, otherwise waits; declaration collapse disposes the callback effect, and redeclaration reruns it. The controller belongs to the caller's plugin fiber, so unloading the contributor cancels either the wait or its active registrations. A direct `slots.register()` into an undeclared slot still throws. @@ -42,17 +41,17 @@ Each `Session` gives its contiguous event window to a `ConversationNodeAssembler Definition authors keep matching local to the current event, give every correlated event a stable business id, and make updates replayable by log `seq`; renderers consume final Node data and constrained Location values rather than scanning Session or Chat collections. The [Conversation Node cookbook](../../../docs/cookbook/adding-a-conversation-node.md) gives the complete registration and pagination path. -`ui-conversation` registers the built-in Chat Definitions and the keyed Chat snapshot builder. Append-origin user, assistant, and Tool results remain the human record; model-only replacement copies stay out, except that a compaction checkpoint becomes its own marker and resolves missing summary provenance when an older page supplies it. Durable inbox splice Contexts classify next-step user messages as steering without making inbox state a Session special case. Context messages retain producer provenance and form. StatsLine reads `ConversationSnapshot.chat.legacy.nodes`, while Session mirrors that legacy slice into the top-level `nodes`, `partial`, and `runningCalls` public compatibility fields without running a second business fold. Trajectory consumes neither compatibility surface; its activated `session-history` inspection keeps an independent fold until it gains its own registered target. +`ui-conversation` registers the built-in Chat Definitions and the keyed Chat snapshot builder. Append-origin user, assistant, and Tool results remain the human record; model-only replacement copies stay out, except that a compaction checkpoint becomes its own marker and resolves missing summary provenance when an older page supplies it. Durable inbox splice Contexts classify next-step user messages as steering without making inbox state a Session special case. Context messages retain producer provenance and form. StatsLine reads `ConversationSnapshot.chat.legacy.nodes`, while Session mirrors that legacy slice into the top-level `nodes`, `partial`, and `runningCalls` public compatibility fields without running a second business fold. `ui-trajectory` registers independent Definitions and a target builder over the same Session window; it preserves the existing stage-oriented view model without consuming the Chat compatibility fields or running another history fold. The Chat builder keeps one mutable keyed store per Session. Content updates notify only the affected node key, structural changes rebuild order and Location membership, and a prepend adds rows without replacing existing keyed values. Assistant chunks update Definition State for every event but request at most one materialization per animation frame; final messages and Turn/Step closure publish immediately. See the [client Tool presentation decision](../../../.agents/notes/implemented/architecture/2026-08-08-client-tool-presentation-ownership.md). -## Request inspection +## Trajectory request data -`SessionHistoryInspection.requests` is one chronological, purpose-discriminated provider-request stream. Assistant requests always carry their numeric `turn` and `step`; compaction requests carry `step: 0` and a `turn` owner that may be `null`. That null owner means a manual compaction ran standalone between turns, not that it belongs to either adjacent turn. A `session/end-seed` boundary closes an unmatched compaction request as an error at the boundary time with `Compaction was interrupted before completion.`; a later start projects as an independent request instead of overwriting the orphan. +Trajectory Definitions assemble one chronological, purpose-discriminated provider-request stream. Assistant requests always carry their numeric `turn` and `step`; compaction requests carry `step: 0` and a `turn` owner that may be `null`. That null owner means a manual compaction ran standalone between turns, not that it belongs to either adjacent turn. A `session/end-seed` boundary closes an unmatched compaction request as an error at the boundary time with `Compaction was interrupted before completion.`; a later start projects as an independent request instead of overwriting the orphan. ## Code Mode child-call tree -Every `ToolCallBlock` recursively owns its children through `subCalls`, in start order. Chat's Tool Definition correlates root calls and results by call id, folds Code Dispatch start/settlement records into that root Context, and projects one keyed recursive tree; child calls never become independent Chat roots. When a start falls outside the loaded window, its settlement remains renderable with `callTime: null`. A child update copies only its ancestor path, so unchanged siblings retain object identity. Edges that introduce a cycle or exceed the fixed 256-call depth limit are consumed without mutating the tree. The separate Trajectory history fold still uses Runtime's `ToolCallTree` over the same nested data contract. +Every `ToolCallBlock` recursively owns its children through `subCalls`, in start order. Chat's Tool Definition correlates root calls and results by call id, folds Code Dispatch start/settlement records into that root Context, and projects one keyed recursive tree; child calls never become independent Chat roots. When a start falls outside the loaded window, its settlement remains renderable with `callTime: null`. A child update copies only its ancestor path, so unchanged siblings retain object identity. Edges that introduce a cycle or exceed the fixed 256-call depth limit are consumed without mutating the tree. Trajectory's Tool Definition independently assembles the same nested data contract for its target. ## Session title projection diff --git a/packages/client/runtime/README.zh.md b/packages/client/runtime/README.zh.md index 6602152790..e7a74c454f 100644 --- a/packages/client/runtime/README.zh.md +++ b/packages/client/runtime/README.zh.md @@ -2,10 +2,9 @@ [English](README.md) | 中文 -客户端 cordis 启动与不依赖 React 的对象服务:SlotsService 包装 SlotCore 并提供 renderer 数据源;SessionsService 拥有 Session 对象以及 Chat 所需的列表、scope 和事件窗口状态;SessionHistoryService 为检查类消费方惰性拥有彼此独立的原始历史账本,先加载当前尾部,并仅在消费方请求时向前补入一页更早历史。每份历史快照都会公开原始窗口的绝对基准序号,因此即使该页没有新增任何 surface 可见节点,消费方仍能检测到向前补页。WorkspacesService 依赖 SessionsService,拥有 Workspace 对象、列表/操作、默认目标派生,以及 New Session 空会话复用入口(`connectWorkspace`)。运行时把共享 Host 流分发给 Session、Workspace 和已激活的历史数据所有者,不让检查状态经过 Session 或 SessionManager,并把注册表失效帧桥接为类型化 ctx 事件(`commands/changed`、`session/preset-changed`、`settings/changed`、`credentials/changed`、`models/changed`),使各表面缓存无需触碰流即可重拉。`host/session-preset-changed` 还会把其中的 preset 折进会话行,因为这次切换的 RPC 回执只会到达发起它的那个客户端。客户端会话一律由 Host 创建(一次 `session.create` 同时产生 Session、agent(智能体)和 cwd);客户端不持有任何实体化之前的会话状态——agent scope(host dsh-scope 的客户端镜像,以 agent/session 共用 id 为键)在会话行进入列表镜像时创建,并随 prune 销毁。每个 `Session` 持有一个通用的 `ProjectionValueStore`,由历史记录尾部的 `projections` 块播种,并经 `session/projection` 帧按 seq 高者胜更新;领域键(含 `todos`)经 `projections.faceOf`/`useProjection` 读取,不经 `ConversationSnapshot`。该 store 还会通过 `SessionSummary.projectionValues` 发布一份引用稳定的完整值映射,使全局列表消费方无需为每个会话创建订阅,即可复用同一组投影。 +客户端 cordis 启动与不依赖 React 的对象服务:SlotsService 包装 SlotCore 并提供 renderer 数据源;SessionsService 拥有 Session 对象、列表与 scope 状态,以及供已注册 conversation view target 共用的事件窗口与历史分页。WorkspacesService 依赖 SessionsService,拥有 Workspace 对象、列表/操作、默认目标派生,以及 New Session 空会话复用入口(`connectWorkspace`)。运行时把共享 Host 流分发给 Session 与 Workspace 所有者,并把注册表失效帧桥接为类型化 ctx 事件(`commands/changed`、`session/preset-changed`、`settings/changed`、`credentials/changed`、`models/changed`),使各表面缓存无需触碰流即可重拉。`host/session-preset-changed` 还会把其中的 preset 折进会话行,因为这次切换的 RPC 回执只会到达发起它的那个客户端。客户端会话一律由 Host 创建(一次 `session.create` 同时产生 Session、agent(智能体)和 cwd);客户端不持有任何实体化之前的会话状态——agent scope(host dsh-scope 的客户端镜像,以 agent/session 共用 id 为键)在会话行进入列表镜像时创建,并随 prune 销毁。约定:api-contracts v3 §4。每个 `Session` 持有一个通用的 `ProjectionValueStore`,由历史记录尾部的 `projections` 块播种,并经 `session/projection` 帧按 seq 高者胜更新;领域键(含 `todos`)经 `projections.faceOf`/`useProjection` 读取,不经 `ConversationSnapshot`。该 store 还会通过 `SessionSummary.projectionValues` 发布一份引用稳定的完整值映射,使全局列表消费方无需为每个会话创建订阅,即可复用同一组投影。 `bindSettingsScope` 面向单个由领域持有的 namespace,是 Host 侧 settings owner seam 的浏览器镜像。它在开始非阻塞初始读取前建立订阅,发布 uSES 快照(状态、分节值、revision、可写性、host/内存模式),使用已知最新 namespace revision 串行执行 `set` 写入,抑制陈旧发布,并在最新写入被拒时从 Host 状态恢复;插件释放时,它会达到完全停稳。默认解码器会对照该 namespace 自身的序列化 wire schema(经 dsh-client-schema-form 还原)校验每个分节,因此领域只有在需要比该 schema 进一步收窄时才添加解码器。回环页面使用 Host settings API,远程页面则停留在内存模式。namespace schema、默认值与实时服务归领域包所有,而非把产品政策放入运行时。 - ## Slot 声明注入 `ctx.slots.inject(name, callback)` 将完整的 `SlotMap` key 作为贡献项的依赖,适用于贡献方插件可独立于声明条目激活的情形。声明存在时,它会同步运行 `callback`,否则等待;声明折叠会 dispose(资源释放)回调 effect,重新声明则会再次运行回调。控制器归调用方的插件 fiber 所有,因此卸载贡献方会取消等待或移除其活跃注册项。直接调用 `slots.register()` 向未声明 slot 注册仍会抛出异常。 @@ -42,17 +41,17 @@ SlotsService 分别为 renderer 提供 `useSessions` 与 `useWorkspaces` 的裸 Definition 作者只根据当前事件完成匹配,为每条关联事件提供稳定业务 id,并保证 update 能按日志 `seq` 回放;renderer 只消费最终 Node data 与受限 Location value,不扫描 Session 或 Chat 集合。完整注册和分页路径见 [Conversation Node 实操手册](../../../docs/cookbook/adding-a-conversation-node.md)。 -`ui-conversation` 注册内建 Chat Definition 与 keyed Chat snapshot builder。append 来源的 user、assistant 和 Tool result 构成人类可见记录;仅供模型使用的 replacement 副本不进入 Chat,compaction 检查点除外,它会成为独立标记,并在更早分页补齐 summary 溯源后更新。持久 inbox splice Context 能把 next-step 用户消息判定为 steering,无须让 inbox 状态成为 Session 特例。上下文消息保留生产者 provenance 与 form。StatsLine 读取 `ConversationSnapshot.chat.legacy.nodes`;Session 则把该 legacy slice 镜像到顶层 `nodes`、`partial` 和 `runningCalls` 公共兼容字段,无须运行第二套业务 fold。Trajectory 不消费这两种兼容表面;在它获得独立注册 target 之前,已激活的 `session-history` inspection 继续维护独立 fold。 +`ui-conversation` 注册内建 Chat Definition 与 keyed Chat snapshot builder。append 来源的 user、assistant 和 Tool result 构成人类可见记录;仅供模型使用的 replacement 副本不进入 Chat,compaction 检查点除外,它会成为独立标记,并在更早分页补齐 summary 溯源后更新。持久 inbox splice Context 能把 next-step 用户消息判定为 steering,无须让 inbox 状态成为 Session 特例。上下文消息保留生产者 provenance 与 form。StatsLine 读取 `ConversationSnapshot.chat.legacy.nodes`;Session 则把该 legacy slice 镜像到顶层 `nodes`、`partial` 和 `runningCalls` 公共兼容字段,无须运行第二套业务 fold。`ui-trajectory` 在同一个 Session 窗口上注册独立 Definition 与 target builder;它保留现有的 stage-oriented view model,既不消费 Chat 兼容字段,也不运行另一套 history fold。 Chat builder 为每个 Session 保留一个 mutable keyed store。内容更新只通知受影响的 node key;结构变化才重建顺序和 Location 成员关系;prepend 只增加行,不替换既有 keyed value。每个 Assistant chunk 都会更新 Definition State,但最多每个 animation frame 请求一次物化;final message 与 Turn/Step 关闭会立即发布。参见 [Client Tool 展示所有权决策](../../../.agents/notes/implemented/architecture/2026-08-08-client-tool-presentation-ownership.md)。 -## 请求检查 +## Trajectory 请求数据 -`SessionHistoryInspection.requests` 是一条按时间顺序排列、以用途为判别字段的提供方请求流。助手请求始终携带数值型 `turn` 与 `step`;压缩请求携带 `step: 0`,其 `turn` 所有者可以是 `null`。这个 null 所有者表示手动压缩独立运行在两个轮次之间,并不表示它属于任一相邻轮次。`session/end-seed` 边界会在边界时刻将未匹配的压缩请求以错误状态结束,错误固定为 `Compaction was interrupted before completion.`;后续 start 会投影为独立请求,而不会覆盖这项遗留的未匹配请求。 +Trajectory Definition 组装出一条按时间顺序排列、以用途为判别字段的提供方请求流。助手请求始终携带数值型 `turn` 与 `step`;压缩请求携带 `step: 0`,其 `turn` 所有者可以是 `null`。这个 null 所有者表示手动压缩独立运行在两个轮次之间,并不表示它属于任一相邻轮次。`session/end-seed` 边界会在边界时刻将未匹配的压缩请求以错误状态结束,错误固定为 `Compaction was interrupted before completion.`;后续 start 会投影为独立请求,而不会覆盖这项遗留的未匹配请求。 ## Code Mode 子调用树 -每个 `ToolCallBlock` 都通过 `subCalls` 按启动顺序递归拥有自己的子调用。Chat 的 Tool Definition 按 call id 关联 root call 与 result,把 Code Dispatch 的 start/settlement 记录折叠进该 root Context,并投影为一棵 keyed 递归树;child call 不会成为独立 Chat root。start 落在已加载窗口之外时,其 settlement 仍以 `callTime: null` 渲染。一次 child 更新只复制其祖先链,因此未变化的 sibling 保持对象身份。会引入环或超过固定 256 层深度上限的边会被消费,但不会修改树。独立的 Trajectory history fold 仍通过 Runtime 的 `ToolCallTree` 生成同一种嵌套数据契约。 +每个 `ToolCallBlock` 都通过 `subCalls` 按启动顺序递归拥有自己的子调用。Chat 的 Tool Definition 按 call id 关联 root call 与 result,把 Code Dispatch 的 start/settlement 记录折叠进该 root Context,并投影为一棵 keyed 递归树;child call 不会成为独立 Chat root。start 落在已加载窗口之外时,其 settlement 仍以 `callTime: null` 渲染。一次 child 更新只复制其祖先链,因此未变化的 sibling 保持对象身份。会引入环或超过固定 256 层深度上限的边会被消费,但不会修改树。Trajectory 的 Tool Definition 为自己的 target 独立组装同一种嵌套数据契约。 ## Session 标题投影 diff --git a/packages/client/runtime/package.json b/packages/client/runtime/package.json index 749e564ef5..86d51cd7a3 100644 --- a/packages/client/runtime/package.json +++ b/packages/client/runtime/package.json @@ -46,7 +46,6 @@ "@deepseek-ai/dsh-client-connection": "workspace:^", "@deepseek-ai/dsh-client-schema-form": "workspace:^", "@deepseek-ai/dsh-commands": "workspace:^", - "@deepseek-ai/dsh-compact": "workspace:^", "@deepseek-ai/dsh-client-ui-slots": "workspace:^", "@deepseek-ai/dsh-host-apiproxy": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", diff --git a/packages/client/runtime/src/client/contract/conversation.ts b/packages/client/runtime/src/client/contract/conversation.ts index 7119980839..26e7e43c67 100644 --- a/packages/client/runtime/src/client/contract/conversation.ts +++ b/packages/client/runtime/src/client/contract/conversation.ts @@ -116,7 +116,7 @@ export interface ConversationViewSnapshotMap {} /** Stable reader over the latest snapshot of every registered view target. */ export interface ConversationViewSnapshotStore { /** @param target - registered view target. @returns its current snapshot. */ - get( + get>( target: Target, ): ConversationViewSnapshotMap[Target] | undefined } diff --git a/packages/client/runtime/src/client/sessions/conversation-assembler.ts b/packages/client/runtime/src/client/sessions/conversation-assembler.ts index ee8e6b0eae..85c59a4053 100644 --- a/packages/client/runtime/src/client/sessions/conversation-assembler.ts +++ b/packages/client/runtime/src/client/sessions/conversation-assembler.ts @@ -324,7 +324,7 @@ export class ConversationNodeAssembler implements ConversationViewSnapshotStore return this.views.get(target)?.snapshot } - get( + get>( target: Target, ): ConversationViewSnapshotMap[Target] | undefined { return this.snapshot(target) as ConversationViewSnapshotMap[Target] | undefined diff --git a/packages/client/ui-conversation/tests/chat-view.spec.tsx b/packages/client/ui-conversation/tests/chat-view.spec.tsx index fd306eb132..084e4ffa3a 100644 --- a/packages/client/ui-conversation/tests/chat-view.spec.tsx +++ b/packages/client/ui-conversation/tests/chat-view.spec.tsx @@ -49,7 +49,8 @@ type RoutedChatNodeOwner = ChatNodeOwnerProps & { readonly node: ChatNode } function snapshotBase(): ConversationSnapshot { return { - sessionId: SID, views: EMPTY_CONVERSATION_VIEWS, chat: chatSnapshotFixture(), nodes: [], turnTimings: new Map(), turnEnds: new Map(), partial: null, runningCalls: [], + sessionId: SID, views: EMPTY_CONVERSATION_VIEWS, chat: chatSnapshotFixture(), nodes: [], + turnTimings: new Map(), turnEnds: new Map(), partial: null, runningCalls: [], pending: [], queue: [], running: false, composerPhase: 'active', removed: false, openState: 'open', openError: null, hasMore: false, loadingOlder: false, promptError: null, blank: false, subagent: null, lastAgentError: null, } diff --git a/packages/client/ui-deliverables/src/client/turn-deliverables.ts b/packages/client/ui-deliverables/src/client/turn-deliverables.ts index 0061400e7a..e63bca2e63 100644 --- a/packages/client/ui-deliverables/src/client/turn-deliverables.ts +++ b/packages/client/ui-deliverables/src/client/turn-deliverables.ts @@ -97,7 +97,6 @@ export function selectProducedFiles(owner: TurnTailOwnerProps): readonly string[ /** Turn-local successful mutation accumulator; it publishes no view Node. */ export const deliverablesDefinition: ConversationNodeDefinition = { kind: 'deliverables', - target: 'chat', match: (event) => { if (event.type === 'turn/start') return { id: String(event.data.turn), role: 'start' } if (event.type === 'tool/call') return { id: String(event.data.turn), role: 'update' } @@ -137,7 +136,6 @@ export const deliverablesDefinition: ConversationNodeDefinition null, } /** diff --git a/packages/client/ui-deliverables/tests/produced-files.spec.tsx b/packages/client/ui-deliverables/tests/produced-files.spec.tsx index 48303f2e54..31289b38de 100644 --- a/packages/client/ui-deliverables/tests/produced-files.spec.tsx +++ b/packages/client/ui-deliverables/tests/produced-files.spec.tsx @@ -73,7 +73,7 @@ interface TimelineSnapshot { class TestEventDefinitions { entries(): readonly ConversationNodeDefinition[] { return [deliverablesDefinition] } - fallbackEntries(): readonly ConversationNodeDefinition[] { return [] } + fallbackEntry(): ConversationNodeDefinition | undefined { return undefined } } class TestViewDefinitions { diff --git a/packages/client/ui-trajectory/README.i18n.yaml b/packages/client/ui-trajectory/README.i18n.yaml index 7fecd92d74..17551b0cc8 100644 --- a/packages/client/ui-trajectory/README.i18n.yaml +++ b/packages/client/ui-trajectory/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/client/ui-trajectory/README.md -README.md: 5b8c0cd111c272007212fea0d2435c5fab2360ab -README.zh.md: 9aaa02ccd9d50b0f0b23e9a53ea9b1048d0e513f +README.md: 75bd9ddf452634460be01e1b89cd5a1a14a1593f +README.zh.md: b5cd53dd50e43b96e2e832c96cb7e93f859c1993 diff --git a/packages/client/ui-trajectory/README.md b/packages/client/ui-trajectory/README.md index 5b8c0cd111..75bd9ddf45 100644 --- a/packages/client/ui-trajectory/README.md +++ b/packages/client/ui-trajectory/README.md @@ -2,7 +2,7 @@ English | [中文](README.zh.md) -Trajectory renders a turn-aware event ledger with selectable User, Assistant, Tool, and nested Subtool records. Thick rules mark Turn boundaries, compact inline markers identify Steps, and the main ledger keeps only index, event, and content; selection opens a local inspector for token usage, duration, Input, Output, and Timing. Scrollable Summary regions keep their scrollbar thumbs transparent until the region is hovered or contains keyboard focus, without changing the reserved scroll geometry. A standalone compaction request appears chronologically in its own `Between turns` section, while a numbered compaction remains inside its owning turn. Long ledgers open at the current tail, load one older page when the user reaches the loaded range's top, and mount only the visible row window plus a small overscan; request-only separators share the next measurable virtual item, while semantic row keys and ARIA indexes survive prepends. Selection, timeline navigation, folding, search, and Request totals cover the currently loaded window. The ledger covers records with an explicit loading row until the initial tail is positioned and while an older page is pending. A fixed Overview above the ledger projects real record start/duration timing from left to right; when earlier records remain unloaded and the viewport includes the loaded domain's start, a neutral ellipsis control identifies the omitted prefix and loads one earlier page without assigning unknown history fabricated duration. Assistant spans divide recorded TTFT from decoding, and a 500 ms hover reveals exact clock and duration details. Dragging an interval focuses the ledger on every record active at any point in that inclusive range, while clearing the selection restores the full branch. Wheel gestures zoom the time domain. A right-button click clears the selected interval, while a right-button drag pans an already zoomed viewport without changing it. The initial view and streaming updates stay at the tail; scrolling upward suspends following so new records do not interrupt inspection of earlier rows. Content-only stream frames preserve virtual row keys and heights, reuse measurements, and do not issue repeated tail-scroll writes. Completed replies retain only the first visible token and usage chunks in the inspection projection, while unfinished and interrupted replies retain every chunk; the independent source keeps the raw history unchanged. Trajectory asks the conversation shell to float the composer over the full-height ledger, while its responsive vertical scrollers reserve the composer's live height so final rows remain reachable. The runtime's independent history source supplies raw context lineage and projects cancellation-frozen Assistant and Tool records, so Trajectory neither reads nor changes the Chat conversation snapshot. The package remains a pure-consumer plugin (registers one view tab into the conversation's `'conversation.view'` slot ring, provides no service, declares no Context merge). +Trajectory renders a turn-aware event ledger with selectable User, Assistant, Tool, and nested Subtool records. Thick rules mark Turn boundaries, compact inline markers identify Steps, and the main ledger keeps only index, event, and content; selection opens a local inspector for token usage, duration, Input, Output, and Timing. Scrollable Summary regions keep their scrollbar thumbs transparent until the region is hovered or contains keyboard focus, without changing the reserved scroll geometry. A standalone compaction request appears chronologically in its own `Between turns` section, while a numbered compaction remains inside its owning turn. Long ledgers open at the current tail, load one older page when the user reaches the loaded range's top, and mount only the visible row window plus a small overscan; request-only separators share the next measurable virtual item, while semantic row keys and ARIA indexes survive prepends. Selection, timeline navigation, folding, search, and Request totals cover the currently loaded window. The ledger covers records with an explicit loading row until the initial tail is positioned and while an older page is pending. A fixed Overview above the ledger projects real record start/duration timing from left to right; when earlier records remain unloaded and the viewport includes the loaded domain's start, a neutral ellipsis control identifies the omitted prefix and loads one earlier page without assigning unknown history fabricated duration. Assistant spans divide recorded TTFT from decoding, and a 500 ms hover reveals exact clock and duration details. Dragging an interval focuses the ledger on every record active at any point in that inclusive range, while clearing the selection restores the full branch. Wheel gestures zoom the time domain. A right-button click clears the selected interval, while a right-button drag pans an already zoomed viewport without changing it. The initial view and streaming updates stay at the tail; scrolling upward suspends following so new records do not interrupt inspection of earlier rows. Content-only stream frames preserve virtual row keys and heights, reuse measurements, and do not issue repeated tail-scroll writes. Completed replies retain assembled blocks, timing, and usage in Trajectory target State, while the shared Session window keeps the raw Events. Trajectory asks the conversation shell to float the composer over the full-height ledger, while its responsive vertical scrollers reserve the composer's live height so final rows remain reachable. Trajectory-owned Definitions assemble context lineage and cancellation-frozen Assistant and Tool records from the shared Session window, so Trajectory neither reads nor changes the Chat conversation snapshot. The package provides no service and declares no Context merge; it registers target-specific Event Definitions, a Trajectory view builder, and one tab in the conversation's `'conversation.view'` slot ring. Contract: api-contracts v3 §8. ## Model Experience diff --git a/packages/client/ui-trajectory/README.zh.md b/packages/client/ui-trajectory/README.zh.md index 9aaa02ccd9..b5cd53dd50 100644 --- a/packages/client/ui-trajectory/README.zh.md +++ b/packages/client/ui-trajectory/README.zh.md @@ -2,7 +2,7 @@ [English](README.md) | 中文 -Trajectory 渲染按轮次组织的事件记录表,其中可选择用户、助手、工具和嵌套子工具记录。较粗的分割线标示轮次边界,紧凑的行内标记标识步骤,主记录表仅保留索引、事件和内容;选择记录则会打开局部检查器,查看 token 用量、耗时、输入、输出和计时。可滚动的概述区域默认保持滚动条滑块透明,直到鼠标悬停该区域或其中包含键盘焦点时才显示,同时不改变滚动条预留的几何空间。独立运行的压缩(compaction)请求会按时间顺序显示在自己的 `Between turns` 区段中,而带编号的压缩仍位于其所属轮次内。长记录表打开时定位于当前尾部,用户到达已加载范围顶部时加载一页更早的历史,并且只挂载可见行窗口和少量额外缓冲行;仅含请求的分隔行并入下一个具备可测高度的虚拟项,语义行键和 ARIA 索引在向前补页后保持不变。选择、时间线导航、折叠、搜索和请求汇总只覆盖当前已加载的窗口。初始尾部完成定位前以及更早页面仍在等待时,记录表会用明确的加载行遮住真实记录。固定在记录表上方的 Overview 区域从左到右投影记录的真实开始时间与耗时;仍有更早记录未加载且 viewport 包含已加载时间域起点时,中性的省略号控件会标识被省略的前缀,并可加载一页更早历史,而不会为未知部分虚构耗时。助手时间条会区分记录到的 TTFT 与解码时间,悬停 500 ms 后可查看精确时刻和耗时详情。拖选一个区间会将记录表聚焦到活动区间与该闭区间有重叠的所有记录,清除选择则恢复完整分支。滚轮手势用于缩放时间域。右键单击会清除所选区间;在已放大的 viewport 上按住右键拖动则只会平移视图,不会改变该区间。初始视图和流式更新都会停留在尾部;向上滚动会暂停跟随,因此新记录不会打断对旧记录的检查。仅含内容更新的流式帧会保持虚拟行的键和高度不变、复用测量结果,并且不会重复写入末尾滚动位置。已完成的回复在检查投影中仅保留首个可见 token 和用量分片,未完成及中断的回复则保留所有分片;独立数据源中的原始历史保持不变。Trajectory 要求会话壳将 composer 作为浮层置于全高记录表上方;其响应式纵向滚动容器会预留 composer 的实时高度,确保仍可滚动到最后几行。运行时的独立历史数据源提供原始上下文谱系,并投影因取消而冻结的助手和工具记录,因此 Trajectory 既不读取也不改变 Chat 会话快照。该包保持为纯消费方插件(向会话的 `'conversation.view'` slot 环注册一个视图标签页,不提供服务,也不声明 Context 合并)。 +Trajectory 渲染按轮次组织的事件记录表,其中可选择用户、助手、工具和嵌套子工具记录。较粗的分割线标示轮次边界,紧凑的行内标记标识步骤,主记录表仅保留索引、事件和内容;选择记录则会打开局部检查器,查看 token 用量、耗时、输入、输出和计时。可滚动的概述区域默认保持滚动条滑块透明,直到鼠标悬停该区域或其中包含键盘焦点时才显示,同时不改变滚动条预留的几何空间。独立运行的压缩(compaction)请求会按时间顺序显示在自己的 `Between turns` 区段中,而带编号的压缩仍位于其所属轮次内。长记录表打开时定位于当前尾部,用户到达已加载范围顶部时加载一页更早的历史,并且只挂载可见行窗口和少量额外缓冲行;仅含请求的分隔行并入下一个具备可测高度的虚拟项,语义行键和 ARIA 索引在向前补页后保持不变。选择、时间线导航、折叠、搜索和请求汇总只覆盖当前已加载的窗口。初始尾部完成定位前以及更早页面仍在等待时,记录表会用明确的加载行遮住真实记录。固定在记录表上方的 Overview 区域从左到右投影记录的真实开始时间与耗时;仍有更早记录未加载且 viewport 包含已加载时间域起点时,中性的省略号控件会标识被省略的前缀,并可加载一页更早历史,而不会为未知部分虚构耗时。助手时间条会区分记录到的 TTFT 与解码时间,悬停 500 ms 后可查看精确时刻和耗时详情。拖选一个区间会将记录表聚焦到活动区间与该闭区间有重叠的所有记录,清除选择则恢复完整分支。滚轮手势用于缩放时间域。右键单击会清除所选区间;在已放大的 viewport 上按住右键拖动则只会平移视图,不会改变该区间。初始视图和流式更新都会停留在尾部;向上滚动会暂停跟随,因此新记录不会打断对旧记录的检查。仅含内容更新的流式帧会保持虚拟行的键和高度不变、复用测量结果,并且不会重复写入末尾滚动位置。已完成的回复会在 Trajectory target State 中保留组装后的 blocks、计时与用量,共享 Session 窗口则保留原始 Event。Trajectory 要求会话壳将 composer 作为浮层置于全高记录表上方;其响应式纵向滚动容器会预留 composer 的实时高度,确保仍可滚动到最后几行。Trajectory 自有的 Definition 从共享 Session 窗口组装上下文谱系,以及因取消而冻结的助手和工具记录,因此 Trajectory 既不读取也不改变 Chat 会话快照。该包不提供 service,也不声明 Context 合并;它会注册 target 专属 Event Definition、Trajectory view builder,以及会话 `'conversation.view'` slot 环中的一个视图标签页。约定:api-contracts v3 §8。 ## 模型体验 diff --git a/packages/client/ui-trajectory/src/client/trajectory-assistant-definition.ts b/packages/client/ui-trajectory/src/client/trajectory-assistant-definition.ts index 8f0d9ff430..d610f6979b 100644 --- a/packages/client/ui-trajectory/src/client/trajectory-assistant-definition.ts +++ b/packages/client/ui-trajectory/src/client/trajectory-assistant-definition.ts @@ -255,17 +255,17 @@ function assistantRequest( ...(state.retry === undefined ? {} : { - error: state.retry.message, - retry: state.retry.retry, - ...(state.retry.maxRetries === undefined ? {} : { maxRetries: state.retry.maxRetries }), - retryDelayMs: state.retry.delayMs, - }), + error: state.retry.message, + retry: state.retry.retry, + ...(state.retry.maxRetries === undefined ? {} : { maxRetries: state.retry.maxRetries }), + retryDelayMs: state.retry.delayMs, + }), ...(node === undefined || node.interrupted === true ? {} : { - resultSeq: node.seq, - ...(node.provenance === undefined ? {} : { provenance: node.provenance }), - }), + resultSeq: node.seq, + ...(node.provenance === undefined ? {} : { provenance: node.provenance }), + }), ...(state.usage === undefined ? {} : { usage: state.usage }), } } @@ -383,14 +383,18 @@ const trajectoryTurnEndDefinition: ConversationNodeDefinition = { buildViewNode: context => context.state === undefined ? null : trajectoryNode(context, context.state.seq, { - kind: 'turn-end', - turn: context.state.turn, - time: context.state.time, - ...(context.state.error === undefined ? {} : { error: context.state.error }), - }), + kind: 'turn-end', + turn: context.state.turn, + time: context.state.time, + ...(context.state.error === undefined ? {} : { error: context.state.error }), + }), } -/** Register the Trajectory Assistant lifecycle. */ +/** + * Register the Trajectory Assistant lifecycle. + * + * @param ctx - Plugin context receiving the Definitions. + */ export function registerTrajectoryAssistantDefinition(ctx: Context): void { ctx.conversationEvents.register(trajectoryAssistantDefinition) ctx.conversationEvents.register(trajectoryTurnEndDefinition) diff --git a/packages/client/ui-trajectory/src/client/trajectory-compaction-definition.ts b/packages/client/ui-trajectory/src/client/trajectory-compaction-definition.ts index 65bab06059..de6d2af21b 100644 --- a/packages/client/ui-trajectory/src/client/trajectory-compaction-definition.ts +++ b/packages/client/ui-trajectory/src/client/trajectory-compaction-definition.ts @@ -61,18 +61,18 @@ function requestFromState( ...(summary?.type !== 'compact/summary' ? {} : { - resultSeq: summary.seq, - summary: summary.data.summary, - ...(summary.data.rawOutput === undefined ? {} : { rawOutput: summary.data.rawOutput }), - provenance: { provider: summary.data.provider, model: summary.data.model }, - requestConfig: { - provider: summary.data.provider, - model: summary.data.model, - purpose: 'compaction', - ...(summary.data.maxTokens === undefined ? {} : { maxTokens: summary.data.maxTokens }), - }, - ...(summary.data.usage === undefined ? {} : { usage: summary.data.usage }), - }), + resultSeq: summary.seq, + summary: summary.data.summary, + ...(summary.data.rawOutput === undefined ? {} : { rawOutput: summary.data.rawOutput }), + provenance: { provider: summary.data.provider, model: summary.data.model }, + requestConfig: { + provider: summary.data.provider, + model: summary.data.model, + purpose: 'compaction', + ...(summary.data.maxTokens === undefined ? {} : { maxTokens: summary.data.maxTokens }), + }, + ...(summary.data.usage === undefined ? {} : { usage: summary.data.usage }), + }), ...(checkpoint?.type === 'user/message' ? { replacementSeq: checkpoint.seq } : {}), } } @@ -126,13 +126,17 @@ const trajectorySessionEndDefinition: ConversationNodeDefinition context.state === undefined ? null : trajectoryNode(context, context.state.seq, { - kind: 'session-end', - seq: context.state.seq, - time: context.state.time, - }), + kind: 'session-end', + seq: context.state.seq, + time: context.state.time, + }), } -/** Register Trajectory compaction requests and session boundaries. */ +/** + * Register Trajectory compaction requests and session boundaries. + * + * @param ctx - Plugin context receiving the Definitions. + */ export function registerTrajectoryCompactionDefinitions(ctx: Context): void { ctx.conversationEvents.register(trajectoryCompactionDefinition) ctx.conversationEvents.register(trajectorySessionEndDefinition) diff --git a/packages/client/ui-trajectory/src/client/trajectory-definition-common.ts b/packages/client/ui-trajectory/src/client/trajectory-definition-common.ts index d11034b9b9..8c9c7d6489 100644 --- a/packages/client/ui-trajectory/src/client/trajectory-definition-common.ts +++ b/packages/client/ui-trajectory/src/client/trajectory-definition-common.ts @@ -5,14 +5,26 @@ import type { TrajectoryContribution, TrajectoryConversationViewNode, } from './trajectory-contract.ts' -/** Resolve the best loaded Location for one target-local Context. */ +/** + * Resolve the best loaded Location for one target-local Context. + * + * @param context - Context whose loaded matches provide the Location. + * @returns The start Location, first-match Location, or unresolved fallback. + */ export function trajectoryContextLocation( context: ConversationNodeContext, ): ConversationLocation { return context.start?.location ?? context.matches[0]?.location ?? { kind: 'unresolved' } } -/** Wrap one contribution in the Engine-owned target envelope. */ +/** + * Wrap one contribution in the Engine-owned target envelope. + * + * @param context - Context that owns the contribution identity. + * @param anchorSeq - Sequence used to order the contribution. + * @param data - Trajectory-specific contribution payload. + * @returns The contribution wrapped as a Trajectory view node. + */ export function trajectoryNode( context: ConversationNodeContext, anchorSeq: number, diff --git a/packages/client/ui-trajectory/src/client/trajectory-message-definitions.ts b/packages/client/ui-trajectory/src/client/trajectory-message-definitions.ts index 5f6b203e28..a35b6080db 100644 --- a/packages/client/ui-trajectory/src/client/trajectory-message-definitions.ts +++ b/packages/client/ui-trajectory/src/client/trajectory-message-definitions.ts @@ -86,20 +86,20 @@ const trajectoryMessageDefinition: ConversationNodeDefinition = { ?.state.claimed.has(String(event.data.id)) === true return claimed ? { - kind: 'steering', - messageId: event.data.id, - seq: event.seq, - time: event.time, - content: event.data.content, - source: event.data.source, - } + kind: 'steering', + messageId: event.data.id, + seq: event.seq, + time: event.time, + content: event.data.content, + source: event.data.source, + } : { - kind: 'user', - seq: event.seq, - time: event.time, - content: event.data.content, - source: event.data.source, - } + kind: 'user', + seq: event.seq, + time: event.time, + content: event.data.content, + source: event.data.source, + } }, update: context => context.state, buildViewNode: context => context.state === undefined @@ -107,7 +107,11 @@ const trajectoryMessageDefinition: ConversationNodeDefinition = { : trajectoryNode(context, context.state.seq, { kind: 'node', node: context.state }), } -/** Register Trajectory-owned inbox classification and message records. */ +/** + * Register Trajectory-owned inbox classification and message records. + * + * @param ctx - Plugin context receiving the Definitions. + */ export function registerTrajectoryMessageDefinitions(ctx: Context): void { ctx.conversationEvents.register(trajectoryInboxDefinition) ctx.conversationEvents.register(trajectoryMessageDefinition) diff --git a/packages/client/ui-trajectory/src/client/trajectory-request-header-definition.ts b/packages/client/ui-trajectory/src/client/trajectory-request-header-definition.ts index a6ec4e4597..4d8a0c9006 100644 --- a/packages/client/ui-trajectory/src/client/trajectory-request-header-definition.ts +++ b/packages/client/ui-trajectory/src/client/trajectory-request-header-definition.ts @@ -65,12 +65,16 @@ const trajectoryRequestHeaderDefinition: ConversationNodeDefinition context.state === undefined ? null : trajectoryNode(context, context.state.seq, { - kind: 'request-header', - header: context.state, - }), + kind: 'request-header', + header: context.state, + }), } -/** Register Trajectory request-header facts. */ +/** + * Register Trajectory request-header facts. + * + * @param ctx - Plugin context receiving the Definition. + */ export function registerTrajectoryRequestHeaderDefinition(ctx: Context): void { ctx.conversationEvents.register(trajectoryRequestHeaderDefinition) } diff --git a/packages/client/ui-trajectory/src/client/trajectory-snapshot-builder.ts b/packages/client/ui-trajectory/src/client/trajectory-snapshot-builder.ts index 613cd1e750..717172c9d8 100644 --- a/packages/client/ui-trajectory/src/client/trajectory-snapshot-builder.ts +++ b/packages/client/ui-trajectory/src/client/trajectory-snapshot-builder.ts @@ -50,11 +50,11 @@ function applyHeader( return header === undefined ? request : { - ...request, - prompt: header.prompt, - requestConfig: header.prompt.config, - ...(header.change === undefined ? {} : { promptChange: header.change }), - } + ...request, + prompt: header.prompt, + requestConfig: header.prompt.config, + ...(header.change === undefined ? {} : { promptChange: header.change }), + } } function withRequestConfig( @@ -70,7 +70,7 @@ function captureSchemas( output: Map, ): void { const name = 'kind' in block ? block.call?.name : block.name - const schema = name === undefined || name === null + const schema = name === undefined ? undefined : tools.find(candidate => candidate.name === name) if (schema !== undefined) output.set(block.callId, schema) @@ -216,7 +216,11 @@ export const trajectoryViewDefinition: ConversationViewDefinition< create: () => new TrajectorySnapshotBuilder(), } -/** Register the legacy-shape Trajectory target builder. */ +/** + * Register the stage-oriented Trajectory target builder. + * + * @param ctx - Plugin context receiving the view Definition. + */ export function registerTrajectoryConversationView(ctx: Context): void { ctx.conversationViews.register(trajectoryViewDefinition) } diff --git a/packages/client/ui-trajectory/src/client/trajectory-tool-definition.ts b/packages/client/ui-trajectory/src/client/trajectory-tool-definition.ts index 353d89070b..c72c6c8709 100644 --- a/packages/client/ui-trajectory/src/client/trajectory-tool-definition.ts +++ b/packages/client/ui-trajectory/src/client/trajectory-tool-definition.ts @@ -244,7 +244,11 @@ const trajectoryToolDefinition: ConversationNodeDefinition = { }, } -/** Register the Trajectory Tool lifecycle. */ +/** + * Register the Trajectory Tool lifecycle. + * + * @param ctx - Plugin context receiving the Definition. + */ export function registerTrajectoryToolDefinition(ctx: Context): void { ctx.conversationEvents.register(trajectoryToolDefinition) } diff --git a/packages/client/ui-trajectory/tests/views.spec.tsx b/packages/client/ui-trajectory/tests/views.spec.tsx index ab3f23d829..2439fb2de5 100644 --- a/packages/client/ui-trajectory/tests/views.spec.tsx +++ b/packages/client/ui-trajectory/tests/views.spec.tsx @@ -17,7 +17,6 @@ import { ConversationEventRegistry, ConversationViewRegistry, createSnapshotStore, EMPTY_CHAT_SNAPSHOT, } from '@deepseek-ai/dsh-client-runtime/client' -import type { UseSession } from '@deepseek-ai/dsh-client-web-react' import { SlotsService } from '@deepseek-ai/dsh-client-runtime/client' import type { ConversationSnapshot, RequestView, @@ -88,7 +87,7 @@ function historySnapshot( sessionId: SID, views: { get: target => target === 'trajectory' ? trajectory : undefined, - } as ConversationSnapshot['views'], + }, chat: EMPTY_CHAT_SNAPSHOT, nodes, turnTimings: new Map(), @@ -136,7 +135,7 @@ function standaloneDuration(): Pick< function fakeSession(nodes: ConversationSnapshot['nodes']) { const store = createSnapshotStore(historySnapshot(nodes)) - return { store, useSession: bindSnapshotSelector(store) as UseSession } + return { store, useSession: bindSnapshotSelector(store) } } /** Empty sessions-list hook; breadcrumbs therefore fall back to the raw id. */ @@ -204,7 +203,7 @@ function tabsOf(slots: SlotsService): ViewTab[] { /** Mount the strict Session header/body over the ring ledger with outlet-faithful render shares. */ function mount(slots: SlotsService, nodes: ConversationSnapshot['nodes'] = NODES) { const sessionSnapshot = sessionSnapshots.get(slots) ?? createSnapshotStore(historySnapshot(nodes)) - const useSession = bindSnapshotSelector(sessionSnapshot) as UseSession + const useSession = bindSnapshotSelector(sessionSnapshot) const chat = createChatStore().create() const views = { list: () => tabsOf(slots), diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 646244da69..40f2643417 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1771,9 +1771,6 @@ importers: '@deepseek-ai/dsh-commands': specifier: workspace:^ version: link:../../interaction/commands - '@deepseek-ai/dsh-compact': - specifier: workspace:^ - version: link:../../compact/compact '@deepseek-ai/dsh-host-apiproxy': specifier: workspace:^ version: link:../../host/apiproxy From 3469de58eb178e7662ece6ce061a26a7b7eaacd8 Mon Sep 17 00:00:00 2001 From: imccyu <276526105+imccyu@users.noreply.github.com> Date: Mon, 10 Aug 2026 19:26:54 +0800 Subject: [PATCH 24/36] fix(ui-trajectory): consume prompt changes once --- .../src/client/trajectory-snapshot-builder.ts | 11 +++- .../tests/snapshot-builder.spec.ts | 62 +++++++++++++++++++ 2 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 packages/client/ui-trajectory/tests/snapshot-builder.spec.ts diff --git a/packages/client/ui-trajectory/src/client/trajectory-snapshot-builder.ts b/packages/client/ui-trajectory/src/client/trajectory-snapshot-builder.ts index 717172c9d8..585975b0aa 100644 --- a/packages/client/ui-trajectory/src/client/trajectory-snapshot-builder.ts +++ b/packages/client/ui-trajectory/src/client/trajectory-snapshot-builder.ts @@ -46,6 +46,7 @@ function headerFor( function applyHeader( request: Extract, header: TrajectoryRequestHeaderState | undefined, + includeChange: boolean, ): Extract { return header === undefined ? request @@ -53,7 +54,7 @@ function applyHeader( ...request, prompt: header.prompt, requestConfig: header.prompt.config, - ...(header.change === undefined ? {} : { promptChange: header.change }), + ...(includeChange && header.change !== undefined ? { promptChange: header.change } : {}), } } @@ -150,6 +151,7 @@ export class TrajectorySnapshotBuilder implements ConversationViewBuilder< const boundaries: { seq: number; time: number }[] = [] const turnEndings: { turn: number; time: number; error?: string }[] = [] const callSchemas = new Map() + const consumedPromptChanges = new Set() let partial: TrajectorySnapshot['partial'] = null const runningCalls: TrajectorySnapshot['runningCalls'][number][] = [] @@ -163,7 +165,12 @@ export class TrajectorySnapshotBuilder implements ConversationViewBuilder< const header = data.request === undefined ? undefined : headerFor(data.request, headers) if (data.node !== undefined) finalized.push(withRequestConfig(data.node, header?.prompt)) if (data.partial !== null) partial = data.partial - if (data.request !== undefined) requests.push(applyHeader(data.request, header)) + if (data.request !== undefined) { + const includeChange = header?.change !== undefined + && !consumedPromptChanges.has(header.seq) + requests.push(applyHeader(data.request, header, includeChange)) + if (includeChange) consumedPromptChanges.add(header.seq) + } continue } if (data.kind === 'tool') { diff --git a/packages/client/ui-trajectory/tests/snapshot-builder.spec.ts b/packages/client/ui-trajectory/tests/snapshot-builder.spec.ts new file mode 100644 index 0000000000..87e484a433 --- /dev/null +++ b/packages/client/ui-trajectory/tests/snapshot-builder.spec.ts @@ -0,0 +1,62 @@ +import { describe, expect, it } from 'vitest' +import type { RequestView } from '@deepseek-ai/dsh-client-runtime/client' +import type { TrajectoryConversationViewNode } from '../src/client/trajectory-contract.ts' +import { TrajectorySnapshotBuilder } from '../src/client/trajectory-snapshot-builder.ts' + +function assistantRequest(startSeq: number, step: number): Extract { + return { + purpose: 'assistant', + startSeq, + turn: 1, + step, + startedAt: startSeq, + completedAt: startSeq + 1, + status: 'complete', + } +} + +describe('TrajectorySnapshotBuilder', () => { + it('inherits one request header across requests without repeating its prompt change', () => { + const prompt = { + config: { provider: 'test', model: 'test' }, + system: 'one initial prompt', + tools: [], + } + const nodes: TrajectoryConversationViewNode[] = [ + { + key: 'header', + kind: 'trajectory-request-header', + id: '2', + target: 'trajectory', + anchorSeq: 2, + data: { + kind: 'request-header', + header: { + seq: 2, + time: 2, + prompt, + change: { seq: 2, time: 2, kind: 'initial' }, + location: { kind: 'session' }, + }, + }, + }, + ...[assistantRequest(3, 1), assistantRequest(5, 2)].map(request => ({ + key: `assistant:${request.step}`, + kind: 'trajectory-assistant-step', + id: `1:${request.step}`, + target: 'trajectory' as const, + anchorSeq: request.startSeq, + data: { kind: 'assistant' as const, partial: null, request }, + })), + ] + + const snapshot = new TrajectorySnapshotBuilder().replace({ nodes }) + + expect(snapshot.requests.map(request => request.purpose === 'assistant' + ? request.prompt?.system + : undefined)).toEqual(['one initial prompt', 'one initial prompt']) + expect(snapshot.requests.map(request => request.purpose === 'assistant' + ? request.promptChange?.kind + : undefined)).toEqual(['initial', undefined]) + }) +}) From fc4df896a089956594a94f4da945ae9c44659328 Mon Sep 17 00:00:00 2001 From: imccyu <276526105+imccyu@users.noreply.github.com> Date: Mon, 10 Aug 2026 20:38:51 +0800 Subject: [PATCH 25/36] perf(ui-trajectory): index trajectory snapshot assembly --- .../src/client/trajectory-snapshot-builder.ts | 130 +++++++++---- .../tests/snapshot-builder.spec.ts | 171 +++++++++++++++++- 2 files changed, 262 insertions(+), 39 deletions(-) diff --git a/packages/client/ui-trajectory/src/client/trajectory-snapshot-builder.ts b/packages/client/ui-trajectory/src/client/trajectory-snapshot-builder.ts index 585975b0aa..2f4c697275 100644 --- a/packages/client/ui-trajectory/src/client/trajectory-snapshot-builder.ts +++ b/packages/client/ui-trajectory/src/client/trajectory-snapshot-builder.ts @@ -11,6 +11,8 @@ import type { const EMPTY_LIST: readonly never[] = [] const EMPTY_CONTEXTS = [{ id: 0, nodes: EMPTY_LIST }] +type AssistantRequest = Extract +type ToolSchema = ConversationPromptSnapshot['tools'][number] /** Stable empty target used until a Session has assembled Trajectory records. */ export const EMPTY_TRAJECTORY_SNAPSHOT: TrajectorySnapshot = { @@ -23,31 +25,31 @@ export const EMPTY_TRAJECTORY_SNAPSHOT: TrajectorySnapshot = { runningCalls: EMPTY_LIST, } -function coordinates( - header: TrajectoryRequestHeaderState, -): { turn?: number; step?: number } { +function stepKey(turn: number, step: number): string { + return `${turn}\u0000${step}` +} + +function headerStepKey(header: TrajectoryRequestHeaderState): string | undefined { const location = header.location - if (location.kind === 'step') return { turn: location.turn.turn, step: location.step.step } - if (location.kind === 'turn') return { turn: location.turn.turn } - return {} + return location.kind === 'step' + ? stepKey(location.turn.turn, location.step.step) + : undefined } function headerFor( - request: Extract, - headers: readonly TrajectoryRequestHeaderState[], + request: AssistantRequest, + headersByStep: ReadonlyMap, + previous: TrajectoryRequestHeaderState | undefined, ): TrajectoryRequestHeaderState | undefined { - const exact = headers.findLast((header) => { - const location = coordinates(header) - return location.turn === request.turn && location.step === request.step - }) - return exact ?? headers.findLast(header => header.seq < request.startSeq) + return headersByStep.get(stepKey(request.turn, request.step)) + ?? (previous !== undefined && previous.seq < request.startSeq ? previous : undefined) } function applyHeader( - request: Extract, + request: AssistantRequest, header: TrajectoryRequestHeaderState | undefined, includeChange: boolean, -): Extract { +): AssistantRequest { return header === undefined ? request : { @@ -67,26 +69,39 @@ function withRequestConfig( function captureSchemas( block: ToolCallBlock, - tools: readonly ConversationPromptSnapshot['tools'][number][], - output: Map, + toolsByName: ReadonlyMap, + output: Map, ): void { const name = 'kind' in block ? block.call?.name : block.name - const schema = name === undefined - ? undefined - : tools.find(candidate => candidate.name === name) + const schema = name === undefined ? undefined : toolsByName.get(name) if (schema !== undefined) output.set(block.callId, schema) - for (const child of block.subCalls) captureSchemas(child, tools, output) + for (const child of block.subCalls) captureSchemas(child, toolsByName, output) +} + +function indexTools(tools: readonly ToolSchema[]): ReadonlyMap { + return new Map(tools.map(tool => [tool.name, tool])) } function interruptCompactions( requests: RequestView[], boundaries: readonly { seq: number; time: number }[], ): void { + let nextRequest = 0 + const runningCompactions: number[] = [] for (const boundary of boundaries) { - const index = requests.findLastIndex(request => - request.purpose === 'compaction' - && request.startSeq < boundary.seq - && request.status === 'running') + while (nextRequest < requests.length) { + const request = requests[nextRequest] + if (request === undefined || request.startSeq >= boundary.seq) break + if (request.purpose === 'compaction' && request.status === 'running') { + runningCompactions.push(nextRequest) + } + nextRequest++ + } + let index = runningCompactions.pop() + while (index !== undefined && requests[index]?.status !== 'running') { + index = runningCompactions.pop() + } + if (index === undefined) continue const request = requests[index] if (request?.purpose !== 'compaction') continue requests[index] = { @@ -102,10 +117,14 @@ function applyTurnErrors( requests: RequestView[], endings: readonly { turn: number; time: number; error?: string }[], ): void { + const lastAssistantByTurn = new Map() + for (const [index, request] of requests.entries()) { + if (request.purpose === 'assistant') lastAssistantByTurn.set(request.turn, index) + } for (const ending of endings) { if (ending.error === undefined) continue - const index = requests.findLastIndex(request => - request.purpose === 'assistant' && request.turn === ending.turn) + const index = lastAssistantByTurn.get(ending.turn) + if (index === undefined) continue const request = requests[index] if (request?.purpose !== 'assistant') continue requests[index] = { @@ -123,6 +142,8 @@ export class TrajectorySnapshotBuilder implements ConversationViewBuilder< TrajectorySnapshot > { private readonly nodes = new Map() + private readonly positions = new Map() + private contributions: TrajectoryConversationViewNode[] = [] readonly empty = EMPTY_TRAJECTORY_SNAPSHOT replace(input: { @@ -130,39 +151,62 @@ export class TrajectorySnapshotBuilder implements ConversationViewBuilder< }): TrajectorySnapshot { this.nodes.clear() for (const node of input.nodes) this.nodes.set(node.key, node) + this.rebuildContributions() return this.snapshot() } apply(input: { readonly upserts: readonly TrajectoryConversationViewNode[] }): TrajectorySnapshot { - for (const node of input.upserts) this.nodes.set(node.key, node) + let structural = false + for (const node of input.upserts) { + const previous = this.nodes.get(node.key) + this.nodes.set(node.key, node) + if (previous === undefined || previous.anchorSeq !== node.anchorSeq) { + structural = true + continue + } + const position = this.positions.get(node.key) + if (position === undefined) structural = true + else this.contributions[position] = node + } + if (structural) this.rebuildContributions() return this.snapshot() } private snapshot(): TrajectorySnapshot { - const contributions = [...this.nodes.values()] - .sort((left, right) => left.anchorSeq - right.anchorSeq || left.key.localeCompare(right.key)) - const headers = contributions.flatMap(node => node.data.kind === 'request-header' - ? [node.data.header] - : []) + const headersByStep = new Map() + for (const contribution of this.contributions) { + if (contribution.data.kind !== 'request-header') continue + const key = headerStepKey(contribution.data.header) + if (key !== undefined) headersByStep.set(key, contribution.data.header) + } const finalized: ConversationNode[] = [] const requests: RequestView[] = [] const boundaries: { seq: number; time: number }[] = [] const turnEndings: { turn: number; time: number; error?: string }[] = [] - const callSchemas = new Map() + const callSchemas = new Map() const consumedPromptChanges = new Set() + let previousHeader: TrajectoryRequestHeaderState | undefined + let previousTools: ReadonlyMap = new Map() let partial: TrajectorySnapshot['partial'] = null const runningCalls: TrajectorySnapshot['runningCalls'][number][] = [] - for (const contribution of contributions) { + for (const contribution of this.contributions) { const data = contribution.data + if (data.kind === 'request-header') { + previousHeader = data.header + previousTools = indexTools(data.header.prompt.tools) + continue + } if (data.kind === 'node') { finalized.push(data.node) continue } if (data.kind === 'assistant') { - const header = data.request === undefined ? undefined : headerFor(data.request, headers) + const header = data.request === undefined + ? undefined + : headerFor(data.request, headersByStep, previousHeader) if (data.node !== undefined) finalized.push(withRequestConfig(data.node, header?.prompt)) if (data.partial !== null) partial = data.partial if (data.request !== undefined) { @@ -176,8 +220,9 @@ export class TrajectorySnapshotBuilder implements ConversationViewBuilder< if (data.kind === 'tool') { if ('kind' in data.root) finalized.push(data.root) else runningCalls.push(data.root) - const header = headers.findLast(candidate => candidate.seq < contribution.anchorSeq) - if (header !== undefined) captureSchemas(data.root, header.prompt.tools, callSchemas) + if (previousHeader !== undefined && previousHeader.seq < contribution.anchorSeq) { + captureSchemas(data.root, previousTools, callSchemas) + } continue } if (data.kind === 'compaction') { @@ -212,6 +257,15 @@ export class TrajectorySnapshotBuilder implements ConversationViewBuilder< runningCalls, } } + + private rebuildContributions(): void { + this.contributions = [...this.nodes.values()] + .sort((left, right) => left.anchorSeq - right.anchorSeq || left.key.localeCompare(right.key)) + this.positions.clear() + for (const [index, contribution] of this.contributions.entries()) { + this.positions.set(contribution.key, index) + } + } } /** Trajectory target factory preserving the existing stage-oriented view model. */ diff --git a/packages/client/ui-trajectory/tests/snapshot-builder.spec.ts b/packages/client/ui-trajectory/tests/snapshot-builder.spec.ts index 87e484a433..d3cf64ac2d 100644 --- a/packages/client/ui-trajectory/tests/snapshot-builder.spec.ts +++ b/packages/client/ui-trajectory/tests/snapshot-builder.spec.ts @@ -1,6 +1,8 @@ import { describe, expect, it } from 'vitest' import type { RequestView } from '@deepseek-ai/dsh-client-runtime/client' -import type { TrajectoryConversationViewNode } from '../src/client/trajectory-contract.ts' +import type { + TrajectoryContribution, TrajectoryConversationViewNode, TrajectoryRequestHeaderState, +} from '../src/client/trajectory-contract.ts' import { TrajectorySnapshotBuilder } from '../src/client/trajectory-snapshot-builder.ts' function assistantRequest(startSeq: number, step: number): Extract { @@ -15,6 +17,47 @@ function assistantRequest(startSeq: number, step: number): Extract undefined } + const stepLocation = { + turn, + step, + start: undefined, + end: undefined, + status: 'unknown' as const, + data, + } + const turnLocation = { + turn, + start: undefined, + end: undefined, + status: 'unknown' as const, + steps: [stepLocation], + data, + } + return { kind: 'step', turn: turnLocation, step: stepLocation } +} + +function compactionRequest(startSeq: number): Extract { + return { + purpose: 'compaction', + startSeq, + turn: null, + step: 0, + startedAt: startSeq, + completedAt: null, + status: 'running', + } +} + describe('TrajectorySnapshotBuilder', () => { it('inherits one request header across requests without repeating its prompt change', () => { const prompt = { @@ -59,4 +102,130 @@ describe('TrajectorySnapshotBuilder', () => { ? request.promptChange?.kind : undefined)).toEqual(['initial', undefined]) }) + + it('indexes exact step headers and the active tool schema without backward scans', () => { + const basePrompt = { + config: { provider: 'test', model: 'base' }, + system: 'base prompt', + tools: [{ name: 'read', description: 'Read', parameters: { type: 'object' } }], + } + const exactPrompt = { + config: { provider: 'test', model: 'exact' }, + system: 'exact prompt', + tools: [{ name: 'edit', description: 'Edit', parameters: { type: 'object' } }], + } + const nodes: TrajectoryConversationViewNode[] = [ + contribution('header:base', 2, { + kind: 'request-header', + header: { + seq: 2, + time: 2, + prompt: basePrompt, + change: { seq: 2, time: 2, kind: 'initial' }, + location: { kind: 'session' }, + }, + }), + contribution('assistant:1', 3, { + kind: 'assistant', + partial: null, + request: assistantRequest(3, 1), + }), + contribution('assistant:2', 5, { + kind: 'assistant', + partial: null, + request: assistantRequest(5, 2), + }), + contribution('header:exact', 6, { + kind: 'request-header', + header: { + seq: 6, + time: 6, + prompt: exactPrompt, + change: { seq: 6, time: 6, kind: 'system', previous: basePrompt }, + location: stepLocation(1, 2), + }, + }), + contribution('tool', 7, { + kind: 'tool', + root: { + callId: 'call-edit', + name: 'edit', + argsRaw: '{}', + turn: 1, + step: 2, + time: 7, + callView: null, + subCalls: [], + }, + }), + ] + + const snapshot = new TrajectorySnapshotBuilder().replace({ nodes }) + + expect(snapshot.requests.map(request => request.purpose === 'assistant' + ? request.prompt?.system + : undefined)).toEqual(['base prompt', 'exact prompt']) + expect(snapshot.callSchemas.get('call-edit')).toEqual(exactPrompt.tools[0]) + }) + + it('applies session boundaries and turn errors with linear request indexes', () => { + const nodes: TrajectoryConversationViewNode[] = [ + ...[assistantRequest(1, 1), assistantRequest(3, 2)].map(request => contribution( + `assistant:${request.step}`, + request.startSeq, + { kind: 'assistant', partial: null, request }, + )), + contribution('turn-end', 5, { + kind: 'turn-end', + turn: 1, + time: 5, + error: 'turn failed', + }), + contribution('compact:10', 10, { + kind: 'compaction', + request: compactionRequest(10), + }), + contribution('compact:12', 12, { + kind: 'compaction', + request: compactionRequest(12), + }), + contribution('session-end:14', 14, { kind: 'session-end', seq: 14, time: 14 }), + contribution('session-end:16', 16, { kind: 'session-end', seq: 16, time: 16 }), + ] + + const snapshot = new TrajectorySnapshotBuilder().replace({ nodes }) + + expect(snapshot.requests).toMatchObject([ + { purpose: 'assistant', step: 1, status: 'complete' }, + { purpose: 'assistant', step: 2, status: 'error', error: 'turn failed' }, + { purpose: 'compaction', startSeq: 10, status: 'error', completedAt: 16 }, + { purpose: 'compaction', startSeq: 12, status: 'error', completedAt: 14 }, + ]) + }) + + it('keeps cached contribution order across content updates and structural inserts', () => { + const builder = new TrajectorySnapshotBuilder() + const first = contribution('assistant:1', 1, { + kind: 'assistant', partial: null, request: assistantRequest(1, 1), + }) + const last = contribution('assistant:3', 5, { + kind: 'assistant', partial: null, request: assistantRequest(5, 3), + }) + expect(builder.replace({ nodes: [last, first] }).requests.map(request => request.startSeq)) + .toEqual([1, 5]) + + const updatedLast = contribution('assistant:3', 5, { + kind: 'assistant', + partial: null, + request: { ...assistantRequest(5, 3), status: 'error', error: 'failed' }, + }) + expect(builder.apply({ upserts: [updatedLast] }).requests.map(request => request.startSeq)) + .toEqual([1, 5]) + + const middle = contribution('assistant:2', 3, { + kind: 'assistant', partial: null, request: assistantRequest(3, 2), + }) + expect(builder.apply({ upserts: [middle] }).requests.map(request => request.startSeq)) + .toEqual([1, 3, 5]) + }) }) From b3d3e423f22a77d99d9f4660b5dae51679a9958c Mon Sep 17 00:00:00 2001 From: imccyu <276526105+imccyu@users.noreply.github.com> Date: Mon, 10 Aug 2026 20:54:37 +0800 Subject: [PATCH 26/36] fix(ui-trajectory): retain parallel tool interruptions --- .../src/client/TrajectoryView.tsx | 5 ++-- .../src/client/context-branches.ts | 19 ++++++++++--- .../tests/context-branches.spec.ts | 27 +++++++++++++++++++ 3 files changed, 46 insertions(+), 5 deletions(-) diff --git a/packages/client/ui-trajectory/src/client/TrajectoryView.tsx b/packages/client/ui-trajectory/src/client/TrajectoryView.tsx index 95476ac851..70e92f72fd 100644 --- a/packages/client/ui-trajectory/src/client/TrajectoryView.tsx +++ b/packages/client/ui-trajectory/src/client/TrajectoryView.tsx @@ -9,6 +9,7 @@ import type { } from '@deepseek-ai/dsh-client-runtime/client' import { deriveTrajectoryContextBranches, trajectoryBranchContainsRequest, + trajectoryNodeIdentity, } from './context-branches.ts' import { TrajectoryTable, @@ -229,9 +230,9 @@ export function TrajectoryView({ const currentBranch = branches.at(-1) if (currentBranch === undefined) throw new Error('trajectory branch projection must not be empty') const selectedNodes = useMemo(() => { - const selected = new Map(currentBranch.nodes.map(node => [node.seq, node])) + const selected = new Map(currentBranch.nodes.map(node => [trajectoryNodeIdentity(node), node])) for (const node of interruptedNodes) { - selected.set(node.seq, node) + selected.set(trajectoryNodeIdentity(node), node) } return [...selected.values()].sort((left, right) => left.seq - right.seq) }, [currentBranch.nodes, interruptedNodes]) diff --git a/packages/client/ui-trajectory/src/client/context-branches.ts b/packages/client/ui-trajectory/src/client/context-branches.ts index 2501511c50..2f665bb413 100644 --- a/packages/client/ui-trajectory/src/client/context-branches.ts +++ b/packages/client/ui-trajectory/src/client/context-branches.ts @@ -23,11 +23,24 @@ interface MutableBranch { key: string contexts: ConversationContext[] latest: ConversationContext - nodes: Map + nodes: Map startSeq: number retainedSurfaceSeqs: Set } +/** + * Resolve the identity used while coalescing one trajectory branch. + * Synthetic tool interruptions share their closing boundary seq, so their + * call ids distinguish parallel roots without inventing false event order. + * @param node - projected conversation node. + * @returns branch-local semantic identity. + */ +export function trajectoryNodeIdentity(node: ConversationNode): string { + return node.kind === 'tool-result' + ? `tool-result\u0000${String(node.seq)}\u0000${node.callId}` + : `seq\u0000${String(node.seq)}` +} + function isCompactionCheckpoint(node: ConversationNode): boolean { if (node.kind !== 'context') return false const source = node.source @@ -73,7 +86,7 @@ export function deriveTrajectoryContextBranches( latest: context, nodes: new Map( [...inheritedNodes, ...context.nodes.filter(node => !isCompactionCheckpoint(node))] - .map(node => [node.seq, node]), + .map(node => [trajectoryNodeIdentity(node), node]), ), startSeq: context.originSeq ?? Number.NEGATIVE_INFINITY, retainedSurfaceSeqs, @@ -85,7 +98,7 @@ export function deriveTrajectoryContextBranches( branch.contexts.push(context) branch.latest = context for (const node of context.nodes) { - if (!isCompactionCheckpoint(node)) branch.nodes.set(node.seq, node) + if (!isCompactionCheckpoint(node)) branch.nodes.set(trajectoryNodeIdentity(node), node) } } return mutable.map(branch => ({ diff --git a/packages/client/ui-trajectory/tests/context-branches.spec.ts b/packages/client/ui-trajectory/tests/context-branches.spec.ts index e608b9fd68..9885e9a4f9 100644 --- a/packages/client/ui-trajectory/tests/context-branches.spec.ts +++ b/packages/client/ui-trajectory/tests/context-branches.spec.ts @@ -34,6 +34,23 @@ const current = { source: { kind: 'plugin', plugin: 'rewind' }, } as ConversationNode +function interruptedTool(callId: string): ConversationNode { + return { + kind: 'tool-result', + seq: 19.2, + time: 20, + callId, + call: { name: 'parallel', argsRaw: '{}' }, + callTime: 10, + content: [], + isError: true, + error: { name: 'Interrupted', code: 'interrupted' }, + callView: null, + resultView: null, + subCalls: [], + } +} + function request( purpose: RequestView['purpose'], startSeq: number, @@ -99,4 +116,14 @@ describe('trajectory context branches', () => { expect(branch(1)?.key).toBe(branch(9)?.key) }) + + it('retains parallel tool interruptions that share one closing boundary', () => { + const branch = deriveTrajectoryContextBranches([{ + id: 0, + nodes: [interruptedTool('call-a'), interruptedTool('call-b')], + }])[0] + + expect(branch?.nodes.map(node => node.kind === 'tool-result' ? node.callId : undefined)) + .toEqual(['call-a', 'call-b']) + }) }) From 62f5d050390904852b8308b6bd4fee0246265d84 Mon Sep 17 00:00:00 2001 From: imccyu <276526105+imccyu@users.noreply.github.com> Date: Mon, 10 Aug 2026 21:35:57 +0800 Subject: [PATCH 27/36] fix(ui-trajectory): tighten conversation assembly contracts --- ...-27-trajectory-inspection-ledger.i18n.yaml | 4 +- ...2026-07-27-trajectory-inspection-ledger.md | 8 +- ...6-07-27-trajectory-inspection-ledger.zh.md | 8 +- .../adding-a-conversation-node.i18n.yaml | 4 +- docs/cookbook/adding-a-conversation-node.md | 7 +- .../cookbook/adding-a-conversation-node.zh.md | 7 +- .../tests/conversation-assembler.spec.ts | 107 +++++-- .../tests/conversation-registry.spec.ts | 34 +++ .../client/ui-trajectory/README.i18n.yaml | 4 +- packages/client/ui-trajectory/README.md | 2 +- packages/client/ui-trajectory/README.zh.md | 2 +- packages/client/ui-trajectory/package.json | 6 + .../src/client/TrajectoryView.tsx | 66 +---- .../src/client/context-branches.ts | 135 --------- .../client/ui-trajectory/src/client/index.ts | 4 +- .../client/trajectory-assistant-definition.ts | 4 + .../src/client/trajectory-contract.ts | 4 +- .../client/trajectory-definition-common.ts | 16 +- .../client/trajectory-message-definitions.ts | 4 + .../src/client/trajectory-snapshot-builder.ts | 5 - .../src/client/trajectory-tool-definition.ts | 25 +- .../ui-trajectory/tests/client-bundle.spec.ts | 6 + .../tests/context-branches.spec.ts | 129 -------- .../tests/conversation-definitions.spec.ts | 276 ++++++++++++++++++ .../client/ui-trajectory/tests/views.spec.tsx | 174 ++--------- packages/client/ui-trajectory/tsconfig.json | 9 + pnpm-lock.yaml | 9 + 27 files changed, 525 insertions(+), 534 deletions(-) delete mode 100644 packages/client/ui-trajectory/src/client/context-branches.ts delete mode 100644 packages/client/ui-trajectory/tests/context-branches.spec.ts create mode 100644 packages/client/ui-trajectory/tests/conversation-definitions.spec.ts diff --git a/.agents/notes/implemented/feature/2026-07-27-trajectory-inspection-ledger.i18n.yaml b/.agents/notes/implemented/feature/2026-07-27-trajectory-inspection-ledger.i18n.yaml index 1e7284378c..38bd4b3d9e 100644 --- a/.agents/notes/implemented/feature/2026-07-27-trajectory-inspection-ledger.i18n.yaml +++ b/.agents/notes/implemented/feature/2026-07-27-trajectory-inspection-ledger.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-07-27-trajectory-inspection-ledger.md -2026-07-27-trajectory-inspection-ledger.md: c09213d35e984ca717d283d45259f61d413407a3 -2026-07-27-trajectory-inspection-ledger.zh.md: 9d2c615dea5b0774201118a0b0abb9862a228690 +2026-07-27-trajectory-inspection-ledger.md: c46b9dbc564a8c3c83792335427614c92a015fce +2026-07-27-trajectory-inspection-ledger.zh.md: 20811f7a23fe1c9ee69dce24c975f6343eaff6df diff --git a/.agents/notes/implemented/feature/2026-07-27-trajectory-inspection-ledger.md b/.agents/notes/implemented/feature/2026-07-27-trajectory-inspection-ledger.md index c09213d35e..c46b9dbc56 100644 --- a/.agents/notes/implemented/feature/2026-07-27-trajectory-inspection-ledger.md +++ b/.agents/notes/implemented/feature/2026-07-27-trajectory-inspection-ledger.md @@ -12,17 +12,17 @@ Trajectory has to make prose, machine payloads, token usage, timing, and nested **Render a compact, turn-aware event ledger with a local record inspector, using the existing DeepSeek design system.** -- The ledger keeps session events in sequence within rewind-delimited branches. Turn boundaries use a slightly heavier rule, the raw Turn id, and a continuous left rail; Request boundaries appear as small points integrated into that structure and use one chronological numbering space across ordinary and compaction requests. +- The ledger keeps materialized business records in Session Event order within the loaded window. Turn boundaries use a slightly heavier rule, the raw Turn id, and a continuous left rail; Request boundaries appear as small points integrated into that structure and use one chronological numbering space across ordinary and compaction requests. - Event kind and content form the two stable columns. Role tags align toward the content, nested subtools receive a small indentation, and CSS truncation preserves the available preview width. Token usage and duration stay in the inspector. - Product prose uses the existing sans stack. Turn ids, token counts, durations, tool calls, raw payloads, and other machine data use the existing code stack. - Existing theme tokens own both light and dark rendering. Neutral borders and surfaces form the structure; distinct low-emphasis role hues support scanning without carrying success or failure meaning, while business blue identifies selection, links, and focus. -- Session owns one contiguous Event window, paging state, live gap repair, and reconnect rebuild. Chat and Trajectory register separate business Definitions against the shared `ConversationNodeAssembler`; Trajectory reads its target snapshot from `Session.views` and requests one older Session page when the user reaches the loaded range's top. Its Definitions and target builder derive event order, context lineage, schema index, and Requests without making those structures part of the Chat snapshot. +- Session owns one contiguous Event window, paging state, live gap repair, and reconnect rebuild. Chat and Trajectory register separate business Definitions against the shared `ConversationNodeAssembler`; Trajectory reads its target snapshot from `Session.views` and requests one older Session page when the user reaches the loaded range's top. Its Definitions and target builder derive event order, the schema index, and Requests without making those structures part of the Chat snapshot. - Ordinary generation and compaction calls form one chronological Request projection, distinguished by purpose rather than separate collections. Effective prompt state and its change ride the Request that introduced them; compaction and prompt changes are not independent inspection entities. Request numbering and cumulative usage cover the loaded history window and expand as older pages arrive. - Call schemas come from the active recorded Request header. Keyless snapshot fixtures deliberately replace that catalog with the non-array `{{tools}}` token, which the durable inspection boundary treats as unavailable instead of attempting to project or fabricate schemas. - Selecting a record or Request opens an inspector inside Trajectory. Tabs and Summary sections follow the selected entity: Markdown messages expose rendered content, source fields, provider/model fields, and hierarchy views; tools add JSON payload/result and schema views; Requests add options, usage, timing, and result navigation. Scrollable Summary regions keep their scrollbar thumbs transparent until hover or `focus-within`, while retaining the scrollbar reservation and scroll behavior. Images render as media rather than serialized data. - Turn folding removes all rows after its first record and replaces them with a compact step/tool-call count; Assistant folding applies the same interaction to its tool-call descendants. Global controls fold or expand both levels. - A long ledger initially positions the loaded tail at the bottom and mounts only the viewport's row window plus bounded overscan. Request-only separators join the next measurable virtual item, with a terminal separator retaining its own fixed clearance, so the virtualizer never owns a zero-height item. Semantic DOM-safe row keys and ARIA indexes expose identity independently from mount position. A tail with known older history virtualizes immediately even when its loaded projection is below the ordinary row threshold. Stable-key virtualizer anchoring preserves the visible item across prepends and appends; the manual scroll-height fallback applies only when completing pagination disables virtualization. Selection, timeline focus, folding, search, and bottom following address records by stable event or tool-call identity rather than requiring their DOM rows to exist. An explicit loading row covers records until initial positioning finishes and while an older Session page is pending. -- The separate Waterfall tab is removed. A fixed Overview above the ledger projects every loaded record with known `startedAt` onto three semantic timing lanes using its own duration. While an older prefix remains unloaded and the viewport includes the loaded domain's start, a neutral ellipsis control covers the truncated edge and loads one earlier page without assigning unknown history a fabricated duration; hovering that control suppresses the ordinary timeline cursor. Finalized Assistant spans divide the recorded interval at the first non-empty token delta, so distinct TTFT and decoding colors retain their actual ratio; incomplete timing falls back to one Assistant color. Hovering for 500 ms exposes exact start/end, total duration, TTFT, and decoding time without relying on the browser's native tooltip delay. Dragging left or right commits an inclusive interval filter: any record whose active interval overlaps either boundary remains visible, records without known timing leave the focused ledger, and clearing the selection restores the full branch. Wheel gestures zoom the time domain. A right-button click clears the interval selection; dragging instead pans an already zoomed viewport without mutating it. The Overview keeps the full time domain while focused so the selection can be resized or cleared without losing orientation. +- The separate Waterfall tab is removed. A fixed Overview above the ledger projects every loaded record with known `startedAt` onto three semantic timing lanes using its own duration. While an older prefix remains unloaded and the viewport includes the loaded domain's start, a neutral ellipsis control covers the truncated edge and loads one earlier page without assigning unknown history a fabricated duration; hovering that control suppresses the ordinary timeline cursor. Finalized Assistant spans divide the recorded interval at the first non-empty token delta, so distinct TTFT and decoding colors retain their actual ratio; incomplete timing falls back to one Assistant color. Hovering for 500 ms exposes exact start/end, total duration, TTFT, and decoding time without relying on the browser's native tooltip delay. Dragging left or right commits an inclusive interval filter: any record whose active interval overlaps either boundary remains visible, records without known timing leave the focused ledger, and clearing the selection restores the full loaded ledger. Wheel gestures zoom the time domain. A right-button click clears the interval selection; dragging instead pans an already zoomed viewport without mutating it. The Overview keeps the full time domain while focused so the selection can be resized or cleared without losing orientation. - Live history updates retain the ledger's bottom position only while the user is already following its tail. Scrolling upward clears that follow state, so streamed chunks and newly appended records do not interrupt inspection of earlier rows. Tail following and virtualizer measurement react to row keys and heights rather than content identity, so text-only stream frames neither discard the measurement cache nor repeat a DOM scroll write. - Token streaming updates only the matching Trajectory Assistant Context, while publication is coalesced to at most once per animation frame. The target snapshot preserves the existing stage, layout, Request numbering, Overview, and search inputs; completed Assistant State retains assembled blocks, timing, and usage rather than every raw chunk payload, while Session keeps the raw Event window. - Each Trajectory Definition extracts a stable ID from the current Event, and the shared Assembler replays only Contexts affected by matching, Location, or Reader changes. Older Session pages prepend into the same engine window; the Trajectory target builder converts its materialized Nodes into the existing stage-oriented snapshot consumed by the ledger. @@ -53,4 +53,4 @@ Trajectory has to make prose, machine payloads, token usage, timing, and nested ## Consequences -Trajectory shows more useful records per viewport while retaining Turn and Request orientation. Context rewrites and compactions remain inline with their surrounding history, while a rewind begins a successor branch that inherits only the retained prefix. The floating composer leaves the ledger visible to the viewport edge without covering its final rows or hiding horizontal controls. The main ledger omits token usage and duration so content receives the available width; the local inspector exposes those facts together with full payloads, provider/model and source fields, schemas, and request timing. The Overview uses recorded start/duration and token-boundary facts without fabricating live elapsed time, and its inclusive focus behavior matches the interaction users already know from Chrome DevTools Network. Tail-first paging bounds initial transport work, virtualization bounds mounted row elements, exact-ID dispatch avoids re-folding unrelated business Contexts, and animation-frame publication caps streaming snapshot frequency. The retained stage-oriented target builder may still perform work proportional to the loaded materialized Nodes for a publication; this migration does not add a stronger Trajectory-specific complexity guarantee. Focused component tests pin tail-first paging, prepend anchoring and identity retention, the virtual window, tail following, content-only streaming without repeated scroll writes, timing projection, delayed detail disclosure, folding, record and interval selection, entity-specific tabs, and running/error semantics. A real-browser long-ledger contract pins stable prepend geometry, bounded mounting, top/middle/bottom reachability, and bounded scroll writes across a paced stream; the assembled Web snapshot pins the ledger, Overview timing details, composer overlay geometry, and inspector through the real client composition. +Trajectory shows more useful records per viewport while retaining Turn and Request orientation. Context rewrites and compactions appear as the current materialized business records in sequence with surrounding history. The floating composer leaves the ledger visible to the viewport edge without covering its final rows or hiding horizontal controls. The main ledger omits token usage and duration so content receives the available width; the local inspector exposes those facts together with full payloads, provider/model and source fields, schemas, and request timing. The Overview uses recorded start/duration and token-boundary facts without fabricating live elapsed time, and its inclusive focus behavior matches the interaction users already know from Chrome DevTools Network. Tail-first paging bounds initial transport work, virtualization bounds mounted row elements, exact-ID dispatch avoids re-folding unrelated business Contexts, and animation-frame publication caps streaming snapshot frequency. The retained stage-oriented target builder may still perform work proportional to the loaded materialized Nodes for a publication; this migration does not add a stronger Trajectory-specific complexity guarantee. Focused component tests pin tail-first paging, prepend anchoring and identity retention, the virtual window, tail following, content-only streaming without repeated scroll writes, timing projection, delayed detail disclosure, folding, record and interval selection, entity-specific tabs, and running/error semantics. A real-browser long-ledger contract pins stable prepend geometry, bounded mounting, top/middle/bottom reachability, and bounded scroll writes across a paced stream; the assembled Web snapshot pins the ledger, Overview timing details, composer overlay geometry, and inspector through the real client composition. diff --git a/.agents/notes/implemented/feature/2026-07-27-trajectory-inspection-ledger.zh.md b/.agents/notes/implemented/feature/2026-07-27-trajectory-inspection-ledger.zh.md index 9d2c615dea..20811f7a23 100644 --- a/.agents/notes/implemented/feature/2026-07-27-trajectory-inspection-ledger.zh.md +++ b/.agents/notes/implemented/feature/2026-07-27-trajectory-inspection-ledger.zh.md @@ -12,17 +12,17 @@ Status: implemented **使用现有 DeepSeek 设计系统,渲染保留轮次结构的紧凑事件记录表,并提供局部记录检查器。** -- 记录表在以 `rewind` 划分的分支内按会话事件顺序展示。轮次边界由稍粗的分割线、原始轮次 id 和连续的左侧竖线表示;请求边界以融入该结构的小圆点表示,普通请求与压缩(compaction)请求在整个时间序列中共用一套编号。 +- 记录表在已加载窗口内按 Session Event 顺序展示物化后的业务记录。轮次边界由稍粗的分割线、原始轮次 id 和连续的左侧竖线表示;请求边界以融入该结构的小圆点表示,普通请求与压缩(compaction)请求在整个时间序列中共用一套编号。 - 事件类型与内容构成两个稳定列。角色标签朝内容侧对齐,嵌套子工具略微缩进,内容预览使用 CSS 截断以适应可用宽度。token 用量和耗时留在检查器中。 - 产品正文使用现有无衬线字体栈。轮次 id、token 数、耗时、工具调用、原始载荷和其他机器数据使用现有代码字体栈。 - 现有主题 token 同时负责亮色和暗色渲染。中性边框与表面构成整体结构;区分度较低的角色色帮助扫读而不表达成功或失败语义,业务蓝色则标识选择状态、链接和焦点。 -- Session 统一拥有一份连续 Event 窗口、分页状态、实时缺口修复与重连重建。Chat 与 Trajectory 针对共享的 `ConversationNodeAssembler` 分别注册业务 Definition;Trajectory 从 `Session.views` 读取自己的 target snapshot,并在用户到达已加载范围顶部时请求一页更早的 Session 历史。它的 Definition 与 target builder 派生事件顺序、上下文谱系、schema 索引和请求,无须把这些结构放进 Chat snapshot。 +- Session 统一拥有一份连续 Event 窗口、分页状态、实时缺口修复与重连重建。Chat 与 Trajectory 针对共享的 `ConversationNodeAssembler` 分别注册业务 Definition;Trajectory 从 `Session.views` 读取自己的 target snapshot,并在用户到达已加载范围顶部时请求一页更早的 Session 历史。它的 Definition 与 target builder 派生事件顺序、schema 索引和请求,无须把这些结构放进 Chat snapshot。 - 普通生成调用与压缩调用形成一条按时间排序的请求投影,以用途区分而不是放入不同集合。生效的提示词状态及其变化附着在引入它们的请求上;压缩和提示词变化都不是独立检查实体。请求编号和累计用量覆盖已加载的历史窗口,并随更早页面到达而扩展。 - 调用 schema 来自当前生效且已记录的请求头。无密钥快照 fixture(测试前置数据)有意将该目录替换为非数组 token `{{tools}}`,持久化检查边界会将其视为不可用,而不是尝试投影或虚构 schema。 - 选择记录或请求后,Trajectory 内部会打开检查器,其标签页和概述区域随实体类型变化:Markdown 消息提供渲染内容、来源字段、提供方/模型字段和层级视图;工具提供 JSON 载荷/结果和 schema 视图;请求提供选项、用量、计时和结果跳转。可滚动的概述区域默认保持滚动条滑块透明,直到悬停或 `focus-within` 时才显示,同时保留滚动条预留空间和滚动行为。图片以媒体形式渲染,而不是显示为序列化数据。 - 折叠轮次时保留其第一条记录,并用紧凑的步骤数和工具调用数替换后续所有行;折叠助手时对其工具调用后代应用相同操作。全局控件会折叠或展开这两个层级。 - 长记录表初始时将已加载尾部置于底部,只挂载视口对应的行窗口及有界的额外缓冲行。仅含请求的分隔行并入下一个具备可测高度的虚拟项,末尾分隔行则保留固定留白,因此虚拟化器不会管理零高度项。可安全用于 DOM 的语义行键与 ARIA 索引使标识不依赖挂载位置。只要已知尾部之前仍有更早历史,即使当前已加载投影低于常规行数阈值,也会立即启用虚拟化。基于稳定键的虚拟化器锚定会在向前补页和尾部追加时保留当前可见项;只有分页完成导致虚拟化停用时,才使用手动滚动高度兜底。选择、时间线聚焦、折叠、搜索和末尾跟随均按稳定的事件或工具调用标识定位,不要求对应 DOM 行已存在。初始定位完成前以及更早 Session 页面仍在等待时,明确的加载行会遮住真实记录。 -- 移除独立的 waterfall(瀑布式事件)标签页。固定在记录表上方的 Overview 区域将所有 `startedAt` 已知的已加载记录按各自耗时投影到三条语义计时轨道。仍有更早前缀尚未加载且 viewport 包含已加载时间域起点时,中性的省略号控件会遮住截断边缘并加载一页更早历史,而不会为未知历史虚构耗时;悬停在该控件上会隐藏普通的时间线光标。已完成的助手时间条以首个非空 token 增量为分界,用不同颜色按真实比例表示 TTFT 与解码时间;计时不完整时退化为单一助手色。悬停 500 ms 后会显示精确起止时刻、总耗时、TTFT 和解码时间,而不依赖浏览器原生 tooltip 的延迟。向左或向右拖动会提交包含边界的区间筛选:任何活动区间与所选区间任一边界重叠的记录都会保留,计时未知的记录会从聚焦后的记录表中移除,清除选择则恢复完整分支。滚轮手势用于缩放时间域。右键单击会清除区间选择;右键拖动则只会平移已放大的 viewport,不会改变该选区。聚焦后,Overview 区域仍保留完整时间范围,以便在不失去方位的情况下调整或清除选择。 +- 移除独立的 waterfall(瀑布式事件)标签页。固定在记录表上方的 Overview 区域将所有 `startedAt` 已知的已加载记录按各自耗时投影到三条语义计时轨道。仍有更早前缀尚未加载且 viewport 包含已加载时间域起点时,中性的省略号控件会遮住截断边缘并加载一页更早历史,而不会为未知历史虚构耗时;悬停在该控件上会隐藏普通的时间线光标。已完成的助手时间条以首个非空 token 增量为分界,用不同颜色按真实比例表示 TTFT 与解码时间;计时不完整时退化为单一助手色。悬停 500 ms 后会显示精确起止时刻、总耗时、TTFT 和解码时间,而不依赖浏览器原生 tooltip 的延迟。向左或向右拖动会提交包含边界的区间筛选:任何活动区间与所选区间任一边界重叠的记录都会保留,计时未知的记录会从聚焦后的记录表中移除,清除选择则恢复完整的已加载记录表。滚轮手势用于缩放时间域。右键单击会清除区间选择;右键拖动则只会平移已放大的 viewport,不会改变该选区。聚焦后,Overview 区域仍保留完整时间范围,以便在不失去方位的情况下调整或清除选择。 - 实时历史更新仅在用户已经跟随记录表末尾时保留底部位置。向上滚动会清除跟随状态,因此流式分块和新追加的记录不会打断对旧记录的检查。末尾跟随与虚拟化器测量仅响应行键和高度,而非内容标识,因此仅含文本的流式帧既不会丢弃测量缓存,也不会重复执行 DOM 滚动写入。 - token 流式输出只更新命中的 Trajectory Assistant Context,发布则合并为每个 animation frame 最多一次。target snapshot 继续提供既有 stage、layout、请求编号、Overview 与搜索输入;已完成的 Assistant State 只保留组装后的 blocks、计时与 usage,不保留每条原始 chunk payload,而 Session 继续保存原始 Event 窗口。 - 每个 Trajectory Definition 都从当前 Event 提取稳定 ID,共享 Assembler 只 replay 因 Match、Location 或 Reader 变化而受影响的 Context。更早 Session 页面 prepend 到同一个引擎窗口;Trajectory target builder 再把已物化 Node 转换为记录表继续消费的 stage-oriented snapshot。 @@ -53,4 +53,4 @@ Status: implemented ## 后果 -轨迹视图在保留轮次与请求定位的同时,每个视口可以显示更多有效记录。上下文 `rewrite` 与压缩保持在周边历史中的原始位置,`rewind` 则建立仅继承保留前缀的后继分支。浮动 composer 让记录表一直显示到视口边缘,同时不会遮住最后几行,也不会隐藏横向控件。主记录表省略 token 用量和耗时,让内容获得可用宽度;局部检查器展示这些数据以及完整载荷、提供方/模型字段、来源字段、schema 和请求计时。Overview 区域使用记录的开始时间、耗时与 token 边界数据,而不虚构实时流逝时间,其包含边界的聚焦行为与用户熟悉的 Chrome DevTools Network 交互一致。尾部优先分页限制初始传输工作,虚拟化限制已挂载的行元素数量,精确 ID 分发避免重新 fold 无关业务 Context,animation-frame 发布则限制流式 snapshot 频率。保留的 stage-oriented target builder 在一次发布中仍可能执行与已加载物化 Node 数量成比例的工作;本次迁移不额外承诺更强的 Trajectory 专属复杂度。针对性组件测试锁定尾部优先分页、向前补页锚定与标识保持、虚拟窗口、末尾跟随、仅含内容的流式输出不会重复写入滚动位置、计时投影、延迟展示详情、折叠、记录与区间选择、实体特定标签页和运行/错误语义。真实浏览器中的长记录表约定锁定向前补页时稳定的几何位置、有界挂载、顶部/中部/底部可达性,以及按节奏进行的流式输出中有界的滚动写入;组装后的 Web 快照则通过真实客户端组合锁定记录表、Overview 计时详情、composer 浮层几何形状与检查器。 +轨迹视图在保留轮次与请求定位的同时,每个视口可以显示更多有效记录。上下文 `rewrite` 与压缩会作为当前物化的业务记录,按顺序出现在周边历史中。浮动 composer 让记录表一直显示到视口边缘,同时不会遮住最后几行,也不会隐藏横向控件。主记录表省略 token 用量和耗时,让内容获得可用宽度;局部检查器展示这些数据以及完整载荷、提供方/模型字段、来源字段、schema 和请求计时。Overview 区域使用记录的开始时间、耗时与 token 边界数据,而不虚构实时流逝时间,其包含边界的聚焦行为与用户熟悉的 Chrome DevTools Network 交互一致。尾部优先分页限制初始传输工作,虚拟化限制已挂载的行元素数量,精确 ID 分发避免重新 fold 无关业务 Context,animation-frame 发布则限制流式 snapshot 频率。保留的 stage-oriented target builder 在一次发布中仍可能执行与已加载物化 Node 数量成比例的工作;本次迁移不额外承诺更强的 Trajectory 专属复杂度。针对性组件测试锁定尾部优先分页、向前补页锚定与标识保持、虚拟窗口、末尾跟随、仅含内容的流式输出不会重复写入滚动位置、计时投影、延迟展示详情、折叠、记录与区间选择、实体特定标签页和运行/错误语义。真实浏览器中的长记录表约定锁定向前补页时稳定的几何位置、有界挂载、顶部/中部/底部可达性,以及按节奏进行的流式输出中有界的滚动写入;组装后的 Web 快照则通过真实客户端组合锁定记录表、Overview 计时详情、composer 浮层几何形状与检查器。 diff --git a/docs/cookbook/adding-a-conversation-node.i18n.yaml b/docs/cookbook/adding-a-conversation-node.i18n.yaml index aa268e9461..52234b5562 100644 --- a/docs/cookbook/adding-a-conversation-node.i18n.yaml +++ b/docs/cookbook/adding-a-conversation-node.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 docs/cookbook/adding-a-conversation-node.md -adding-a-conversation-node.md: ea4ec73eb109af6b0e4c7cf50fc8692942c75dd4 -adding-a-conversation-node.zh.md: 4b9a8049e2f1d060ec4bc3334036559b989ea562 +adding-a-conversation-node.md: c1965dc8a3081eebb8c1026ac53d2f7b8964edb7 +adding-a-conversation-node.zh.md: 92445e1432369a4e42cc372b5d5869c3cdeada4a diff --git a/docs/cookbook/adding-a-conversation-node.md b/docs/cookbook/adding-a-conversation-node.md index ea4ec73eb1..c1965dc8a3 100644 --- a/docs/cookbook/adding-a-conversation-node.md +++ b/docs/cookbook/adding-a-conversation-node.md @@ -120,6 +120,7 @@ function viewData(state: ReviewState): ReviewChatData { const reviewDefinition: ConversationNodeDefinition = { kind: 'review-job', + target: 'chat', match: (event) => { if (event.type === 'review/start') { return { id: String(event.data.reviewId), role: 'start' } @@ -161,8 +162,8 @@ const reviewDefinition: ConversationNodeDefinition = { value: viewData(context.state), } }, - buildViewNode: (context, target) => { - if (target !== 'chat' || context.state === undefined) return null + buildViewNode: (context) => { + if (context.state === undefined) return null return { key: context.key, kind: 'review-job', @@ -196,7 +197,7 @@ export function apply(ctx: ClientContext): void { `buildLocationData(context, scope)` optionally publishes Definition-owned data onto an engine-owned Turn or Step. Use declaration merging to give each key a precise value type. Another Node in the same Location can consume that value through its constrained slot hook, such as `useTurnData(key)`, without receiving the Session or scanning `snapshot.chat.nodes`. -`buildViewNode(context, target)` materializes the final target-specific Node. Preserve `context.key` as the React-facing identity, choose `anchorSeq` from durable ordering evidence, and return only renderer-ready data. Once a target Node has been published, keep returning the same key; use `visibility: 'hidden'` when it must temporarily leave the visible flow rather than withdrawing it with `null`. +`target` and `buildViewNode(context)` declare one target-owned rendering contribution and must appear together. Preserve `context.key` as the React-facing identity, choose `anchorSeq` from durable ordering evidence, and return only renderer-ready data. Once a target Node has been published, keep returning the same key; use `visibility: 'hidden'` when it must temporarily leave the visible flow rather than withdrawing it with `null`. ## 3. Query an earlier business Context only at start diff --git a/docs/cookbook/adding-a-conversation-node.zh.md b/docs/cookbook/adding-a-conversation-node.zh.md index 4b9a8049e2..92445e1432 100644 --- a/docs/cookbook/adding-a-conversation-node.zh.md +++ b/docs/cookbook/adding-a-conversation-node.zh.md @@ -120,6 +120,7 @@ function viewData(state: ReviewState): ReviewChatData { const reviewDefinition: ConversationNodeDefinition = { kind: 'review-job', + target: 'chat', match: (event) => { if (event.type === 'review/start') { return { id: String(event.data.reviewId), role: 'start' } @@ -161,8 +162,8 @@ const reviewDefinition: ConversationNodeDefinition = { value: viewData(context.state), } }, - buildViewNode: (context, target) => { - if (target !== 'chat' || context.state === undefined) return null + buildViewNode: (context) => { + if (context.state === undefined) return null return { key: context.key, kind: 'review-job', @@ -196,7 +197,7 @@ export function apply(ctx: ClientContext): void { `buildLocationData(context, scope)` 可以把 Definition 拥有的数据发布到引擎拥有的 Turn 或 Step 上。通过 declaration merging 为每个 key 指定精确 value 类型。同一 Location 内的另一个 Node 可以使用受限 slot hook(例如 `useTurnData(key)`)读取该值,无须取得 Session,也无须扫描 `snapshot.chat.nodes`。 -`buildViewNode(context, target)` 物化最终的目标专用 Node。把 `context.key` 保留为 React 侧身份,根据持久排序证据选择 `anchorSeq`,并且只返回 renderer 可以直接使用的数据。某个 target Node 一旦发布,就要继续返回同一个 key;需要暂时离开可见流时使用 `visibility: 'hidden'`,不要改为返回 `null` 撤回它。 +`target` 与 `buildViewNode(context)` 必须同时声明一项由 target 拥有的渲染贡献。把 `context.key` 保留为 React 侧身份,根据持久排序证据选择 `anchorSeq`,并且只返回 renderer 可以直接使用的数据。某个 target Node 一旦发布,就要继续返回同一个 key;需要暂时离开可见流时使用 `visibility: 'hidden'`,不要改为返回 `null` 撤回它。 ## 3. 只在 start 时查询更早的业务 Context diff --git a/packages/client/runtime/tests/conversation-assembler.spec.ts b/packages/client/runtime/tests/conversation-assembler.spec.ts index 50380a20a3..6108169192 100644 --- a/packages/client/runtime/tests/conversation-assembler.spec.ts +++ b/packages/client/runtime/tests/conversation-assembler.spec.ts @@ -37,8 +37,8 @@ class TestEventDefinitions { definitions: readonly ConversationNodeDefinition[], fallback?: ConversationNodeDefinition, ) { - this.definitions = definitions.map(asChatDefinition) - this.fallback = fallback === undefined ? undefined : asChatDefinition(fallback) + this.definitions = definitions + this.fallback = fallback } entries(): readonly ConversationNodeDefinition[] { @@ -50,12 +50,6 @@ class TestEventDefinitions { } } -function asChatDefinition(definition: ConversationNodeDefinition): ConversationNodeDefinition { - return definition.buildViewNode === undefined || definition.target !== undefined - ? definition - : { ...definition, target: 'chat' } -} - class TestViewDefinitions { constructor(readonly definitions: readonly ConversationViewDefinition[]) {} @@ -118,6 +112,17 @@ function node( } } +function fallbackDefinition(start: () => string): ConversationNodeDefinition { + return { + kind: 'fallback', + target: 'chat', + match: event => ({ id: String(event.seq), role: 'start' }), + start, + update: context => context.state, + buildViewNode: context => node(context, context.state), + } +} + describe('ConversationNodeAssembler', () => { it('appends through an exact business-id Context without replaying unrelated Contexts', () => { const starts = vi.fn(( @@ -137,6 +142,7 @@ describe('ConversationNodeAssembler', () => { }, start: starts, update: updates, + target: 'chat', buildViewNode: context => node(context, context.state), } const assembler = new ConversationNodeAssembler( @@ -188,6 +194,7 @@ describe('ConversationNodeAssembler', () => { matchCollections.add(context.matches) return updates(context) }, + target: 'chat', buildViewNode: context => node(context, context.state), } const assembler = new ConversationNodeAssembler( @@ -223,6 +230,7 @@ describe('ConversationNodeAssembler', () => { }, start: starts, update: updates, + target: 'chat', buildViewNode: context => node(context, context.state), } const assembler = new ConversationNodeAssembler( @@ -262,6 +270,7 @@ describe('ConversationNodeAssembler', () => { }, start: () => ({ settled: false }), update: updates, + target: 'chat', buildViewNode: context => node(context, context.state ?? { pendingStart: true }), } const assembler = new ConversationNodeAssembler( @@ -295,6 +304,7 @@ describe('ConversationNodeAssembler', () => { : event.type === 'turn/start' ? { id: 'one', role: 'update' } : null, start: () => null, update: context => context.state, + target: 'chat', buildViewNode: () => null, } const assembler = new ConversationNodeAssembler( @@ -316,6 +326,7 @@ describe('ConversationNodeAssembler', () => { : null, start: (_context, match) => Number((match.event.data as { value?: unknown }).value ?? 0), update: context => context.state, + target: 'chat', buildViewNode: () => null, } const consumerStart = vi.fn(( @@ -330,6 +341,7 @@ describe('ConversationNodeAssembler', () => { : null, start: consumerStart, update: context => context.state, + target: 'chat', buildViewNode: context => node(context, context.state), } const assembler = new ConversationNodeAssembler( @@ -359,6 +371,7 @@ describe('ConversationNodeAssembler', () => { : null, start: (_context, match) => match.event.seq, update: context => context.state, + target: 'chat', buildViewNode: () => null, } const consumer: ConversationNodeDefinition = { @@ -368,6 +381,7 @@ describe('ConversationNodeAssembler', () => { : null, start: (_context, _match, reader) => reader.previous('source')?.state ?? -1, update: context => context.state, + target: 'chat', buildViewNode: context => node(context, context.state), } const assembler = new ConversationNodeAssembler( @@ -412,6 +426,7 @@ describe('ConversationNodeAssembler', () => { : null, start: consumerStart, update: context => context.state, + target: 'chat', buildViewNode: context => node(context, context.state), } const assembler = new ConversationNodeAssembler( @@ -440,6 +455,7 @@ describe('ConversationNodeAssembler', () => { }, start: () => 1, update: (_context, match) => (match.event.data as unknown as { value: number }).value, + target: 'chat', buildViewNode: () => null, } const consumerStart = vi.fn(( @@ -454,6 +470,7 @@ describe('ConversationNodeAssembler', () => { : null, start: consumerStart, update: context => context.state, + target: 'chat', buildViewNode: context => node(context, context.state), } const assembler = new ConversationNodeAssembler( @@ -483,6 +500,7 @@ describe('ConversationNodeAssembler', () => { }, start: () => 1, update: (_context, match) => (match.event.data as unknown as { value: number }).value, + target: 'chat', buildViewNode: () => null, } const sourceX: ConversationNodeDefinition = { @@ -494,6 +512,7 @@ describe('ConversationNodeAssembler', () => { }, start: () => 10, update: (_context, match) => (match.event.data as unknown as { value: number }).value, + target: 'chat', buildViewNode: () => null, } const middle: ConversationNodeDefinition = { @@ -506,6 +525,7 @@ describe('ConversationNodeAssembler', () => { + (reader.previous('diamond-x')?.state ?? 0) ), update: context => context.state, + target: 'chat', buildViewNode: context => node(context, context.state), } const consumer: ConversationNodeDefinition = { @@ -518,6 +538,7 @@ describe('ConversationNodeAssembler', () => { + (reader.previous('diamond-b')?.state ?? 0) ), update: context => context.state, + target: 'chat', buildViewNode: context => node(context, context.state), } const assembler = new ConversationNodeAssembler( @@ -553,6 +574,7 @@ describe('ConversationNodeAssembler', () => { : null, start: starts, update: context => context.state, + target: 'chat', buildViewNode: context => node(context, context.state), } const assembler = new ConversationNodeAssembler( @@ -624,6 +646,7 @@ describe('ConversationNodeAssembler', () => { value: { valueSeenFromStep: stepValue ?? -1 }, } }, + target: 'chat', buildViewNode: (context) => { const location = context.start?.location if (location?.kind !== 'step') return null @@ -661,6 +684,7 @@ describe('ConversationNodeAssembler', () => { : null, start: () => null, update: context => context.state, + target: 'chat', buildViewNode: context => node(context, context.start?.location.kind === 'turn' ? context.start.location.turn.steps.length : -1), @@ -716,6 +740,7 @@ describe('ConversationNodeAssembler', () => { }, start: () => null, update: context => context.state, + target: 'chat', buildViewNode: (context) => { const location = context.start?.location const data = location?.kind === 'step' @@ -749,6 +774,7 @@ describe('ConversationNodeAssembler', () => { : null, start: () => null, update: context => context.state, + target: 'chat', buildViewNode: context => node(context, context.start?.location.kind), } const assembler = new ConversationNodeAssembler( @@ -775,6 +801,7 @@ describe('ConversationNodeAssembler', () => { : null, start: () => null, update: context => context.state, + target: 'chat', buildViewNode: (context) => { const location = context.start?.location return node(context, location?.kind === 'step' @@ -807,6 +834,7 @@ describe('ConversationNodeAssembler', () => { : null, start: () => null, update: context => context.state, + target: 'chat', buildViewNode: (context) => { const location = context.start?.location return node(context, location?.kind === 'step' @@ -841,6 +869,7 @@ describe('ConversationNodeAssembler', () => { : null, start: seen, update: context => context.state, + target: 'chat', buildViewNode: context => node(context, context.state), } const assembler = new ConversationNodeAssembler( @@ -856,24 +885,64 @@ describe('ConversationNodeAssembler', () => { expect(seen).toHaveBeenCalledTimes(2) }) - it('does not invoke the fallback when an ordinary non-rendering Definition claims an event', () => { + it('invokes the fallback when only a State-only Definition claims an event', () => { + const fallbackStart = vi.fn(() => 'fallback') + const claimed: ConversationNodeDefinition = { + kind: 'claimed-state', + match: event => (event.type as string) === 'command/run' + ? { id: 'claimed', role: 'start' } + : null, + start: () => null, + update: context => context.state, + } + const assembler = new ConversationNodeAssembler( + new TestEventDefinitions([claimed], fallbackDefinition(fallbackStart)), + new TestViewDefinitions([testView()]), + ) + + assembler.replaceWindow([input(at(1, 'command/run', { commandId: 'one', name: 'x' }))], false) + assembler.flush() + + expect(fallbackStart).toHaveBeenCalledOnce() + expect(chatSnapshot(assembler)?.order).toHaveLength(1) + }) + + it('invokes the fallback when only another target claims an event', () => { + const fallbackStart = vi.fn(() => 'fallback') + const claimed: ConversationNodeDefinition = { + kind: 'claimed-trajectory', + target: 'trajectory', + match: event => (event.type as string) === 'command/run' + ? { id: 'claimed', role: 'start' } + : null, + start: () => null, + update: context => context.state, + buildViewNode: () => null, + } + const assembler = new ConversationNodeAssembler( + new TestEventDefinitions([claimed], fallbackDefinition(fallbackStart)), + new TestViewDefinitions([testView()]), + ) + + assembler.replaceWindow([input(at(1, 'command/run', { commandId: 'one', name: 'x' }))], false) + assembler.flush() + + expect(fallbackStart).toHaveBeenCalledOnce() + expect(chatSnapshot(assembler)?.order).toHaveLength(1) + }) + + it('suppresses the fallback when the same target claims an event', () => { const fallbackStart = vi.fn(() => 'fallback') const claimed: ConversationNodeDefinition = { kind: 'claimed', + target: 'chat', match: event => (event.type as string) === 'command/run' ? { id: 'claimed', role: 'start' } : null, start: () => null, update: context => context.state, buildViewNode: () => null, } - const fallback: ConversationNodeDefinition = { - kind: 'fallback', - match: event => ({ id: String(event.seq), role: 'start' }), - start: fallbackStart, - update: context => context.state, - buildViewNode: context => node(context, context.state), - } const assembler = new ConversationNodeAssembler( - new TestEventDefinitions([claimed], fallback), + new TestEventDefinitions([claimed], fallbackDefinition(fallbackStart)), new TestViewDefinitions([testView()]), ) assembler.replaceWindow([input(at(1, 'command/run', { commandId: 'one', name: 'x' }))], false) @@ -893,6 +962,7 @@ describe('ConversationNodeAssembler', () => { }, start: () => true, update: () => false, + target: 'chat', buildViewNode: context => context.state === true ? node(context, true) : null, } const assembler = new ConversationNodeAssembler( @@ -915,6 +985,7 @@ describe('ConversationNodeAssembler', () => { match: event => (event.type as string) === 'command/run' ? { id: 'one', role: 'start' } : null, start: () => undefined, update: context => context.state, + target: 'chat', buildViewNode: () => null, } const startAssembler = new ConversationNodeAssembler( @@ -934,6 +1005,7 @@ describe('ConversationNodeAssembler', () => { }, start: () => true, update: () => undefined as never, + target: 'chat', buildViewNode: context => node(context, context.state), } const updateAssembler = new ConversationNodeAssembler( @@ -954,6 +1026,7 @@ describe('ConversationNodeAssembler', () => { match: event => (event.type as string) === 'command/run' ? { id: 'one', role: 'start' } : null, start: (_context, match) => match.event.seq, update: context => context.state, + target: 'chat', buildViewNode: context => node(context, context.state), } const assembler = new ConversationNodeAssembler( diff --git a/packages/client/runtime/tests/conversation-registry.spec.ts b/packages/client/runtime/tests/conversation-registry.spec.ts index 0beaf1d5c2..5181dab926 100644 --- a/packages/client/runtime/tests/conversation-registry.spec.ts +++ b/packages/client/runtime/tests/conversation-registry.spec.ts @@ -72,6 +72,40 @@ describe('Conversation registries', () => { expect(events.fallbackEntry()).toBeUndefined() }) + it('rejects rendering Definitions that omit either target or builder', async () => { + const { events } = await bootRegistries() + const targetOnly: ConversationNodeDefinition = { + kind: 'target-only', + target: 'chat', + match: () => null, + start: () => null, + update: context => context.state, + } + const builderOnly: ConversationNodeDefinition = { + kind: 'builder-only', + match: () => null, + start: () => null, + update: context => context.state, + buildViewNode: () => null, + } + + expect(() => events.register(targetOnly)).toThrow(/target and buildViewNode together/) + expect(() => events.register(builderOnly)).toThrow(/target and buildViewNode together/) + }) + + it('rejects a State-only Definition as the unmatched-event fallback', async () => { + const { events } = await bootRegistries() + const fallback: ConversationNodeDefinition = { + kind: 'state-only-fallback', + match: () => null, + start: () => null, + update: context => context.state, + } + + expect(() => events.registerFallback(fallback)) + .toThrow('conversation fallback Definition must declare a target') + }) + it('rejects duplicate view targets and disposes a view registration once', async () => { const { views } = await bootRegistries() const definition = viewDefinition('chat') diff --git a/packages/client/ui-trajectory/README.i18n.yaml b/packages/client/ui-trajectory/README.i18n.yaml index 17551b0cc8..78082eb1f0 100644 --- a/packages/client/ui-trajectory/README.i18n.yaml +++ b/packages/client/ui-trajectory/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/client/ui-trajectory/README.md -README.md: 75bd9ddf452634460be01e1b89cd5a1a14a1593f -README.zh.md: b5cd53dd50e43b96e2e832c96cb7e93f859c1993 +README.md: d3786b6460c5df7eaa6d24e68c80025e7fb29ae4 +README.zh.md: 5eb1451b9a3a9896d5486fcf5c8d9cf30d6159a0 diff --git a/packages/client/ui-trajectory/README.md b/packages/client/ui-trajectory/README.md index 75bd9ddf45..d3786b6460 100644 --- a/packages/client/ui-trajectory/README.md +++ b/packages/client/ui-trajectory/README.md @@ -2,7 +2,7 @@ English | [中文](README.zh.md) -Trajectory renders a turn-aware event ledger with selectable User, Assistant, Tool, and nested Subtool records. Thick rules mark Turn boundaries, compact inline markers identify Steps, and the main ledger keeps only index, event, and content; selection opens a local inspector for token usage, duration, Input, Output, and Timing. Scrollable Summary regions keep their scrollbar thumbs transparent until the region is hovered or contains keyboard focus, without changing the reserved scroll geometry. A standalone compaction request appears chronologically in its own `Between turns` section, while a numbered compaction remains inside its owning turn. Long ledgers open at the current tail, load one older page when the user reaches the loaded range's top, and mount only the visible row window plus a small overscan; request-only separators share the next measurable virtual item, while semantic row keys and ARIA indexes survive prepends. Selection, timeline navigation, folding, search, and Request totals cover the currently loaded window. The ledger covers records with an explicit loading row until the initial tail is positioned and while an older page is pending. A fixed Overview above the ledger projects real record start/duration timing from left to right; when earlier records remain unloaded and the viewport includes the loaded domain's start, a neutral ellipsis control identifies the omitted prefix and loads one earlier page without assigning unknown history fabricated duration. Assistant spans divide recorded TTFT from decoding, and a 500 ms hover reveals exact clock and duration details. Dragging an interval focuses the ledger on every record active at any point in that inclusive range, while clearing the selection restores the full branch. Wheel gestures zoom the time domain. A right-button click clears the selected interval, while a right-button drag pans an already zoomed viewport without changing it. The initial view and streaming updates stay at the tail; scrolling upward suspends following so new records do not interrupt inspection of earlier rows. Content-only stream frames preserve virtual row keys and heights, reuse measurements, and do not issue repeated tail-scroll writes. Completed replies retain assembled blocks, timing, and usage in Trajectory target State, while the shared Session window keeps the raw Events. Trajectory asks the conversation shell to float the composer over the full-height ledger, while its responsive vertical scrollers reserve the composer's live height so final rows remain reachable. Trajectory-owned Definitions assemble context lineage and cancellation-frozen Assistant and Tool records from the shared Session window, so Trajectory neither reads nor changes the Chat conversation snapshot. The package provides no service and declares no Context merge; it registers target-specific Event Definitions, a Trajectory view builder, and one tab in the conversation's `'conversation.view'` slot ring. Contract: api-contracts v3 §8. +Trajectory renders a turn-aware event ledger with selectable User, Assistant, Tool, and nested Subtool records. Thick rules mark Turn boundaries, compact inline markers identify Steps, and the main ledger keeps only index, event, and content; selection opens a local inspector for token usage, duration, Input, Output, and Timing. Scrollable Summary regions keep their scrollbar thumbs transparent until the region is hovered or contains keyboard focus, without changing the reserved scroll geometry. A standalone compaction request appears chronologically in its own `Between turns` section, while a numbered compaction remains inside its owning turn. Long ledgers open at the current tail, load one older page when the user reaches the loaded range's top, and mount only the visible row window plus a small overscan; request-only separators share the next measurable virtual item, while semantic row keys and ARIA indexes survive prepends. Selection, timeline navigation, folding, search, and Request totals cover the currently loaded window. The ledger covers records with an explicit loading row until the initial tail is positioned and while an older page is pending. A fixed Overview above the ledger projects real record start/duration timing from left to right; when earlier records remain unloaded and the viewport includes the loaded domain's start, a neutral ellipsis control identifies the omitted prefix and loads one earlier page without assigning unknown history fabricated duration. Assistant spans divide recorded TTFT from decoding, and a 500 ms hover reveals exact clock and duration details. Dragging an interval focuses the ledger on every record active at any point in that inclusive range, while clearing the selection restores the full loaded ledger. Wheel gestures zoom the time domain. A right-button click clears the selected interval, while a right-button drag pans an already zoomed viewport without changing it. The initial view and streaming updates stay at the tail; scrolling upward suspends following so new records do not interrupt inspection of earlier rows. Content-only stream frames preserve virtual row keys and heights, reuse measurements, and do not issue repeated tail-scroll writes. Completed replies retain assembled blocks, timing, and usage in Trajectory target State, while the shared Session window keeps the raw Events. Trajectory asks the conversation shell to float the composer over the full-height ledger, while its responsive vertical scrollers reserve the composer's live height so final rows remain reachable. Trajectory-owned Definitions assemble business records, including cancellation-frozen Assistant and Tool records, from the shared Session window, so Trajectory neither reads nor changes the Chat conversation snapshot. The package provides no service and declares no Context merge; it registers target-specific Event Definitions, a Trajectory view builder, and one tab in the conversation's `'conversation.view'` slot ring. Contract: api-contracts v3 §8. ## Model Experience diff --git a/packages/client/ui-trajectory/README.zh.md b/packages/client/ui-trajectory/README.zh.md index b5cd53dd50..5eb1451b9a 100644 --- a/packages/client/ui-trajectory/README.zh.md +++ b/packages/client/ui-trajectory/README.zh.md @@ -2,7 +2,7 @@ [English](README.md) | 中文 -Trajectory 渲染按轮次组织的事件记录表,其中可选择用户、助手、工具和嵌套子工具记录。较粗的分割线标示轮次边界,紧凑的行内标记标识步骤,主记录表仅保留索引、事件和内容;选择记录则会打开局部检查器,查看 token 用量、耗时、输入、输出和计时。可滚动的概述区域默认保持滚动条滑块透明,直到鼠标悬停该区域或其中包含键盘焦点时才显示,同时不改变滚动条预留的几何空间。独立运行的压缩(compaction)请求会按时间顺序显示在自己的 `Between turns` 区段中,而带编号的压缩仍位于其所属轮次内。长记录表打开时定位于当前尾部,用户到达已加载范围顶部时加载一页更早的历史,并且只挂载可见行窗口和少量额外缓冲行;仅含请求的分隔行并入下一个具备可测高度的虚拟项,语义行键和 ARIA 索引在向前补页后保持不变。选择、时间线导航、折叠、搜索和请求汇总只覆盖当前已加载的窗口。初始尾部完成定位前以及更早页面仍在等待时,记录表会用明确的加载行遮住真实记录。固定在记录表上方的 Overview 区域从左到右投影记录的真实开始时间与耗时;仍有更早记录未加载且 viewport 包含已加载时间域起点时,中性的省略号控件会标识被省略的前缀,并可加载一页更早历史,而不会为未知部分虚构耗时。助手时间条会区分记录到的 TTFT 与解码时间,悬停 500 ms 后可查看精确时刻和耗时详情。拖选一个区间会将记录表聚焦到活动区间与该闭区间有重叠的所有记录,清除选择则恢复完整分支。滚轮手势用于缩放时间域。右键单击会清除所选区间;在已放大的 viewport 上按住右键拖动则只会平移视图,不会改变该区间。初始视图和流式更新都会停留在尾部;向上滚动会暂停跟随,因此新记录不会打断对旧记录的检查。仅含内容更新的流式帧会保持虚拟行的键和高度不变、复用测量结果,并且不会重复写入末尾滚动位置。已完成的回复会在 Trajectory target State 中保留组装后的 blocks、计时与用量,共享 Session 窗口则保留原始 Event。Trajectory 要求会话壳将 composer 作为浮层置于全高记录表上方;其响应式纵向滚动容器会预留 composer 的实时高度,确保仍可滚动到最后几行。Trajectory 自有的 Definition 从共享 Session 窗口组装上下文谱系,以及因取消而冻结的助手和工具记录,因此 Trajectory 既不读取也不改变 Chat 会话快照。该包不提供 service,也不声明 Context 合并;它会注册 target 专属 Event Definition、Trajectory view builder,以及会话 `'conversation.view'` slot 环中的一个视图标签页。约定:api-contracts v3 §8。 +Trajectory 渲染按轮次组织的事件记录表,其中可选择用户、助手、工具和嵌套子工具记录。较粗的分割线标示轮次边界,紧凑的行内标记标识步骤,主记录表仅保留索引、事件和内容;选择记录则会打开局部检查器,查看 token 用量、耗时、输入、输出和计时。可滚动的概述区域默认保持滚动条滑块透明,直到鼠标悬停该区域或其中包含键盘焦点时才显示,同时不改变滚动条预留的几何空间。独立运行的压缩(compaction)请求会按时间顺序显示在自己的 `Between turns` 区段中,而带编号的压缩仍位于其所属轮次内。长记录表打开时定位于当前尾部,用户到达已加载范围顶部时加载一页更早的历史,并且只挂载可见行窗口和少量额外缓冲行;仅含请求的分隔行并入下一个具备可测高度的虚拟项,语义行键和 ARIA 索引在向前补页后保持不变。选择、时间线导航、折叠、搜索和请求汇总只覆盖当前已加载的窗口。初始尾部完成定位前以及更早页面仍在等待时,记录表会用明确的加载行遮住真实记录。固定在记录表上方的 Overview 区域从左到右投影记录的真实开始时间与耗时;仍有更早记录未加载且 viewport 包含已加载时间域起点时,中性的省略号控件会标识被省略的前缀,并可加载一页更早历史,而不会为未知部分虚构耗时。助手时间条会区分记录到的 TTFT 与解码时间,悬停 500 ms 后可查看精确时刻和耗时详情。拖选一个区间会将记录表聚焦到活动区间与该闭区间有重叠的所有记录,清除选择则恢复完整的已加载记录表。滚轮手势用于缩放时间域。右键单击会清除所选区间;在已放大的 viewport 上按住右键拖动则只会平移视图,不会改变该区间。初始视图和流式更新都会停留在尾部;向上滚动会暂停跟随,因此新记录不会打断对旧记录的检查。仅含内容更新的流式帧会保持虚拟行的键和高度不变、复用测量结果,并且不会重复写入末尾滚动位置。已完成的回复会在 Trajectory target State 中保留组装后的 blocks、计时与用量,共享 Session 窗口则保留原始 Event。Trajectory 要求会话壳将 composer 作为浮层置于全高记录表上方;其响应式纵向滚动容器会预留 composer 的实时高度,确保仍可滚动到最后几行。Trajectory 自有的 Definition 从共享 Session 窗口组装业务记录,其中包括因取消而冻结的助手和工具记录,因此 Trajectory 既不读取也不改变 Chat 会话快照。该包不提供 service,也不声明 Context 合并;它会注册 target 专属 Event Definition、Trajectory view builder,以及会话 `'conversation.view'` slot 环中的一个视图标签页。约定:api-contracts v3 §8。 ## 模型体验 diff --git a/packages/client/ui-trajectory/package.json b/packages/client/ui-trajectory/package.json index c11b607939..a0c76575ae 100644 --- a/packages/client/ui-trajectory/package.json +++ b/packages/client/ui-trajectory/package.json @@ -48,19 +48,25 @@ "diff": "^9.0.0" }, "peerDependencies": { + "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-client-runtime": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-client-ui-primitives": "workspace:^", "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/dsh-compact": "workspace:^", + "@deepseek-ai/dsh-tools": "workspace:^", "react": "^18.2.0", "react-dom": "^18.2.0" }, "devDependencies": { + "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-client-runtime": "workspace:^", "@deepseek-ai/dsh-client-ui-primitives": "workspace:^", "@deepseek-ai/dsh-client-ui-conversation": "workspace:^", "@deepseek-ai/dsh-client-ui-slots": "workspace:^", + "@deepseek-ai/dsh-compact": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", + "@deepseek-ai/dsh-tools": "workspace:^", "@types/react": "~18.3.1", "@types/react-dom": "~18.3.0", "@deepseek-ai/cordis": "workspace:^", diff --git a/packages/client/ui-trajectory/src/client/TrajectoryView.tsx b/packages/client/ui-trajectory/src/client/TrajectoryView.tsx index 70e92f72fd..5651e620e5 100644 --- a/packages/client/ui-trajectory/src/client/TrajectoryView.tsx +++ b/packages/client/ui-trajectory/src/client/TrajectoryView.tsx @@ -4,13 +4,9 @@ import { useCallback, useMemo, useState } from 'react' import type { ConvViewProps } from '@deepseek-ai/dsh-client-ui-conversation/client' import type { InjectFace } from '@deepseek-ai/dsh-client-ui-slots' import type { - AssistantBlock, AssistantMessageNode, ConversationContext, ConversationSnapshot, + AssistantBlock, AssistantMessageNode, ConversationSnapshot, SnapshotStore, } from '@deepseek-ai/dsh-client-runtime/client' -import { - deriveTrajectoryContextBranches, trajectoryBranchContainsRequest, - trajectoryNodeIdentity, -} from './context-branches.ts' import { TrajectoryTable, type TrajectoryRequestNumber, @@ -190,10 +186,7 @@ export function TrajectoryView({ const [collapsedTurns, setCollapsedTurns] = useState>(EMPTY_TURN_IDS) const [collapsedAssistants, setCollapsedAssistants] = useState>(EMPTY_RECORD_IDS) - const [timelineSelection, setTimelineSelection] = useState<{ - branchKey: string - range: TrajectoryTimeRange - } | null>(null) + const [timelineSelection, setTimelineSelection] = useState(null) const actualDuration = useDuration(value => value) const [actualTime, setActualTime] = useState(false) const [searchQuery, setSearchQuery] = useState('') @@ -215,41 +208,8 @@ export function TrajectoryView({ const runningCalls = inspection.runningCalls const requests = inspection.requests const callSchemas = inspection.callSchemas - const historyContexts = inspection.contexts - const interruptedNodes = inspection.interruptedNodes - const contexts = useMemo( - () => historyContexts.length === 0 - ? [{ id: 0, nodes }] - : historyContexts, - [historyContexts, nodes], - ) - const branches = useMemo( - () => deriveTrajectoryContextBranches(contexts), - [contexts], - ) - const currentBranch = branches.at(-1) - if (currentBranch === undefined) throw new Error('trajectory branch projection must not be empty') - const selectedNodes = useMemo(() => { - const selected = new Map(currentBranch.nodes.map(node => [trajectoryNodeIdentity(node), node])) - for (const node of interruptedNodes) { - selected.set(trajectoryNodeIdentity(node), node) - } - return [...selected.values()].sort((left, right) => left.seq - right.seq) - }, [currentBranch.nodes, interruptedNodes]) - const selectedRequests = useMemo( - () => requests.filter(request => - trajectoryBranchContainsRequest(currentBranch, request), - ), - [currentBranch, requests], - ) const requestNumbers = useMemo(() => { const assistantsByStep = new Map() - for (const context of contexts) { - for (const node of context.nodes) { - if (node.kind !== 'assistant' || node.step <= 0) continue - assistantsByStep.set(`${node.turn}\u0000${node.step}`, node) - } - } for (const node of nodes) { if (node.kind !== 'assistant' || node.step <= 0) continue assistantsByStep.set(`${node.turn}\u0000${node.step}`, node) @@ -345,24 +305,24 @@ export function TrajectoryView({ return numbered }, [ - contexts, nodes, requests, + nodes, requests, ]) const partialTurn = partial?.turn ?? null const partialStep = partial?.step ?? null const finalized = useMemo(() => { const turns = deriveTrajectoryLayout({ - nodes: selectedNodes, + nodes, partial: partialTurn === null || partialStep === null ? null : { turn: partialTurn, step: partialStep, blocks: [] }, runningCalls, - requests: selectedRequests, + requests, callSchemas, }) return { turns, lastIndex: lastCellIndex(turns) } }, [ - selectedNodes, partialTurn, partialStep, - runningCalls, selectedRequests, callSchemas, + nodes, partialTurn, partialStep, + runningCalls, requests, callSchemas, ]) const timelinePartialSignature = partialStructureSignature(partial) const timelinePartial = useMemo(() => partial === null @@ -402,9 +362,7 @@ export function TrajectoryView({ () => mergeSearchMatches(finalizedSearchMatches, partialSearchMatches), [finalizedSearchMatches, partialSearchMatches], ) - const timelineRange = timelineSelection?.branchKey === currentBranch.key - ? timelineSelection.range - : null + const timelineRange = timelineSelection const timelineFocusIndexes = useMemo( () => timelineRange === null ? null @@ -420,11 +378,8 @@ export function TrajectoryView({ } }, [timelineFocusIndexes]) const handleTimelineRangeChange = useCallback((range: TrajectoryTimeRange | null) => { - setTimelineSelection(range === null ? null : { - branchKey: currentBranch.key, - range, - }) - }, [currentBranch.key]) + setTimelineSelection(range) + }, []) const handleTimelineRecordSelect = useCallback((index: number) => { setTimelineSelection(null) setTimelineRecordSelection({ index }) @@ -547,7 +502,6 @@ export function TrajectoryView({ />
-} - -interface MutableBranch { - id: number - key: string - contexts: ConversationContext[] - latest: ConversationContext - nodes: Map - startSeq: number - retainedSurfaceSeqs: Set -} - -/** - * Resolve the identity used while coalescing one trajectory branch. - * Synthetic tool interruptions share their closing boundary seq, so their - * call ids distinguish parallel roots without inventing false event order. - * @param node - projected conversation node. - * @returns branch-local semantic identity. - */ -export function trajectoryNodeIdentity(node: ConversationNode): string { - return node.kind === 'tool-result' - ? `tool-result\u0000${String(node.seq)}\u0000${node.callId}` - : `seq\u0000${String(node.seq)}` -} - -function isCompactionCheckpoint(node: ConversationNode): boolean { - if (node.kind !== 'context') return false - const source = node.source - return typeof source === 'object' - && source !== null - && 'kind' in source - && source.kind === 'plugin' - && 'plugin' in source - && source.plugin === 'compact' -} - -/** - * Join context generations across compaction/rewrite operations and split only at rewind. - * @param contexts - Append-only context generations from the runtime fold. - * @returns Rewind-delimited branches in creation order. - */ -export function deriveTrajectoryContextBranches( - contexts: readonly ConversationContext[], -): readonly TrajectoryContextBranch[] { - const mutable: MutableBranch[] = [] - for (const context of contexts) { - const startsBranch = mutable.length === 0 || context.origin === 'rewind' - if (startsBranch) { - const previous = mutable.at(-1) - const retainedSurfaceSeqs = new Set( - context.nodes - .filter(node => - context.originSeq !== undefined && node.seq < context.originSeq, - ) - .map(node => node.seq), - ) - const inheritedNodes = previous === undefined - ? [] - : [...previous.nodes.values()].filter(node => - retainedSurfaceSeqs.has(node.seq), - ) - mutable.push({ - id: context.id, - key: context.origin === 'rewind' && context.originSeq !== undefined - ? `rewind:${context.originSeq}` - : 'root', - contexts: [context], - latest: context, - nodes: new Map( - [...inheritedNodes, ...context.nodes.filter(node => !isCompactionCheckpoint(node))] - .map(node => [trajectoryNodeIdentity(node), node]), - ), - startSeq: context.originSeq ?? Number.NEGATIVE_INFINITY, - retainedSurfaceSeqs, - }) - continue - } - const branch = mutable.at(-1) - if (branch === undefined) continue - branch.contexts.push(context) - branch.latest = context - for (const node of context.nodes) { - if (!isCompactionCheckpoint(node)) branch.nodes.set(trajectoryNodeIdentity(node), node) - } - } - return mutable.map(branch => ({ - id: branch.id, - key: branch.key, - contexts: branch.contexts, - latest: branch.latest, - nodes: [...branch.nodes.values()].sort((left, right) => left.seq - right.seq), - startSeq: branch.startSeq, - retainedSurfaceSeqs: branch.retainedSurfaceSeqs, - })) -} - -/** - * Test whether a provider request belongs to one rewind branch. - * @param branch - Branch carrying the exact inherited surface event seqs. - * @param request - Provider request to classify. - * @returns Whether the request began on this branch or produced a retained surface record. - */ -export function trajectoryBranchContainsRequest( - branch: TrajectoryContextBranch, - request: RequestView, -): boolean { - if (request.startSeq >= branch.startSeq) return true - return ( - request.resultSeq !== undefined - && branch.retainedSurfaceSeqs.has(request.resultSeq) - ) || ( - request.purpose === 'compaction' - && - request.replacementSeq !== undefined - && branch.retainedSurfaceSeqs.has(request.replacementSeq) - ) -} diff --git a/packages/client/ui-trajectory/src/client/index.ts b/packages/client/ui-trajectory/src/client/index.ts index 1f48a4711d..a8a41f5183 100644 --- a/packages/client/ui-trajectory/src/client/index.ts +++ b/packages/client/ui-trajectory/src/client/index.ts @@ -45,9 +45,9 @@ export function apply(ctx: Context): void { return { hooks: { duration }, loadOlder: async () => { - const hadMore = session.getSnapshot().hasMore + const before = session.getSnapshot().views.get('trajectory') await session.loadOlder() - return hadMore + return session.getSnapshot().views.get('trajectory') !== before }, setActualDuration: (value) => { duration.set(value) }, } diff --git a/packages/client/ui-trajectory/src/client/trajectory-assistant-definition.ts b/packages/client/ui-trajectory/src/client/trajectory-assistant-definition.ts index d610f6979b..717b4855d7 100644 --- a/packages/client/ui-trajectory/src/client/trajectory-assistant-definition.ts +++ b/packages/client/ui-trajectory/src/client/trajectory-assistant-definition.ts @@ -9,6 +9,9 @@ import { } from '@deepseek-ai/dsh-client-runtime/client' import { trajectoryNode } from './trajectory-definition-common.ts' +/* jscpd:ignore-start -- Target-owned Definitions intentionally keep their event + * state machines independent; see ../../../../../.agents/notes/implemented/ + * architecture/2026-08-09-client-conversation-node-assembly.md. */ interface UsageValue { readonly inputTokens: number readonly outputTokens: number @@ -389,6 +392,7 @@ const trajectoryTurnEndDefinition: ConversationNodeDefinition = { ...(context.state.error === undefined ? {} : { error: context.state.error }), }), } +/* jscpd:ignore-end */ /** * Register the Trajectory Assistant lifecycle. diff --git a/packages/client/ui-trajectory/src/client/trajectory-contract.ts b/packages/client/ui-trajectory/src/client/trajectory-contract.ts index e261eeb9fc..3e877a7969 100644 --- a/packages/client/ui-trajectory/src/client/trajectory-contract.ts +++ b/packages/client/ui-trajectory/src/client/trajectory-contract.ts @@ -1,5 +1,5 @@ import type { - AssistantMessageNode, ConversationContext, ConversationLocation, ConversationNode, + AssistantMessageNode, ConversationLocation, ConversationNode, ConversationPromptSnapshot, ConversationViewNode, PartialAssistant, RequestPromptChange, RequestView, RunningToolCall, ToolCallBlock, } from '@deepseek-ai/dsh-client-runtime/client' @@ -59,10 +59,8 @@ export interface TrajectoryConversationViewNode extends ConversationViewNode { /** Stage-oriented Trajectory data assembled from registered business Contexts. */ export interface TrajectorySnapshot { readonly eventNodes: readonly ConversationNode[] - readonly contexts: readonly ConversationContext[] readonly requests: readonly RequestView[] readonly callSchemas: ReadonlyMap - readonly interruptedNodes: readonly ConversationNode[] readonly partial: PartialAssistant | null readonly runningCalls: readonly RunningToolCall[] } diff --git a/packages/client/ui-trajectory/src/client/trajectory-definition-common.ts b/packages/client/ui-trajectory/src/client/trajectory-definition-common.ts index 8c9c7d6489..639b1ad3ea 100644 --- a/packages/client/ui-trajectory/src/client/trajectory-definition-common.ts +++ b/packages/client/ui-trajectory/src/client/trajectory-definition-common.ts @@ -1,22 +1,8 @@ -import type { - ConversationLocation, ConversationNodeContext, -} from '@deepseek-ai/dsh-client-runtime/client' +import type { ConversationNodeContext } from '@deepseek-ai/dsh-client-runtime/client' import type { TrajectoryContribution, TrajectoryConversationViewNode, } from './trajectory-contract.ts' -/** - * Resolve the best loaded Location for one target-local Context. - * - * @param context - Context whose loaded matches provide the Location. - * @returns The start Location, first-match Location, or unresolved fallback. - */ -export function trajectoryContextLocation( - context: ConversationNodeContext, -): ConversationLocation { - return context.start?.location ?? context.matches[0]?.location ?? { kind: 'unresolved' } -} - /** * Wrap one contribution in the Engine-owned target envelope. * diff --git a/packages/client/ui-trajectory/src/client/trajectory-message-definitions.ts b/packages/client/ui-trajectory/src/client/trajectory-message-definitions.ts index a35b6080db..c8861c85a7 100644 --- a/packages/client/ui-trajectory/src/client/trajectory-message-definitions.ts +++ b/packages/client/ui-trajectory/src/client/trajectory-message-definitions.ts @@ -9,6 +9,9 @@ import { import type {} from '@deepseek-ai/dsh-agent/types' import { trajectoryNode } from './trajectory-definition-common.ts' +/* jscpd:ignore-start -- Target-owned Definitions intentionally keep their event + * state machines independent; see ../../../../../.agents/notes/implemented/ + * architecture/2026-08-09-client-conversation-node-assembly.md. */ interface InboxIdentity { readonly id: string } @@ -106,6 +109,7 @@ const trajectoryMessageDefinition: ConversationNodeDefinition = { ? null : trajectoryNode(context, context.state.seq, { kind: 'node', node: context.state }), } +/* jscpd:ignore-end */ /** * Register Trajectory-owned inbox classification and message records. diff --git a/packages/client/ui-trajectory/src/client/trajectory-snapshot-builder.ts b/packages/client/ui-trajectory/src/client/trajectory-snapshot-builder.ts index 2f4c697275..a7f2de6be4 100644 --- a/packages/client/ui-trajectory/src/client/trajectory-snapshot-builder.ts +++ b/packages/client/ui-trajectory/src/client/trajectory-snapshot-builder.ts @@ -10,17 +10,14 @@ import type { } from './trajectory-contract.ts' const EMPTY_LIST: readonly never[] = [] -const EMPTY_CONTEXTS = [{ id: 0, nodes: EMPTY_LIST }] type AssistantRequest = Extract type ToolSchema = ConversationPromptSnapshot['tools'][number] /** Stable empty target used until a Session has assembled Trajectory records. */ export const EMPTY_TRAJECTORY_SNAPSHOT: TrajectorySnapshot = { eventNodes: EMPTY_LIST, - contexts: EMPTY_CONTEXTS, requests: EMPTY_LIST, callSchemas: new Map(), - interruptedNodes: EMPTY_LIST, partial: null, runningCalls: EMPTY_LIST, } @@ -249,10 +246,8 @@ export class TrajectorySnapshotBuilder implements ConversationViewBuilder< const eventNodes = finalized return { eventNodes, - contexts: [{ id: 0, nodes: eventNodes }], requests, callSchemas, - interruptedNodes: EMPTY_LIST, partial, runningCalls, } diff --git a/packages/client/ui-trajectory/src/client/trajectory-tool-definition.ts b/packages/client/ui-trajectory/src/client/trajectory-tool-definition.ts index c72c6c8709..201ac15d72 100644 --- a/packages/client/ui-trajectory/src/client/trajectory-tool-definition.ts +++ b/packages/client/ui-trajectory/src/client/trajectory-tool-definition.ts @@ -6,6 +6,9 @@ import type { import type {} from '@deepseek-ai/dsh-tools/types' import { trajectoryNode } from './trajectory-definition-common.ts' +/* jscpd:ignore-start -- Target-owned Definitions intentionally keep their event + * state machines independent; see ../../../../../.agents/notes/implemented/ + * architecture/2026-08-09-client-conversation-node-assembly.md. */ const MAX_DEPTH = 256 interface ToolState { @@ -109,11 +112,26 @@ function childResult( function acceptsEdge(state: ToolState, parent: string, child: string): boolean { if (parent === child || state.parents.has(child)) return false let cursor: string | undefined = parent - for (let depth = 0; cursor !== undefined && depth <= MAX_DEPTH; depth++) { - if (cursor === child) return false + let parentDepth = 0 + const ancestors = new Set() + while (cursor !== undefined) { + if (cursor === child || ancestors.has(cursor)) return false + ancestors.add(cursor) + parentDepth++ cursor = state.parents.get(cursor) } - return cursor === undefined + const pending = [{ callId: child, depth: 1 }] + const descendants = new Set() + let subtreeDepth = 0 + for (const candidate of pending) { + if (descendants.has(candidate.callId)) return false + descendants.add(candidate.callId) + subtreeDepth = Math.max(subtreeDepth, candidate.depth) + for (const nested of state.children.get(candidate.callId) ?? []) { + pending.push({ callId: nested, depth: candidate.depth + 1 }) + } + } + return parentDepth + subtreeDepth <= MAX_DEPTH } function updateDispatch(state: ToolState, match: ConversationMatch): ToolState { @@ -243,6 +261,7 @@ const trajectoryToolDefinition: ConversationNodeDefinition = { return trajectoryNode(context, anchorSeq, { kind: 'tool', root }) }, } +/* jscpd:ignore-end */ /** * Register the Trajectory Tool lifecycle. diff --git a/packages/client/ui-trajectory/tests/client-bundle.spec.ts b/packages/client/ui-trajectory/tests/client-bundle.spec.ts index 902363b719..9590f28b5e 100644 --- a/packages/client/ui-trajectory/tests/client-bundle.spec.ts +++ b/packages/client/ui-trajectory/tests/client-bundle.spec.ts @@ -84,9 +84,15 @@ describe('tsdown client artifact', () => { ctx.provide('sessions', { binding: () => undefined }) const fiber = ctx.plugin(surface as { apply: (ctx: Context) => void }) await fiber.await() + const events = ctx.get('conversationEvents') as ConversationEventRegistry + const views = ctx.get('conversationViews') as ConversationViewRegistry expect(slots.entries('conversation.view').map(e => e.options.id)).toEqual(['trajectory']) + expect(events.entries().length).toBeGreaterThan(0) + expect(views.entries()).toHaveLength(1) await fiber.dispose() expect(slots.entries('conversation.view')).toHaveLength(0) + expect(events.entries()).toEqual([]) + expect(views.entries()).toEqual([]) }) it.skipIf(code === undefined)('injects plugin-tagged module CSS during factory execution', async () => { diff --git a/packages/client/ui-trajectory/tests/context-branches.spec.ts b/packages/client/ui-trajectory/tests/context-branches.spec.ts deleted file mode 100644 index 9885e9a4f9..0000000000 --- a/packages/client/ui-trajectory/tests/context-branches.spec.ts +++ /dev/null @@ -1,129 +0,0 @@ -import { describe, expect, it } from 'vitest' -import type { - ConversationContext, ConversationNode, RequestView, -} from '@deepseek-ai/dsh-client-runtime/client' -import { - deriveTrajectoryContextBranches, - trajectoryBranchContainsRequest, -} from '../src/client/context-branches.ts' - -const checkpoint = { - kind: 'context', - seq: 100, - time: 100, - content: [], - source: { kind: 'plugin', plugin: 'compact' }, - provenance: { role: 'inject', label: 'compact' }, - form: null, -} as ConversationNode - -const abandoned = { - kind: 'assistant', - seq: 20, - time: 20, - turn: 1, - step: 1, - blocks: [{ kind: 'text', text: 'abandoned' }], -} as ConversationNode - -const current = { - kind: 'user', - seq: 110, - time: 110, - content: [{ type: 'text', text: 'rewound' }], - source: { kind: 'plugin', plugin: 'rewind' }, -} as ConversationNode - -function interruptedTool(callId: string): ConversationNode { - return { - kind: 'tool-result', - seq: 19.2, - time: 20, - callId, - call: { name: 'parallel', argsRaw: '{}' }, - callTime: 10, - content: [], - isError: true, - error: { name: 'Interrupted', code: 'interrupted' }, - callView: null, - resultView: null, - subCalls: [], - } -} - -function request( - purpose: RequestView['purpose'], - startSeq: number, - resultSeq?: number, - replacementSeq?: number, -): RequestView { - const base = { - startSeq, - startedAt: startSeq, - completedAt: startSeq + 1, - status: 'complete' as const, - ...(resultSeq === undefined ? {} : { resultSeq }), - } - return purpose === 'assistant' - ? { ...base, purpose, turn: 1, step: 1 } - : { - ...base, - purpose, - turn: 1, - step: 0, - ...(replacementSeq === undefined ? {} : { replacementSeq }), - } -} - -describe('trajectory context branches', () => { - it('inherits nodes and requests by retained surface position rather than seq cutoff', () => { - const contexts: ConversationContext[] = [ - { id: 0, nodes: [checkpoint, abandoned] }, - { - id: 1, - parentId: 0, - origin: 'rewind', - originSeq: 110, - nodes: [checkpoint, current], - }, - ] - const branches = deriveTrajectoryContextBranches(contexts) - const successor = branches[1]! - - expect(successor.key).toBe('rewind:110') - expect(successor.nodes.map(node => node.seq)).toEqual([110]) - expect(trajectoryBranchContainsRequest( - successor, - request('assistant', 10, 20), - )).toBe(false) - expect(trajectoryBranchContainsRequest( - successor, - request('compaction', 90, 95, 100), - )).toBe(true) - expect(trajectoryBranchContainsRequest( - successor, - request('assistant', 111), - )).toBe(true) - }) - - it('keeps branch identity when prepended generations shift local ids', () => { - const branch = (id: number) => deriveTrajectoryContextBranches([{ - id, - origin: 'rewind', - originSeq: 110, - nodes: [current], - }])[0] - - expect(branch(1)?.key).toBe(branch(9)?.key) - }) - - it('retains parallel tool interruptions that share one closing boundary', () => { - const branch = deriveTrajectoryContextBranches([{ - id: 0, - nodes: [interruptedTool('call-a'), interruptedTool('call-b')], - }])[0] - - expect(branch?.nodes.map(node => node.kind === 'tool-result' ? node.callId : undefined)) - .toEqual(['call-a', 'call-b']) - }) -}) diff --git a/packages/client/ui-trajectory/tests/conversation-definitions.spec.ts b/packages/client/ui-trajectory/tests/conversation-definitions.spec.ts new file mode 100644 index 0000000000..f61f90c02c --- /dev/null +++ b/packages/client/ui-trajectory/tests/conversation-definitions.spec.ts @@ -0,0 +1,276 @@ +import type { Context } from 'cordis' +import { describe, expect, it } from 'vitest' +import type { + ConversationEventInput, ConversationNodeDefinition, ConversationViewDefinition, +} from '@deepseek-ai/dsh-client-runtime/client' +import { ConversationNodeAssembler } from '@deepseek-ai/dsh-client-runtime/client' +import { registerTrajectoryAssistantDefinition } from '../src/client/trajectory-assistant-definition.ts' +import { registerTrajectoryCompactionDefinitions } from '../src/client/trajectory-compaction-definition.ts' +import type { TrajectorySnapshot } from '../src/client/trajectory-contract.ts' +import { registerTrajectoryMessageDefinitions } from '../src/client/trajectory-message-definitions.ts' +import { registerTrajectoryRequestHeaderDefinition } from '../src/client/trajectory-request-header-definition.ts' +import { trajectoryViewDefinition } from '../src/client/trajectory-snapshot-builder.ts' +import { registerTrajectoryToolDefinition } from '../src/client/trajectory-tool-definition.ts' + +const DEFINITIONS: ConversationNodeDefinition[] = [] +const registrationContext = { + conversationEvents: { + register: (definition: ConversationNodeDefinition) => { + DEFINITIONS.push(definition) + return () => {} + }, + }, +} as unknown as Context + +registerTrajectoryMessageDefinitions(registrationContext) +registerTrajectoryRequestHeaderDefinition(registrationContext) +registerTrajectoryAssistantDefinition(registrationContext) +registerTrajectoryToolDefinition(registrationContext) +registerTrajectoryCompactionDefinitions(registrationContext) + +class TestEventDefinitions { + entries(): readonly ConversationNodeDefinition[] { + return DEFINITIONS + } + + fallbackEntry(): undefined { + return undefined + } +} + +class TestViewDefinitions { + entries(): readonly ConversationViewDefinition[] { + return [trajectoryViewDefinition] + } +} + +function at( + seq: number, + type: string, + data: unknown, + extra: Record = {}, +): ConversationEventInput { + return { + event: { + seq, + time: 1_700_000_000_000 + seq, + type, + data, + ...extra, + } as unknown as ConversationEventInput['event'], + view: undefined, + } +} + +function assembler(events: readonly ConversationEventInput[]): ConversationNodeAssembler { + const value = new ConversationNodeAssembler( + new TestEventDefinitions(), + new TestViewDefinitions(), + ) + value.replaceWindow(events, false) + value.flush() + return value +} + +function snapshot(value: ConversationNodeAssembler): TrajectorySnapshot { + const current = value.snapshot('trajectory') as TrajectorySnapshot | undefined + if (current === undefined) throw new Error('trajectory view was not registered') + return current +} + +function assistantMessage(id: string, text: string) { + return { + id, + role: 'assistant', + content: [{ type: 'text', text }], + source: { kind: 'model', provider: 'test', model: 'test' }, + } +} + +describe('Trajectory conversation Definitions', () => { + it('assembles streaming usage, preserves retry facts, and materializes interruption', () => { + const value = assembler([ + at(1, 'turn/start', { turn: 1 }), + at(2, 'step/start', { turn: 1, step: 1 }), + at(3, 'assistant/chunk', { + turn: 1, + step: 1, + chunk: { type: 'text-delta', index: 0, text: 'first attempt' }, + }), + at(4, 'assistant/chunk', { + turn: 1, + step: 1, + chunk: { type: 'usage', usage: { inputTokens: 10, outputTokens: 3 } }, + }), + ]) + + expect(snapshot(value).partial?.blocks).toEqual([{ kind: 'text', text: 'first attempt' }]) + expect(snapshot(value).requests).toMatchObject([{ + purpose: 'assistant', + status: 'running', + usage: { inputTokens: 10, outputTokens: 3 }, + }]) + + value.append(at(5, 'llm/retry', { + retryId: 'retry-1', + turn: 1, + step: 1, + provider: 'test', + mode: 'normal', + policyKey: 'test-normal', + retry: 1, + maxRetries: 2, + delayMs: 25, + failure: { code: 'TRANSPORT', message: 'temporary failure' }, + })) + value.append(at(6, 'assistant/chunk', { + turn: 1, + step: 1, + chunk: { type: 'text-delta', index: 0, text: 'second attempt' }, + })) + value.append(at(7, 'step/end', { turn: 1, step: 1 })) + value.flush() + + const settled = snapshot(value) + expect(settled.partial).toBeNull() + expect(settled.eventNodes).toMatchObject([{ + kind: 'assistant', + seq: 6.1, + interrupted: true, + blocks: [{ kind: 'text', text: 'second attempt' }], + }]) + expect(settled.requests).toMatchObject([{ + purpose: 'assistant', + status: 'error', + retry: 1, + maxRetries: 2, + retryDelayMs: 25, + usage: { inputTokens: 10, outputTokens: 3 }, + }]) + }) + + it('keeps parallel interrupted roots and nests Code Dispatch results', () => { + const current = snapshot(assembler([ + at(1, 'turn/start', { turn: 1 }), + at(2, 'step/start', { turn: 1, step: 1 }), + at(3, 'tool/call', { + turn: 1, step: 1, callId: 'root-a', name: 'code', arguments: '{}', + }), + at(4, 'tool/call', { + turn: 1, step: 1, callId: 'root-b', name: 'parallel', arguments: '{}', + }), + at(5, 'tool/code-dispatch-start', { + rootCallId: 'root-a', + parentCallId: 'root-a', + subCallId: 'child', + name: 'read', + arguments: { path: 'README.md' }, + }), + at(6, 'tool/code-dispatch', { + rootCallId: 'root-a', + parentCallId: 'root-a', + subCallId: 'child', + name: 'read', + arguments: { path: 'README.md' }, + content: [{ type: 'text', text: 'contents' }], + }), + at(7, 'step/end', { turn: 1, step: 1 }), + ])) + + const tools = current.eventNodes.filter(node => node.kind === 'tool-result') + expect(tools.map(node => node.callId).sort()).toEqual(['root-a', 'root-b']) + expect(tools.find(node => node.callId === 'root-a')?.subCalls).toMatchObject([{ + kind: 'tool-result', + callId: 'child', + call: { name: 'read' }, + }]) + }) + + it('assembles compaction lifecycle, checkpoint replacement, and orphan interruption', () => { + const current = snapshot(assembler([ + at(1, 'compact/start', { compactionId: 'complete', turn: null }), + at(2, 'compact/summary', { + compactionId: 'complete', + turn: null, + summary: 'summary', + provider: 'test', + model: 'test', + maxTokens: 100, + usage: { inputTokens: 20, outputTokens: 5 }, + }), + at(3, 'user/message', { + id: 'checkpoint', + role: 'user', + content: [{ type: 'text', text: 'summary checkpoint' }], + source: { kind: 'plugin', plugin: 'compact', compactionId: 'complete' }, + }), + at(4, 'compact/end', { compactionId: 'complete', turn: null }), + at(5, 'compact/start', { compactionId: 'orphan', turn: null }), + at(6, 'session/end-seed', {}), + ])) + + expect(current.requests).toMatchObject([ + { + purpose: 'compaction', + startSeq: 1, + status: 'complete', + resultSeq: 2, + replacementSeq: 3, + summary: 'summary', + }, + { + purpose: 'compaction', + startSeq: 5, + status: 'error', + completedAt: 1_700_000_000_006, + }, + ]) + }) + + it('classifies claimed inbox input as steering and consumes one inherited prompt change', () => { + const current = snapshot(assembler([ + at(1, 'agent/inbox/spliced', { + target: 'next-step', start: 0, removedCount: 0, inserted: [{ id: 'm1' }], + }), + at(2, 'agent/inbox/spliced', { + target: 'next-step', start: 0, removedCount: 1, inserted: [], + }), + at(3, 'user/message', { + id: 'm1', + role: 'user', + content: [{ type: 'text', text: 'steer here' }], + source: { kind: 'user' }, + }), + at(4, 'turn/start', { turn: 1 }), + at(5, 'request/header', { + reason: 'initial', + header: { + config: { provider: 'test', model: 'test' }, + system: 'system prompt', + tools: [], + }, + }), + at(6, 'step/start', { turn: 1, step: 1 }), + at(7, 'assistant/message', { + turn: 1, + step: 1, + message: assistantMessage('assistant-1', 'first'), + }), + at(8, 'step/end', { turn: 1, step: 1 }), + at(9, 'step/start', { turn: 1, step: 2 }), + at(10, 'assistant/message', { + turn: 1, + step: 2, + message: assistantMessage('assistant-2', 'second'), + }), + ])) + + expect(current.eventNodes.find(node => node.seq === 3)?.kind).toBe('steering') + expect(current.requests.map(request => request.purpose === 'assistant' + ? request.prompt?.system + : undefined)).toEqual(['system prompt', 'system prompt']) + expect(current.requests.map(request => request.purpose === 'assistant' + ? request.promptChange?.kind + : undefined)).toEqual(['initial', undefined]) + }) +}) diff --git a/packages/client/ui-trajectory/tests/views.spec.tsx b/packages/client/ui-trajectory/tests/views.spec.tsx index 2439fb2de5..88c7f41ccf 100644 --- a/packages/client/ui-trajectory/tests/views.spec.tsx +++ b/packages/client/ui-trajectory/tests/views.spec.tsx @@ -75,10 +75,8 @@ function historySnapshot( ): ConversationSnapshot { const trajectory: TrajectorySnapshot = { eventNodes: nodes, - contexts: [{ id: 0, nodes }], requests: [], callSchemas: new Map(), - interruptedNodes: [], partial: null, runningCalls: [], ...inspection, @@ -191,7 +189,7 @@ async function bench(snapshot = historySnapshot(NODES)) { { name: 'conversation.view', id: 'chat', order: 0, label: 'Chat' } as never, chatBody as never) const fiber = ctx.plugin({ inject: [...inject], apply }) await fiber.await() - return { ctx, slots, fiber, loadOlder } + return { ctx, slots, fiber, loadOlder, sessionStore } } /** Tab projection twin of apply's viewTabs (the render-side consumption path). */ @@ -294,8 +292,16 @@ describe('plugin registration', () => { it('fiber disposal removes the tab and leaves chat standing', async () => { const b = await bench() + const events = b.ctx.get('conversationEvents') as ConversationEventRegistry + const views = b.ctx.get('conversationViews') as ConversationViewRegistry + expect(events.entries().length).toBeGreaterThan(0) + expect(views.entries()).toHaveLength(1) + await b.fiber.dispose() + expect(tabsOf(b.slots).map(v => v.id)).toEqual(['chat']) + expect(events.entries()).toEqual([]) + expect(views.entries()).toEqual([]) }) it('shares one browser-wide duration preference across session injections', async () => { @@ -315,6 +321,23 @@ describe('plugin registration', () => { expect(localStorage.getItem('dsh.trajectory.duration')).toBe('true') expect(localStorage.getItem(`dsh.trajectory.duration.${SID}`)).toBeNull() }) + + it('reports whether loading older history changed the Trajectory snapshot', async () => { + const b = await bench() + const entry = b.slots.entries('conversation.view') + .find(candidate => candidate.options.id === 'trajectory') + const injectEntry = entry!.inject as unknown as ( + sessionId: SessionId, + ) => TrajectoryViewInjected + const injected = injectEntry(SID) + + expect(await injected.loadOlder()).toBe(false) + + b.loadOlder.mockImplementationOnce(async () => { + b.sessionStore.set(historySnapshot([...NODES])) + }) + expect(await injected.loadOlder()).toBe(true) + }) }) describe('tab switching in ConversationRoot', () => { @@ -1083,7 +1106,7 @@ describe('timeline projection', () => { }) }) -describe('TrajectoryView branches', () => { +describe('TrajectoryView state', () => { it('persists the duration preference through the runtime snapshot-store seam', () => { const firstDuration = createTrajectoryDurationStore() const commonProps = { @@ -1116,109 +1139,6 @@ describe('TrajectoryView branches', () => { .toBe('true') }) - it('renders only the selected rewind branch while retaining session-global requests', () => { - const retained = { - kind: 'user', - seq: 1, - time: 1_000, - content: [{ type: 'text', text: 'retained user' }], - source: null, - } as unknown as ConversationSnapshot['nodes'][number] - const abandoned = { - kind: 'assistant', - seq: 3, - time: 3_000, - turn: 1, - step: 1, - blocks: [{ kind: 'text', text: 'abandoned response' }], - } as unknown as ConversationSnapshot['nodes'][number] - const current = { - kind: 'assistant', - seq: 5, - time: 5_000, - turn: 2, - step: 1, - blocks: [{ kind: 'text', text: 'current response' }], - } as unknown as ConversationSnapshot['nodes'][number] - const request = (startSeq: number, turn: number): RequestView => ({ - purpose: 'assistant', - startSeq, - turn, - step: 1, - startedAt: startSeq * 1_000, - completedAt: startSeq * 1_000 + 100, - status: 'complete', - }) - const store = createSnapshotStore(historySnapshot( - [retained, abandoned, current], - { - eventNodes: [retained, abandoned, current], - contexts: [ - { id: 0, nodes: [retained, abandoned] }, - { - id: 1, - parentId: 0, - origin: 'rewind' as const, - originSeq: 4, - nodes: [retained, current], - }, - ], - requests: [request(2, 1), request(4, 2)], - callSchemas: new Map(), - }, - )) - - const view = render( - Promise.resolve(false))} - />, - ) - - expect(screen.queryByText('abandoned response')).toBeNull() - expect(screen.getByText('current response')).toBeTruthy() - expect(screen.getByRole('row', { name: /Request 2, ASSISTANT/ })).toBeTruthy() - expect(view.container.querySelectorAll('[data-request-only="true"]')).toHaveLength(0) - }) - - it('does not remount the ledger when prepending shifts a rewind generation id', () => { - const current = { - kind: 'assistant', - seq: 5, - time: 5_000, - turn: 2, - step: 1, - blocks: [{ kind: 'text', text: 'stable rewind response' }], - } as unknown as ConversationSnapshot['nodes'][number] - const snapshot = (id: number) => historySnapshot([current], { - contexts: [{ - id, - origin: 'rewind' as const, - originSeq: 4, - nodes: [current], - }], - }) - const store = createSnapshotStore(snapshot(1)) - render( - Promise.resolve(false))} - />, - ) - const row = screen.getByRole('row', { name: /stable rewind response/ }) - fireEvent.click(row) - expect(row.getAttribute('aria-selected')).toBe('true') - - act(() => { store.set(snapshot(2)) }) - - expect(screen.getByRole('row', { name: /stable rewind response/ }) - .getAttribute('aria-selected')).toBe('true') - }) - it('keeps ledger and timeline selection on the same event after prepend', () => { const older = { kind: 'user', seq: 1, time: 1_000, @@ -1249,46 +1169,6 @@ describe('TrajectoryView branches', () => { )).toBeTruthy() }) - it('retains cancellation-frozen assistant and tool nodes outside raw contexts', () => { - const retained = { - kind: 'user', seq: 1, time: 1_000, - content: [{ type: 'text', text: 'stop the task' }], source: null, - } as unknown as ConversationSnapshot['nodes'][number] - const interruptedAssistant = { - kind: 'assistant', seq: 2.1, time: 2_000, turn: 1, step: 1, - blocks: [{ kind: 'text', text: 'partial response retained' }], - interrupted: true, - } as unknown as ConversationSnapshot['nodes'][number] - const interruptedTool = { - kind: 'tool-result', seq: 2.2, time: 2_100, callId: 'slow-call', - call: { name: 'bash', argsRaw: '{"command":"sleep 30"}' }, callTime: 1_900, - content: [], isError: true, - error: { name: 'Interrupted', code: 'interrupted' }, - callView: null, resultView: null, - } as unknown as ConversationSnapshot['nodes'][number] - const store = createSnapshotStore(historySnapshot( - [retained], - { - eventNodes: [retained], - contexts: [{ id: 0, nodes: [retained] }], - requests: [], - callSchemas: new Map(), - interruptedNodes: [interruptedAssistant, interruptedTool], - }, - )) - - render( - Promise.resolve(false))} - />, - ) - - expect(screen.getByText('partial response retained')).toBeTruthy() - expect(screen.getByRole('row', { name: /TOOL, bash/ })).toBeTruthy() - }) }) describe('node half', () => { diff --git a/packages/client/ui-trajectory/tsconfig.json b/packages/client/ui-trajectory/tsconfig.json index f525474d9d..5feffced67 100644 --- a/packages/client/ui-trajectory/tsconfig.json +++ b/packages/client/ui-trajectory/tsconfig.json @@ -20,6 +20,15 @@ { "path": "../runtime" }, + { + "path": "../../core/agent" + }, + { + "path": "../../core/tools" + }, + { + "path": "../../compact/compact" + }, { "path": "../../support/invariants" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 40f2643417..771706fb80 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2813,6 +2813,9 @@ importers: '@deepseek-ai/cordis': specifier: workspace:^ version: link:../../../vendor/cordis + '@deepseek-ai/dsh-agent': + specifier: workspace:^ + version: link:../../core/agent '@deepseek-ai/dsh-client-runtime': specifier: workspace:^ version: link:../runtime @@ -2825,9 +2828,15 @@ importers: '@deepseek-ai/dsh-client-ui-slots': specifier: workspace:^ version: link:../ui-slots + '@deepseek-ai/dsh-compact': + specifier: workspace:^ + version: link:../../compact/compact '@deepseek-ai/dsh-invariants': specifier: workspace:^ version: link:../../support/invariants + '@deepseek-ai/dsh-tools': + specifier: workspace:^ + version: link:../../core/tools '@types/react': specifier: ~18.3.1 version: 18.3.31 From 556b11ef56438979f4d8e3ba70cbe8200a325239 Mon Sep 17 00:00:00 2001 From: imccyu <276526105+imccyu@users.noreply.github.com> Date: Mon, 10 Aug 2026 21:42:12 +0800 Subject: [PATCH 28/36] docs: refresh module graph --- docs/module-graph.i18n.yaml | 4 ++-- docs/module-graph.md | 11 +++++++---- docs/module-graph.zh.md | 11 +++++++---- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/docs/module-graph.i18n.yaml b/docs/module-graph.i18n.yaml index 954f038557..1f864cf46d 100644 --- a/docs/module-graph.i18n.yaml +++ b/docs/module-graph.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 docs/module-graph.md -module-graph.md: 3efb73d075f3d5d7a8bae990fc2f524dc710bcb7 -module-graph.zh.md: df3b9b38497893471b2613c0c95da409dda0262b +module-graph.md: 2218d79e28e835ab96abce96eaf92bbae25e2182 +module-graph.zh.md: 276b70d69c2898d74ac6897e398b02a8944fd503 diff --git a/docs/module-graph.md b/docs/module-graph.md index 3efb73d075..2218d79e28 100644 --- a/docs/module-graph.md +++ b/docs/module-graph.md @@ -399,9 +399,6 @@ flowchart TD pkg_client_ui_settings --> pkg_client_ui_primitives pkg_client_ui_settings --> pkg_client_ui_slots pkg_client_ui_settings --> pkg_invariants - pkg_client_ui_trajectory --> pkg_client_runtime - pkg_client_ui_trajectory --> pkg_client_ui_primitives - pkg_client_ui_trajectory --> pkg_invariants pkg_credentials_local --> pkg_atomic_write pkg_credentials_local --> pkg_credentials pkg_credentials_local --> pkg_environment @@ -893,6 +890,12 @@ flowchart TD pkg_llm_replay --> pkg_invariants pkg_llm_replay --> pkg_llm pkg_llm_replay --> pkg_session + pkg_client_ui_trajectory --> pkg_agent + pkg_client_ui_trajectory --> pkg_client_runtime + pkg_client_ui_trajectory --> pkg_client_ui_primitives + pkg_client_ui_trajectory --> pkg_compact + pkg_client_ui_trajectory --> pkg_invariants + pkg_client_ui_trajectory --> pkg_tools pkg_session_reference --> pkg_agent pkg_session_reference --> pkg_compact pkg_session_reference --> pkg_invariants @@ -1295,7 +1298,6 @@ flowchart TD | [`client-locale`](../packages/client/locale) | `client` | [`client-connection`](../packages/client/connection), [`client-runtime`](../packages/client/runtime), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants) | | [`client-ui-models`](../packages/client/ui-models) | `client` | [`client-connection`](../packages/client/connection), [`client-runtime`](../packages/client/runtime), [`client-schema-form`](../packages/client/schema-form), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slots`](../packages/client/ui-slots), [`client-web-react`](../packages/client/web-react), [`invariants`](../packages/support/invariants) | | [`client-ui-settings`](../packages/client/ui-settings) | `client` | [`client-runtime`](../packages/client/runtime), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants) | -| [`client-ui-trajectory`](../packages/client/ui-trajectory) | `client` | [`client-runtime`](../packages/client/runtime), [`client-ui-primitives`](../packages/client/ui-primitives), [`invariants`](../packages/support/invariants) | | [`credentials-local`](../packages/credentials/credentials-local) | `credentials` | [`atomic-write`](../packages/util/atomic-write), [`credentials`](../packages/credentials/credentials), [`environment`](../packages/util/environment), [`invariants`](../packages/support/invariants), [`paths`](../packages/util/paths) | | [`settings-local`](../packages/settings/settings-local) | `settings` | [`atomic-write`](../packages/util/atomic-write), [`invariants`](../packages/support/invariants), [`paths`](../packages/util/paths), [`settings`](../packages/settings/settings) | | [`llm-deepseek`](../packages/llm/llm-deepseek) | `llm` | [`credentials`](../packages/credentials/credentials), [`environment`](../packages/util/environment), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`settings`](../packages/settings/settings), [`timeout`](../packages/util/timeout) | @@ -1400,6 +1402,7 @@ flowchart TD | [`tool-session-query`](../packages/session-query/tool-session-query) | `session-query` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`session-query`](../packages/session-query/session-query), [`system-prompt`](../packages/core/system-prompt), [`timeout`](../packages/util/timeout), [`tools`](../packages/core/tools) | | [`agent-loop-testkit`](../packages/support/agent-loop-testkit) | `support` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools) | | [`llm-replay`](../packages/support/llm-replay) | `support` | [`compact`](../packages/compact/compact), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session) | +| [`client-ui-trajectory`](../packages/client/ui-trajectory) | `client` | [`agent`](../packages/core/agent), [`client-runtime`](../packages/client/runtime), [`client-ui-primitives`](../packages/client/ui-primitives), [`compact`](../packages/compact/compact), [`invariants`](../packages/support/invariants), [`tools`](../packages/core/tools) | | [`session-reference`](../packages/context/session-reference) | `context` | [`agent`](../packages/core/agent), [`compact`](../packages/compact/compact), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`retention`](../packages/util/retention), [`session`](../packages/core/session), [`session-query`](../packages/session-query/session-query) | | [`workspace-context`](../packages/context/workspace-context) | `context` | [`agent`](../packages/core/agent), [`fs`](../packages/fs/fs), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`paths`](../packages/util/paths), [`session`](../packages/core/session), [`tools`](../packages/core/tools) | | [`repeat-tool-guard`](../packages/guard/repeat-tool-guard) | `guard` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`tools`](../packages/core/tools) | diff --git a/docs/module-graph.zh.md b/docs/module-graph.zh.md index df3b9b3849..276b70d69c 100644 --- a/docs/module-graph.zh.md +++ b/docs/module-graph.zh.md @@ -401,9 +401,6 @@ flowchart TD pkg_client_ui_settings --> pkg_client_ui_primitives pkg_client_ui_settings --> pkg_client_ui_slots pkg_client_ui_settings --> pkg_invariants - pkg_client_ui_trajectory --> pkg_client_runtime - pkg_client_ui_trajectory --> pkg_client_ui_primitives - pkg_client_ui_trajectory --> pkg_invariants pkg_credentials_local --> pkg_atomic_write pkg_credentials_local --> pkg_credentials pkg_credentials_local --> pkg_environment @@ -895,6 +892,12 @@ flowchart TD pkg_llm_replay --> pkg_invariants pkg_llm_replay --> pkg_llm pkg_llm_replay --> pkg_session + pkg_client_ui_trajectory --> pkg_agent + pkg_client_ui_trajectory --> pkg_client_runtime + pkg_client_ui_trajectory --> pkg_client_ui_primitives + pkg_client_ui_trajectory --> pkg_compact + pkg_client_ui_trajectory --> pkg_invariants + pkg_client_ui_trajectory --> pkg_tools pkg_session_reference --> pkg_agent pkg_session_reference --> pkg_compact pkg_session_reference --> pkg_invariants @@ -1297,7 +1300,6 @@ flowchart TD | [`client-locale`](../packages/client/locale) | `client` | [`client-connection`](../packages/client/connection), [`client-runtime`](../packages/client/runtime), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants) | | [`client-ui-models`](../packages/client/ui-models) | `client` | [`client-connection`](../packages/client/connection), [`client-runtime`](../packages/client/runtime), [`client-schema-form`](../packages/client/schema-form), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slots`](../packages/client/ui-slots), [`client-web-react`](../packages/client/web-react), [`invariants`](../packages/support/invariants) | | [`client-ui-settings`](../packages/client/ui-settings) | `client` | [`client-runtime`](../packages/client/runtime), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants) | -| [`client-ui-trajectory`](../packages/client/ui-trajectory) | `client` | [`client-runtime`](../packages/client/runtime), [`client-ui-primitives`](../packages/client/ui-primitives), [`invariants`](../packages/support/invariants) | | [`credentials-local`](../packages/credentials/credentials-local) | `credentials` | [`atomic-write`](../packages/util/atomic-write), [`credentials`](../packages/credentials/credentials), [`environment`](../packages/util/environment), [`invariants`](../packages/support/invariants), [`paths`](../packages/util/paths) | | [`settings-local`](../packages/settings/settings-local) | `settings` | [`atomic-write`](../packages/util/atomic-write), [`invariants`](../packages/support/invariants), [`paths`](../packages/util/paths), [`settings`](../packages/settings/settings) | | [`llm-deepseek`](../packages/llm/llm-deepseek) | `llm` | [`credentials`](../packages/credentials/credentials), [`environment`](../packages/util/environment), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`settings`](../packages/settings/settings), [`timeout`](../packages/util/timeout) | @@ -1402,6 +1404,7 @@ flowchart TD | [`tool-session-query`](../packages/session-query/tool-session-query) | `session-query` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`session-query`](../packages/session-query/session-query), [`system-prompt`](../packages/core/system-prompt), [`timeout`](../packages/util/timeout), [`tools`](../packages/core/tools) | | [`agent-loop-testkit`](../packages/support/agent-loop-testkit) | `support` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools) | | [`llm-replay`](../packages/support/llm-replay) | `support` | [`compact`](../packages/compact/compact), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session) | +| [`client-ui-trajectory`](../packages/client/ui-trajectory) | `client` | [`agent`](../packages/core/agent), [`client-runtime`](../packages/client/runtime), [`client-ui-primitives`](../packages/client/ui-primitives), [`compact`](../packages/compact/compact), [`invariants`](../packages/support/invariants), [`tools`](../packages/core/tools) | | [`session-reference`](../packages/context/session-reference) | `context` | [`agent`](../packages/core/agent), [`compact`](../packages/compact/compact), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`retention`](../packages/util/retention), [`session`](../packages/core/session), [`session-query`](../packages/session-query/session-query) | | [`workspace-context`](../packages/context/workspace-context) | `context` | [`agent`](../packages/core/agent), [`fs`](../packages/fs/fs), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`paths`](../packages/util/paths), [`session`](../packages/core/session), [`tools`](../packages/core/tools) | | [`repeat-tool-guard`](../packages/guard/repeat-tool-guard) | `guard` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`tools`](../packages/core/tools) | From cc25bceec8c9a6292fe598948f956239fb1ab8cc Mon Sep 17 00:00:00 2001 From: imccyu <276526105+imccyu@users.noreply.github.com> Date: Mon, 10 Aug 2026 22:13:21 +0800 Subject: [PATCH 29/36] fix(ui-trajectory): simplify terminal contribution branch --- .../src/client/trajectory-snapshot-builder.ts | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/packages/client/ui-trajectory/src/client/trajectory-snapshot-builder.ts b/packages/client/ui-trajectory/src/client/trajectory-snapshot-builder.ts index a7f2de6be4..d10979f75f 100644 --- a/packages/client/ui-trajectory/src/client/trajectory-snapshot-builder.ts +++ b/packages/client/ui-trajectory/src/client/trajectory-snapshot-builder.ts @@ -230,13 +230,11 @@ export class TrajectorySnapshotBuilder implements ConversationViewBuilder< boundaries.push({ seq: data.seq, time: data.time }) continue } - if (data.kind === 'turn-end') { - turnEndings.push({ - turn: data.turn, - time: data.time, - ...(data.error === undefined ? {} : { error: data.error }), - }) - } + turnEndings.push({ + turn: data.turn, + time: data.time, + ...(data.error === undefined ? {} : { error: data.error }), + }) } requests.sort((left, right) => left.startSeq - right.startSeq) From 58ea69f64f84bc92d05da3aeec8f41b726173e79 Mon Sep 17 00:00:00 2001 From: imccyu <276526105+imccyu@users.noreply.github.com> Date: Mon, 10 Aug 2026 22:23:14 +0800 Subject: [PATCH 30/36] build(ui-trajectory): use rescoped cordis package --- .../ui-trajectory/src/client/trajectory-assistant-definition.ts | 2 +- .../src/client/trajectory-compaction-definition.ts | 2 +- .../ui-trajectory/src/client/trajectory-message-definitions.ts | 2 +- .../src/client/trajectory-request-header-definition.ts | 2 +- .../ui-trajectory/src/client/trajectory-snapshot-builder.ts | 2 +- .../ui-trajectory/src/client/trajectory-tool-definition.ts | 2 +- .../client/ui-trajectory/tests/conversation-definitions.spec.ts | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/client/ui-trajectory/src/client/trajectory-assistant-definition.ts b/packages/client/ui-trajectory/src/client/trajectory-assistant-definition.ts index 717b4855d7..16b61f6d53 100644 --- a/packages/client/ui-trajectory/src/client/trajectory-assistant-definition.ts +++ b/packages/client/ui-trajectory/src/client/trajectory-assistant-definition.ts @@ -1,4 +1,4 @@ -import type { Context } from 'cordis' +import type { Context } from '@deepseek-ai/cordis' import type { AssistantBlock, AssistantMessageNode, ConversationLocation, ConversationMatch, ConversationNodeContext, ConversationNodeDefinition, PartialAssistant, RequestView, diff --git a/packages/client/ui-trajectory/src/client/trajectory-compaction-definition.ts b/packages/client/ui-trajectory/src/client/trajectory-compaction-definition.ts index de6d2af21b..a822e4e5bb 100644 --- a/packages/client/ui-trajectory/src/client/trajectory-compaction-definition.ts +++ b/packages/client/ui-trajectory/src/client/trajectory-compaction-definition.ts @@ -1,4 +1,4 @@ -import type { Context } from 'cordis' +import type { Context } from '@deepseek-ai/cordis' import type { ConversationMatch, ConversationNodeDefinition, RequestView, } from '@deepseek-ai/dsh-client-runtime/client' diff --git a/packages/client/ui-trajectory/src/client/trajectory-message-definitions.ts b/packages/client/ui-trajectory/src/client/trajectory-message-definitions.ts index c8861c85a7..4139a318db 100644 --- a/packages/client/ui-trajectory/src/client/trajectory-message-definitions.ts +++ b/packages/client/ui-trajectory/src/client/trajectory-message-definitions.ts @@ -1,4 +1,4 @@ -import type { Context } from 'cordis' +import type { Context } from '@deepseek-ai/cordis' import type { ContextMessageNode, ConversationNodeDefinition, ConversationPreviousContext, SteeringMessageNode, UserMessageNode, diff --git a/packages/client/ui-trajectory/src/client/trajectory-request-header-definition.ts b/packages/client/ui-trajectory/src/client/trajectory-request-header-definition.ts index 4d8a0c9006..20a4d437e9 100644 --- a/packages/client/ui-trajectory/src/client/trajectory-request-header-definition.ts +++ b/packages/client/ui-trajectory/src/client/trajectory-request-header-definition.ts @@ -1,4 +1,4 @@ -import type { Context } from 'cordis' +import type { Context } from '@deepseek-ai/cordis' import type { ConversationMatch, ConversationNodeDefinition, ConversationPromptSnapshot, RequestPromptChange, diff --git a/packages/client/ui-trajectory/src/client/trajectory-snapshot-builder.ts b/packages/client/ui-trajectory/src/client/trajectory-snapshot-builder.ts index d10979f75f..dcc5f2edbc 100644 --- a/packages/client/ui-trajectory/src/client/trajectory-snapshot-builder.ts +++ b/packages/client/ui-trajectory/src/client/trajectory-snapshot-builder.ts @@ -1,4 +1,4 @@ -import type { Context } from 'cordis' +import type { Context } from '@deepseek-ai/cordis' import type { AssistantMessageNode, ConversationNode, ConversationPromptSnapshot, ConversationViewBuilder, ConversationViewDefinition, RequestView, diff --git a/packages/client/ui-trajectory/src/client/trajectory-tool-definition.ts b/packages/client/ui-trajectory/src/client/trajectory-tool-definition.ts index 201ac15d72..7e069dd912 100644 --- a/packages/client/ui-trajectory/src/client/trajectory-tool-definition.ts +++ b/packages/client/ui-trajectory/src/client/trajectory-tool-definition.ts @@ -1,4 +1,4 @@ -import type { Context } from 'cordis' +import type { Context } from '@deepseek-ai/cordis' import type { ConversationMatch, ConversationNodeContext, ConversationNodeDefinition, RunningToolCall, ToolCallBlock, ToolResultNode, diff --git a/packages/client/ui-trajectory/tests/conversation-definitions.spec.ts b/packages/client/ui-trajectory/tests/conversation-definitions.spec.ts index f61f90c02c..631d283f21 100644 --- a/packages/client/ui-trajectory/tests/conversation-definitions.spec.ts +++ b/packages/client/ui-trajectory/tests/conversation-definitions.spec.ts @@ -1,4 +1,4 @@ -import type { Context } from 'cordis' +import type { Context } from '@deepseek-ai/cordis' import { describe, expect, it } from 'vitest' import type { ConversationEventInput, ConversationNodeDefinition, ConversationViewDefinition, From e27dba845760211d7f8280cc02134e531dc778b7 Mon Sep 17 00:00:00 2001 From: imccyu <276526105+imccyu@users.noreply.github.com> Date: Mon, 10 Aug 2026 23:51:18 +0800 Subject: [PATCH 31/36] perf(ui-trajectory): defer trajectory text processing --- ...lient-conversation-node-assembly.i18n.yaml | 4 +- ...08-09-client-conversation-node-assembly.md | 2 + ...09-client-conversation-node-assembly.zh.md | 2 + packages/client/ui-primitives/src/Tooltip.tsx | 13 +- .../ui-primitives/tests/tooltip.spec.tsx | 21 +++ .../src/client/TrajectoryTable.tsx | 134 +++++++++++++----- .../src/client/TrajectoryTimeline.tsx | 2 +- .../src/client/TrajectoryView.tsx | 125 +++++++--------- .../client/ui-trajectory/src/client/layout.ts | 121 +++++++++------- .../src/client/trajectory-preview.ts | 20 +++ .../src/client/trajectory-record.ts | 6 +- .../src/client/trajectory-search-index.ts | 133 +++++++++++++++++ 12 files changed, 415 insertions(+), 168 deletions(-) create mode 100644 packages/client/ui-trajectory/src/client/trajectory-preview.ts create mode 100644 packages/client/ui-trajectory/src/client/trajectory-search-index.ts diff --git a/.agents/notes/implemented/architecture/2026-08-09-client-conversation-node-assembly.i18n.yaml b/.agents/notes/implemented/architecture/2026-08-09-client-conversation-node-assembly.i18n.yaml index 1dec922826..3d569b7ce2 100644 --- a/.agents/notes/implemented/architecture/2026-08-09-client-conversation-node-assembly.i18n.yaml +++ b/.agents/notes/implemented/architecture/2026-08-09-client-conversation-node-assembly.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/architecture/2026-08-09-client-conversation-node-assembly.md -2026-08-09-client-conversation-node-assembly.md: 1d5fd20bfa8c3b370f736937d54a668ca7f19ca3 -2026-08-09-client-conversation-node-assembly.zh.md: 6f0acc448950cdedcb249ada8cfd931a21765b3e +2026-08-09-client-conversation-node-assembly.md: 3b02fde8b5c8da0c7086a2de65a5ae8eea8b2526 +2026-08-09-client-conversation-node-assembly.zh.md: 2ddb14c35b3ac5aeba5b00e7d56b3a4e69a97adb diff --git a/.agents/notes/implemented/architecture/2026-08-09-client-conversation-node-assembly.md b/.agents/notes/implemented/architecture/2026-08-09-client-conversation-node-assembly.md index 1d5fd20bfa..3b02fde8b5 100644 --- a/.agents/notes/implemented/architecture/2026-08-09-client-conversation-node-assembly.md +++ b/.agents/notes/implemented/architecture/2026-08-09-client-conversation-node-assembly.md @@ -330,6 +330,8 @@ The concrete Tool renderer remains governed by the [`ui-tool ownership decision` Trajectory registers its own target and business Definitions against the same Assembler and Session event window as Chat. Its target builder preserves the stage-oriented read model without consuming the Chat Builder's legacy slice or running an independent history fold. The Chat Builder retains its legacy slice for StatsLine and the top-level public compatibility fields; target-specific Definitions do not change the shared Context, Reader, or Location contracts. +Trajectory stage/layout processing retains raw summary sources and structural data without parsing Markdown. A stable Record presentation in the Table memoizes each one-line summary by content and shares the result across body text, title, and aria-label; Detail renders only the selected record. Timeline timing labels invoke their formatters only after the delayed Tooltip opens. Search owns an independent per-view `TrajectorySearchIndex` keyed by stable Record identity with each source signature and normalized text. The initial window is indexed immediately, and a three-second throttle commits later new or changed Records in batches. Queries read only the latest committed index version, so a prepended page enters results atomically with the next batch; neither prepend nor append reparses unchanged historical Markdown. Display caching and search indexing do not share lifecycles. + ## Runtime and render path ```text diff --git a/.agents/notes/implemented/architecture/2026-08-09-client-conversation-node-assembly.zh.md b/.agents/notes/implemented/architecture/2026-08-09-client-conversation-node-assembly.zh.md index 6f0acc4489..2ddb14c35b 100644 --- a/.agents/notes/implemented/architecture/2026-08-09-client-conversation-node-assembly.zh.md +++ b/.agents/notes/implemented/architecture/2026-08-09-client-conversation-node-assembly.zh.md @@ -330,6 +330,8 @@ Assistant streaming 到 final、Tool running 到 settled 只更新同一个 Seat Trajectory 针对与 Chat 相同的 Assembler 和 Session 事件窗口注册自己的 target 与业务 Definition。它的 target builder 保留 stage-oriented read model,既不消费 Chat Builder 的 legacy slice,也不运行独立 history fold。Chat Builder 为 StatsLine 和顶层公共兼容字段保留 legacy slice;target 专属 Definition 不改变共享的 Context、Reader 或 Location 契约。 +Trajectory 的 stage/layout 只保留原始摘要来源和结构数据,不解析 Markdown。Table 的稳定 Record presentation 按内容 memo 单行摘要,并把同一结果用于正文、title 与 aria-label;Detail 只渲染当前选中记录。Timeline 的时序标签只在延迟 Tooltip 实际打开后执行格式化。搜索拥有独立的 per-view `TrajectorySearchIndex`,按稳定 Record identity 保存来源签名和标准化文本;初始窗口立即建立索引,后续新增或变化的 Record 由三秒 throttle 批量提交。查询只读取最近一次提交的索引版本,分页的新一页随下一批一次性进入结果;prepend 与 append 都不会重复解析未变化的历史 Markdown。展示缓存与搜索索引互不借用生命周期。 + ## Runtime and render path ```text diff --git a/packages/client/ui-primitives/src/Tooltip.tsx b/packages/client/ui-primitives/src/Tooltip.tsx index 449d4fe717..c1c1d1c5dc 100644 --- a/packages/client/ui-primitives/src/Tooltip.tsx +++ b/packages/client/ui-primitives/src/Tooltip.tsx @@ -24,9 +24,11 @@ interface AnchorProps { onBlur?: FocusEventHandler | undefined } +type TooltipLabel = string | (() => string) + /** * Attach a hover/focus tooltip to an anchor element. - * @param props.label - bubble text. + * @param props.label - bubble text, or a resolver evaluated only while the bubble is visible. * @param props.side - placement relative to the anchor (default 'right'). * @param props.delayMs - hover delay in milliseconds; keyboard focus remains immediate. * @param props.disabled - suppress the bubble while true; the anchor renders identically so @@ -34,7 +36,7 @@ interface AnchorProps { * @param props.children - a single anchor element; its own ref (callback or object) is forwarded alongside the tooltip's. * @returns the cloned anchor plus a fixed-position bubble while hovered/focused. */ -export function Tooltip({ label, side = 'right', delayMs = 0, disabled = false, children }: { label: string; side?: TooltipSide; delayMs?: number; disabled?: boolean; children: ReactElement }) { +export function Tooltip({ label, side = 'right', delayMs = 0, disabled = false, children }: { label: TooltipLabel; side?: TooltipSide; delayMs?: number; disabled?: boolean; children: ReactElement }) { const anchor = useRef(null) // React 18 keeps the element's ref outside props; forward it so wrapping an // anchor in Tooltip never silently severs the owner's ref. @@ -46,6 +48,9 @@ export function Tooltip({ label, side = 'right', delayMs = 0, disabled = false, }, [childRef]) const [pos, setPos] = useState<{ x: number; y: number } | null>(null) const bubble = useRef(null) + const resolvedLabel = pos === null + ? null + : typeof label === 'function' ? label() : label // Horizontal viewport clamp: fixed positioning knows nothing about edges, so // a centered bubble near the right edge would clip. Each measurement resets // the base position before applying a direct style offset, allowing a shorter @@ -67,7 +72,7 @@ export function Tooltip({ label, side = 'right', delayMs = 0, disabled = false, clamp() window.addEventListener('resize', clamp) return () => { window.removeEventListener('resize', clamp) } - }, [label, pos]) + }, [pos, resolvedLabel]) const showTimer = useRef | null>(null) // Hover and focus are independent triggers: the bubble hides only after // BOTH clear (hovering away from a focused anchor must not drop it). @@ -128,7 +133,7 @@ export function Tooltip({ label, side = 'right', delayMs = 0, disabled = false, })} {pos !== null && ( - {label} + {resolvedLabel} )} diff --git a/packages/client/ui-primitives/tests/tooltip.spec.tsx b/packages/client/ui-primitives/tests/tooltip.spec.tsx index 72b33ce12c..b355b56f68 100644 --- a/packages/client/ui-primitives/tests/tooltip.spec.tsx +++ b/packages/client/ui-primitives/tests/tooltip.spec.tsx @@ -6,6 +6,27 @@ import { Tooltip } from '@deepseek-ai/dsh-client-ui-primitives' afterEach(cleanup) describe('Tooltip', () => { + it('resolves lazy labels only after the bubble becomes visible', () => { + vi.useFakeTimers() + try { + const label = vi.fn(() => 'Timing details') + render( + + + , + ) + expect(label).not.toHaveBeenCalled() + fireEvent.mouseEnter(screen.getByText('anchor')) + act(() => { vi.advanceTimersByTime(499) }) + expect(label).not.toHaveBeenCalled() + act(() => { vi.advanceTimersByTime(1) }) + expect(screen.getByRole('tooltip').textContent).toBe('Timing details') + expect(label).toHaveBeenCalledOnce() + } finally { + vi.useRealTimers() + } + }) + it('can delay pointer hover without delaying keyboard focus', () => { vi.useFakeTimers() try { diff --git a/packages/client/ui-trajectory/src/client/TrajectoryTable.tsx b/packages/client/ui-trajectory/src/client/TrajectoryTable.tsx index 9cef2dccfb..67ec1cd2d6 100644 --- a/packages/client/ui-trajectory/src/client/TrajectoryTable.tsx +++ b/packages/client/ui-trajectory/src/client/TrajectoryTable.tsx @@ -24,7 +24,8 @@ import { groupTrajectoryVirtualRows, trajectoryVirtualRecordKey, } from './trajectory-virtual-rows.ts' import type { TrajectoryVirtualRow } from './trajectory-virtual-rows.ts' -import { trajectoryPreviewText, type TrajectoryTurnModel } from './layout.ts' +import type { TrajectoryTurnModel } from './layout.ts' +import { trajectoryPreviewText } from './trajectory-preview.ts' import css from './TrajectoryTable.module.css' const BOTTOM_FOLLOW_THRESHOLD_PX = 2 @@ -903,6 +904,11 @@ function detailTabs(record: TableRecord): readonly DetailTabItem[] { function recordDisplayText(cell: TrajectoryCellProps): string { if (isToolCallOnly(cell)) return '' + if (cell.previewMarkdown !== undefined) { + const preview = trajectoryPreviewText(cell.previewMarkdown) + if (cell.text === '') return preview + return preview === '' ? cell.text : `${cell.text} · ${preview}` + } if (cell.text !== '') return cell.text const markdown = cell.kind === 'user' || cell.kind === 'context' ? cell.inputDetail @@ -912,6 +918,12 @@ function recordDisplayText(cell: TrajectoryCellProps): string { return markdown === undefined ? '' : trajectoryPreviewText(markdown) } +function recordResultText(cell: TrajectoryCellProps): string | undefined { + return cell.resultPreviewMarkdown === undefined + ? cell.result + : trajectoryPreviewText(cell.resultPreviewMarkdown) +} + function toolCallTextParts( kind: TrajectoryCellKind, text: string, @@ -932,6 +944,71 @@ function isToolCallOnly(cell: TrajectoryCellProps): boolean { && cell.text === 'Tool call only' } +interface RecordPresentationValue { + displayText: string + listDisplayText: string + resultText: string | undefined + toolCallOnly: boolean + toolCallText: ToolCallTextParts | undefined +} + +function RecordPresentation({ + cell, + children, +}: { + cell: TrajectoryCellProps + children: (value: RecordPresentationValue) => ReactNode +}) { + const displayText = useMemo( + () => recordDisplayText(cell), + [ + cell.kind, cell.text, cell.previewMarkdown, + cell.inputDetail, cell.outputDetail, cell.thinkingDetail, + ], + ) + const resultText = useMemo( + () => recordResultText(cell), + [cell.result, cell.resultPreviewMarkdown], + ) + const toolCallOnly = isToolCallOnly(cell) + const toolCallText = toolCallTextParts(cell.kind, displayText) + const listDisplayText = toolCallOnly + ? '(tool call only)' + : toolCallText === undefined + ? displayText + : [toolCallText.name, toolCallText.args].filter(Boolean).join(' ') + return children({ + displayText, + listDisplayText, + resultText, + toolCallOnly, + toolCallText, + }) +} + +function RecordListText({ + displayText, + toolCallOnly, + toolCallText, +}: Pick) { + if (toolCallOnly) { + return (tool call only) + } + if (toolCallText === undefined) return displayText || '—' + return ( + <> + + {toolCallText.name || '—'} + + {toolCallText.args !== undefined && ( + + {toolCallText.args} + + )} + + ) +} + function MarkdownFragment({ text, rendered, @@ -2131,15 +2208,12 @@ export function TrajectoryTable({ /> )} - {renderedRecords.map(({ record, position, terminalRequestBoundary }) => { - const displayText = recordDisplayText(record.cell) - const toolCallOnly = isToolCallOnly(record.cell) - const toolCallText = toolCallTextParts(record.cell.kind, displayText) - const listDisplayText = toolCallOnly - ? '(tool call only)' - : toolCallText === undefined - ? displayText - : [toolCallText.name, toolCallText.args].filter(Boolean).join(' ') + {renderedRecords.map(({ record, position, terminalRequestBoundary }) => ( + + {({ displayText, listDisplayText, resultText, toolCallOnly, toolCallText }) => { const isCollapsedSummary = record.collapsedSummary !== undefined const isRequestOnly = record.cell.requestOnly === true const isInitialSystem = record.cell.kind === 'system' @@ -2169,7 +2243,6 @@ export function TrajectoryTable({ : activeTurn === record.turn return ( - - {toolCallOnly - ? (tool call only) - : toolCallText === undefined - ? listDisplayText || '—' - : ( - <> - - {toolCallText.name || '—'} - - {toolCallText.args !== undefined && ( - - {toolCallText.args} - - )} - - )} + + - {record.cell.result !== undefined && ( + {resultText !== undefined && ( - - {record.cell.result} + {resultText} )} @@ -2387,7 +2449,9 @@ export function TrajectoryTable({ ) - })} + }} + + ))} {virtualBottom > 0 && ( timelineTooltipLabel(span.kind, detail)} side="bottom" delayMs={TIMELINE_TOOLTIP_DELAY_MS} > diff --git a/packages/client/ui-trajectory/src/client/TrajectoryView.tsx b/packages/client/ui-trajectory/src/client/TrajectoryView.tsx index 5651e620e5..2b2e50fc65 100644 --- a/packages/client/ui-trajectory/src/client/TrajectoryView.tsx +++ b/packages/client/ui-trajectory/src/client/TrajectoryView.tsx @@ -1,6 +1,6 @@ /** Trajectory view: compact summary over a turn-aware event ledger. */ -import { useCallback, useMemo, useState } from 'react' +import { useCallback, useEffect, useMemo, useRef, useState } from 'react' import type { ConvViewProps } from '@deepseek-ai/dsh-client-ui-conversation/client' import type { InjectFace } from '@deepseek-ai/dsh-client-ui-slots' import type { @@ -24,11 +24,13 @@ import { type TrajectoryTimeRange, } from './timeline.ts' import { trajectoryRecordId } from './trajectory-record.ts' +import { TrajectorySearchIndex } from './trajectory-search-index.ts' import { EMPTY_TRAJECTORY_SNAPSHOT } from './trajectory-snapshot-builder.ts' import css from './views.module.css' const EMPTY_TURN_IDS: ReadonlySet = new Set() const EMPTY_RECORD_IDS: ReadonlySet = new Set() +const SEARCH_INDEX_THROTTLE_MS = 3_000 function lastCellIndex(turns: readonly TrajectoryTurnModel[]): number { let last = 0 @@ -115,70 +117,6 @@ function addUsage( } } -function searchableJson(value: unknown): string { - if (value === undefined) return '' - try { - return JSON.stringify(value) - } catch { - return '' - } -} - -function searchMatches( - turns: ReturnType, - query: string, -): ReadonlySet | null { - const terms = query.trim().toLocaleLowerCase().split(/\s+/).filter(Boolean) - if (terms.length === 0) return null - const matches = new Set() - for (const turn of turns) { - for (const group of turn.groups) { - for (const cell of group.cells) { - if (cell.requestOnly === true) continue - const blocks = [ - ...(cell.sourceBlocks ?? []), - ...(cell.outputBlocks ?? []), - ] - const text = [ - turn.turn === null ? 'between turns' : `turn ${turn.turn}`, - group.title, - cell.kind, - cell.kind === 'message' ? 'assistant' : undefined, - cell.text, - cell.inputDetail, - cell.outputDetail, - cell.thinkingDetail, - cell.schemaDetail, - cell.result, - cell.callId, - ...blocks.flatMap(block => [ - block.type, - block.content, - block.callId, - block.toolName, - block.imageAlt, - ]), - searchableJson(cell.messageSource), - searchableJson(cell.promptDetail), - searchableJson(cell.previousPromptDetail), - ].filter((value): value is string => typeof value === 'string') - .join('\n') - .toLocaleLowerCase() - if (terms.every(term => text.includes(term))) matches.add(cell.index) - } - } - } - return matches -} - -function mergeSearchMatches( - finalized: ReadonlySet | null, - partial: ReadonlySet | null, -): ReadonlySet | null { - if (finalized === null || partial === null) return null - return new Set([...finalized, ...partial]) -} - export function TrajectoryView({ useSession, useDuration, loadOlder, setActualDuration, inspect, onInspectDone, @@ -190,6 +128,10 @@ export function TrajectoryView({ const actualDuration = useDuration(value => value) const [actualTime, setActualTime] = useState(false) const [searchQuery, setSearchQuery] = useState('') + const [searchIndex] = useState(() => new TrajectorySearchIndex()) + const [searchIndexRevision, setSearchIndexRevision] = useState(0) + const searchIndexTimer = useRef | null>(null) + const searchIndexInitialized = useRef(false) const [selectedTimelineIndex, setSelectedTimelineIndex] = useState(null) const [timelineRecordSelection, setTimelineRecordSelection] = useState<{ readonly index: number @@ -340,28 +282,59 @@ export function TrajectoryView({ const timelineMode: TrajectoryTimelineMode = actualDuration ? actualTime ? 'actual' : 'duration' : actualTime ? 'time' : 'sequence' - const finalizedSearchMatches = useMemo( - () => searchMatches(finalized.turns, searchQuery), - [finalized, searchQuery], - ) const partialSearchTurns = useMemo( () => appendTrajectoryPartialLayout([], partial, finalized.lastIndex), [finalized.lastIndex, partial], ) + const searchLayouts = useMemo( + () => [finalized.turns, partialSearchTurns] as const, + [finalized, partialSearchTurns], + ) + const latestSearchLayouts = useRef(searchLayouts) + latestSearchLayouts.current = searchLayouts + useEffect(() => { + if (!searchIndexInitialized.current) { + searchIndexInitialized.current = true + if (searchIndex.update(searchLayouts)) { + setSearchIndexRevision(revision => revision + 1) + } + return + } + if (searchIndexTimer.current !== null) return + searchIndexTimer.current = setTimeout(() => { + searchIndexTimer.current = null + if (searchIndex.update(latestSearchLayouts.current)) { + setSearchIndexRevision(revision => revision + 1) + } + }, SEARCH_INDEX_THROTTLE_MS) + }, [searchIndex, searchLayouts]) + useEffect(() => () => { + if (searchIndexTimer.current !== null) clearTimeout(searchIndexTimer.current) + }, []) const streamingCells = useMemo( () => partialSearchTurns.flatMap(turn => turn.groups.flatMap(group => group.cells), ), [partialSearchTurns], ) - const partialSearchMatches = useMemo( - () => searchMatches(partialSearchTurns, searchQuery), - [partialSearchTurns, searchQuery], - ) - const searchMatchIndexes = useMemo( - () => mergeSearchMatches(finalizedSearchMatches, partialSearchMatches), - [finalizedSearchMatches, partialSearchMatches], + const searchMatchRecordIds = useMemo( + () => searchIndex.search(searchQuery), + [searchIndex, searchIndexRevision, searchQuery], ) + const searchMatchIndexes = useMemo(() => { + if (searchMatchRecordIds === null) return null + const indexes = new Set() + for (const turns of searchLayouts) { + for (const turn of turns) { + for (const group of turn.groups) { + for (const cell of group.cells) { + if (searchMatchRecordIds.has(trajectoryRecordId(cell))) indexes.add(cell.index) + } + } + } + } + return indexes + }, [searchLayouts, searchMatchRecordIds]) const timelineRange = timelineSelection const timelineFocusIndexes = useMemo( () => timelineRange === null diff --git a/packages/client/ui-trajectory/src/client/layout.ts b/packages/client/ui-trajectory/src/client/layout.ts index 0d7a8c9e07..3a118aadfb 100644 --- a/packages/client/ui-trajectory/src/client/layout.ts +++ b/packages/client/ui-trajectory/src/client/layout.ts @@ -12,7 +12,6 @@ import type { ToolCallBlock, ToolResultNode, } from '@deepseek-ai/dsh-client-runtime/client' -import { extractMarkdownPlainText } from '@deepseek-ai/dsh-client-ui-primitives' import type { TrajectoryCellProps, TrajectorySourceBlock, @@ -70,9 +69,6 @@ interface TurnBucket { type AssistantRequestView = Extract type CompactionRequestView = Extract -const PREVIEW_SOURCE_CHARACTERS = 2_048 -const PREVIEW_OUTPUT_CHARACTERS = 512 - type InputNode = Extract< ConversationSnapshot['nodes'][number], { kind: 'user' | 'context' } @@ -110,10 +106,19 @@ function layoutEntryOrder(entry: OrderedLayoutEntry): number { function inputCellDetail(node: InputNode): Pick< TrajectoryCellProps, - 'text' | 'sourceSeq' | 'messageSource' | 'inputDetail' | 'sourceBlocks' | 'timeSeconds' | 'startedAt' + | 'text' + | 'previewMarkdown' + | 'sourceSeq' + | 'messageSource' + | 'inputDetail' + | 'sourceBlocks' + | 'timeSeconds' + | 'startedAt' > { + const previewMarkdown = previewContent(node.content) return { - text: summarizeContent(node.content), + text: '', + ...(previewMarkdown === undefined ? {} : { previewMarkdown }), sourceSeq: node.seq, messageSource: node.source, inputDetail: detailContent(node.content), @@ -293,7 +298,10 @@ export function deriveTrajectoryLayout(input: TrajectoryLayoutInput): readonly T ? request.error ?? 'Compaction failed' : request.summary === undefined ? 'Context compacted' - : summarizeContent(request.summary), + : '', + ...(request.status === 'complete' && request.summary !== undefined + ? previewContentProperty(request.summary) + : {}), sourceSeq: request.startSeq, ...(request.summary === undefined ? {} @@ -377,6 +385,7 @@ export function deriveTrajectoryLayout(input: TrajectoryLayoutInput): readonly T if (node.kind === 'tool-result') { if (!emittedCallIds.has(node.callId)) { const toolName = node.call?.name + const resultPreview = summarizeResult(node) const laidList: LaidCell[] = [{ absTime: finiteTime(node.callTime ?? node.time), ...(toolName !== undefined ? { toolName } : {}), @@ -386,13 +395,13 @@ export function deriveTrajectoryLayout(input: TrajectoryLayoutInput): readonly T index: ++index, kind: 'tool', sourceSeq: node.seq, - text: node.call !== null + ...(node.call !== null ? summarizeCall(node.call.name, node.call.argsRaw) - : summarizeResult(node), + : resultAsText(resultPreview)), ...(node.call !== null ? { inputDetail: node.call.argsRaw } : {}), outputDetail: detailResult(node), outputBlocks: node.content.map(block => sourceBlock(block)), - result: summarizeResult(node), + ...resultPreview, callId: node.callId, isError: node.isError, timeSeconds: durationSeconds(node.time, node.callTime), @@ -440,7 +449,7 @@ export function deriveTrajectoryLayout(input: TrajectoryLayoutInput): readonly T cell: { index: ++index, kind: 'tool', - text: summarizeCall(call.name, call.argsRaw), + ...summarizeCall(call.name, call.argsRaw), inputDetail: call.argsRaw, callId: call.callId, timeSeconds: null, @@ -650,11 +659,14 @@ function expandAssistant( recordId: `assistant\u0000${node.turn}\u0000${node.step}`, kind: 'message', sourceSeq: node.seq, - text: messageText !== '' - ? summarizeText(messageText) + text: messageText !== '' || thinkingText !== '' + ? '' + : summarizeAssistantActivity(node.blocks), + ...(messageText !== '' + ? { previewMarkdown: messageText } : thinkingText !== '' - ? summarizeText(thinkingText) - : summarizeAssistantActivity(node.blocks), + ? { previewMarkdown: thinkingText } + : {}), ...(messageText !== '' ? { outputDetail: messageText } : {}), ...(thinkingText !== '' ? { thinkingDetail: thinkingText } : {}), sourceBlocks: node.blocks.map(block => assistantSourceBlock(block)), @@ -681,6 +693,7 @@ function expandAssistant( : durationSeconds(result.time, result.callTime) const callAbs = finiteTime(callStarts.get(block.callId)) const call = calls.get(block.callId) + const resultPreview = result === undefined ? undefined : summarizeResult(result) out.push({ absTime: callAbs, toolName: block.name, @@ -688,14 +701,14 @@ function expandAssistant( ...(call === undefined ? {} : { subCalls: call.subCalls }), cell: { index: ++index, kind: 'tool', - text: summarizeCall(block.name, block.argsRaw), + ...summarizeCall(block.name, block.argsRaw), inputDetail: block.argsRaw, callId: block.callId, ...(result !== undefined ? { outputDetail: detailResult(result), outputBlocks: result.content.map(block => sourceBlock(block)), - result: summarizeResult(result), + ...resultPreview, isError: result.isError, } : {}), @@ -919,6 +932,7 @@ function expandSubCalls( let index = startIndex for (const sub of subs) { const settled = 'kind' in sub + const resultPreview = settled ? summarizeResult(sub) : undefined const laid: LaidCell = { absTime: settled ? finiteTime(sub.callTime ?? sub.time) : finiteTime(sub.time), toolName: settled ? sub.call?.name ?? sub.callId : sub.name, @@ -927,9 +941,11 @@ function expandSubCalls( index: ++index, kind: 'subtool', callId: sub.callId, - text: settled - ? (sub.call !== null ? summarizeCall(sub.call.name, sub.call.argsRaw) : summarizeResult(sub)) - : summarizeCall(sub.name, sub.argsRaw), + ...(settled + ? (sub.call !== null + ? summarizeCall(sub.call.name, sub.call.argsRaw) + : resultAsText(resultPreview)) + : summarizeCall(sub.name, sub.argsRaw)), ...(settled ? (sub.call !== null ? { inputDetail: sub.call.argsRaw } : {}) : { inputDetail: sub.argsRaw }), @@ -937,7 +953,7 @@ function expandSubCalls( ? { outputDetail: detailResult(sub), outputBlocks: sub.content.map(block => sourceBlock(block)), - result: summarizeResult(sub), + ...resultPreview, isError: sub.isError, } : {}), @@ -958,22 +974,39 @@ function expandSubCalls( return out } -function summarizeCall(name: string, argsRaw: string): string { - const args = trajectoryPreviewText(argsRaw) - if (args === '') return name - return `${name} · ${args}` +function summarizeCall( + name: string, + argsRaw: string, +): Pick { + return { + text: name, + ...(argsRaw === '' ? {} : { previewMarkdown: argsRaw }), + } } -function summarizeResult(node: ToolResultNode): string { +function summarizeResult( + node: ToolResultNode, +): Pick { if (node.isError) { - return node.error?.code ?? 'error' + return { result: node.error?.code ?? 'error' } } for (const block of node.content) { if (block.type === 'text' && typeof block.text === 'string' && block.text !== '') { - return summarizeText(block.text) + return { result: '', resultPreviewMarkdown: block.text } } } - return 'No output' + return { result: 'No output' } +} + +function resultAsText( + result: Pick | undefined, +): Pick { + return { + text: result?.result ?? '', + ...(result?.resultPreviewMarkdown === undefined + ? {} + : { previewMarkdown: result.resultPreviewMarkdown }), + } } function detailResult(node: ToolResultNode): string { @@ -1009,28 +1042,18 @@ function detailReasoning(content: readonly { type: string; text?: string }[]): s .join('\n') } -function summarizeContent(content: readonly { type: string; text?: string }[]): string { +function previewContent( + content: readonly { type: string; text?: string }[], +): string | undefined { for (const block of content) { - if (block.type === 'text' && typeof block.text === 'string') return summarizeText(block.text) + if (block.type === 'text' && typeof block.text === 'string') return block.text } - return '' + return undefined } -function summarizeText(text: string): string { - return trajectoryPreviewText(text) -} - -/** - * Build a bounded one-line ledger preview without parsing the complete Markdown document. - * Full source remains on the cell for the inspector. - * @param text - Untrusted message, reasoning, payload, or result text. - * @returns A compact preview capped independently from the retained source. - */ -export function trajectoryPreviewText(text: string): string { - const source = text.slice(0, PREVIEW_SOURCE_CHARACTERS) - const compact = extractMarkdownPlainText(source).replace(/\s+/g, ' ').trim() - const preview = compact.slice(0, PREVIEW_OUTPUT_CHARACTERS).trimEnd() - return source.length < text.length || preview.length < compact.length - ? `${preview}…` - : preview +function previewContentProperty( + content: readonly { type: string; text?: string }[], +): Pick { + const previewMarkdown = previewContent(content) + return previewMarkdown === undefined ? {} : { previewMarkdown } } diff --git a/packages/client/ui-trajectory/src/client/trajectory-preview.ts b/packages/client/ui-trajectory/src/client/trajectory-preview.ts new file mode 100644 index 0000000000..840fc2381e --- /dev/null +++ b/packages/client/ui-trajectory/src/client/trajectory-preview.ts @@ -0,0 +1,20 @@ +/** Bounded Markdown-to-text projection shared by trajectory consumers. */ + +import { extractMarkdownPlainText } from '@deepseek-ai/dsh-client-ui-primitives' + +const PREVIEW_SOURCE_CHARACTERS = 2_048 +const PREVIEW_OUTPUT_CHARACTERS = 512 + +/** + * Build a bounded one-line preview without parsing the complete Markdown document. + * @param text - Untrusted message, reasoning, payload, or result text. + * @returns A compact preview capped independently from the retained source. + */ +export function trajectoryPreviewText(text: string): string { + const source = text.slice(0, PREVIEW_SOURCE_CHARACTERS) + const compact = extractMarkdownPlainText(source).replace(/\s+/g, ' ').trim() + const preview = compact.slice(0, PREVIEW_OUTPUT_CHARACTERS).trimEnd() + return source.length < text.length || preview.length < compact.length + ? `${preview}…` + : preview +} diff --git a/packages/client/ui-trajectory/src/client/trajectory-record.ts b/packages/client/ui-trajectory/src/client/trajectory-record.ts index 2c3f2a1a83..38101f8233 100644 --- a/packages/client/ui-trajectory/src/client/trajectory-record.ts +++ b/packages/client/ui-trajectory/src/client/trajectory-record.ts @@ -40,8 +40,10 @@ export interface TrajectoryCellProps extends HTMLAttributes { /** Projection-stable identity when no single source event owns the record lifecycle. */ recordId?: string kind: TrajectoryCellKind - /** Single-line summary; CSS ellipsis when it overflows. */ + /** Non-Markdown summary or prefix; CSS ellipsis when it overflows. */ text: string + /** Raw Markdown source converted into the single-line summary at its consumer. */ + previewMarkdown?: string /** Whether this user record opens a new model turn. */ opensTurn?: boolean /** Source session-event seq for cross-record navigation. */ @@ -71,6 +73,8 @@ export interface TrajectoryCellProps extends HTMLAttributes { assistantMetrics?: AssistantMetricDetail /** Tool-only result summary paired with the call in the same record. */ result?: string + /** Raw Markdown source converted into the tool-result summary at its consumer. */ + resultPreviewMarkdown?: string /** Tool call id used to link message source blocks to tool records. */ callId?: string /** Tool-only result failure state. */ diff --git a/packages/client/ui-trajectory/src/client/trajectory-search-index.ts b/packages/client/ui-trajectory/src/client/trajectory-search-index.ts new file mode 100644 index 0000000000..889fbff7e6 --- /dev/null +++ b/packages/client/ui-trajectory/src/client/trajectory-search-index.ts @@ -0,0 +1,133 @@ +/** Incremental full-text index for the trajectory ledger. */ + +import type { TrajectoryTurnModel } from './layout.ts' +import type { TrajectoryCellProps } from './trajectory-record.ts' +import { trajectoryRecordId } from './trajectory-record.ts' +import { trajectoryPreviewText } from './trajectory-preview.ts' + +interface SearchEntry { + readonly sources: readonly string[] + readonly text: string +} + +function searchableJson(value: unknown): string { + if (value === undefined) return '' + try { + return JSON.stringify(value) + } catch { + return '' + } +} + +function sameSources(left: readonly string[], right: readonly string[]): boolean { + return left.length === right.length && left.every((value, index) => value === right[index]) +} + +function markdownPreview(cell: TrajectoryCellProps): string { + if (cell.previewMarkdown === undefined) return '' + const preview = trajectoryPreviewText(cell.previewMarkdown) + if (cell.text === '') return preview + return preview === '' ? cell.text : `${cell.text} · ${preview}` +} + +function resultPreview(cell: TrajectoryCellProps): string { + return cell.resultPreviewMarkdown === undefined + ? cell.result ?? '' + : trajectoryPreviewText(cell.resultPreviewMarkdown) +} + +function recordSources( + turn: number | null, + group: string, + cell: TrajectoryCellProps, +): readonly string[] { + const blocks = [ + ...(cell.sourceBlocks ?? []), + ...(cell.outputBlocks ?? []), + ] + return [ + turn === null ? 'between turns' : `turn ${turn}`, + group, + cell.kind, + cell.kind === 'message' ? 'assistant' : '', + cell.text, + cell.previewMarkdown ?? '', + cell.inputDetail ?? '', + cell.outputDetail ?? '', + cell.thinkingDetail ?? '', + cell.schemaDetail ?? '', + cell.result ?? '', + cell.resultPreviewMarkdown ?? '', + cell.callId ?? '', + ...blocks.flatMap(block => [ + block.type, + block.content, + block.callId ?? '', + block.toolName ?? '', + block.imageAlt ?? '', + ]), + searchableJson(cell.messageSource), + searchableJson(cell.promptDetail), + searchableJson(cell.previousPromptDetail), + ] +} + +/** Session-view-local index that reparses Markdown only when one record's source changes. */ +export class TrajectorySearchIndex { + private readonly entries = new Map() + private layouts: readonly (readonly TrajectoryTurnModel[])[] | undefined + + /** + * Incrementally synchronize one or more current trajectory layout slices. + * @param layouts - Finalized and optional streaming layouts from the same view. + * @returns Whether the indexed layout version changed. + */ + update(layouts: readonly (readonly TrajectoryTurnModel[])[]): boolean { + if (this.layouts === layouts) return false + this.layouts = layouts + const seen = new Set() + for (const turns of layouts) { + for (const turn of turns) { + for (const group of turn.groups) { + for (const cell of group.cells) { + if (cell.requestOnly === true) continue + const id = trajectoryRecordId(cell) + const sources = recordSources(turn.turn, group.title, cell) + const previous = this.entries.get(id) + const entry = previous !== undefined && sameSources(previous.sources, sources) + ? previous + : { + sources, + text: [ + ...sources, + markdownPreview(cell), + resultPreview(cell), + ].join('\n').toLocaleLowerCase(), + } + this.entries.set(id, entry) + seen.add(id) + } + } + } + } + for (const id of this.entries.keys()) { + if (!seen.has(id)) this.entries.delete(id) + } + return true + } + + /** + * Match a query against the latest committed index version. + * @param query - Space-separated case-insensitive search terms. + * @returns Matching stable record identities, or `null` without a query. + */ + search(query: string): ReadonlySet | null { + const terms = query.trim().toLocaleLowerCase().split(/\s+/).filter(Boolean) + if (terms.length === 0) return null + const matches = new Set() + for (const [id, entry] of this.entries) { + if (terms.every(term => entry.text.includes(term))) matches.add(id) + } + return matches + } +} From 2695f31edb633a2a59ecc8fbd27162184137a219 Mon Sep 17 00:00:00 2001 From: imccyu <276526105+imccyu@users.noreply.github.com> Date: Tue, 11 Aug 2026 00:01:14 +0800 Subject: [PATCH 32/36] test(ui-trajectory): assert deferred preview sources --- .../ui-trajectory/tests/layout.spec.tsx | 43 +++++++++++++------ 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/packages/client/ui-trajectory/tests/layout.spec.tsx b/packages/client/ui-trajectory/tests/layout.spec.tsx index 4c49b07907..d04c95b46d 100644 --- a/packages/client/ui-trajectory/tests/layout.spec.tsx +++ b/packages/client/ui-trajectory/tests/layout.spec.tsx @@ -84,7 +84,10 @@ describe('deriveTrajectoryLayout', () => { input: 10, output: 20, think: 5, timeSeconds: 5, }) const tool = turns[0]?.groups.flatMap(g => g.cells).find(c => c.kind === 'tool') - expect(tool?.text).toBe('bash · {"command":"ls"}') + expect(tool).toMatchObject({ + text: 'bash', + previewMarkdown: '{"command":"ls"}', + }) expect(tool?.timeSeconds).toBe(1.3) }) @@ -99,7 +102,10 @@ describe('deriveTrajectoryLayout', () => { }) expect(turns[0]?.groups.map(g => g.title)).toEqual(['Step 2']) expect(turns[0]?.groups[0]?.cells[0]).toMatchObject({ - kind: 'tool', text: 'bash · {"command":"pwd"}', timeSeconds: null, + kind: 'tool', + text: 'bash', + previewMarkdown: '{"command":"pwd"}', + timeSeconds: null, }) }) @@ -132,7 +138,8 @@ describe('deriveTrajectoryLayout', () => { expect(streamed[1]?.groups[0]?.cells).toMatchObject([{ index: 2, kind: 'message', - text: 'streaming', + text: '', + previewMarkdown: 'streaming', timeSeconds: null, }]) expect(streamed[1]?.groups[0]?.cells[0]?.requestOnly).toBeUndefined() @@ -222,8 +229,14 @@ describe('deriveTrajectoryLayout', () => { ] as unknown as ConversationSnapshot['nodes'] const turns = deriveTrajectoryLayout({ nodes, partial: null, runningCalls: [] }) expect(turns.map(t => t.turn)).toEqual([1, 2]) - expect(turns[0]?.groups.flatMap(g => g.cells.map(c => c.text))).toEqual(['first', 'ok1']) - expect(turns[1]?.groups.flatMap(g => g.cells.map(c => c.text))).toEqual(['second', 'ok2']) + expect(turns[0]?.groups.flatMap(g => g.cells.map(c => c.previewMarkdown))).toEqual([ + 'first', + 'ok1', + ]) + expect(turns[1]?.groups.flatMap(g => g.cells.map(c => c.previewMarkdown))).toEqual([ + 'second', + 'ok2', + ]) }) it('places standalone compaction chronologically in its own between-turn section', () => { @@ -263,7 +276,8 @@ describe('deriveTrajectoryLayout', () => { cells: [{ kind: 'compacted', sourceSeq: 3, - text: 'standalone summary', + text: '', + previewMarkdown: 'standalone summary', }], }]) }) @@ -279,7 +293,7 @@ describe('deriveTrajectoryLayout', () => { const turns = deriveTrajectoryLayout({ nodes, partial: null, runningCalls: [] }) const message = turns[0]?.groups.flatMap(g => g.cells).find(c => c.kind === 'message') expect(message).toMatchObject({ - text: '…', input: 11, output: 22, think: 3, + text: '', previewMarkdown: '…', input: 11, output: 22, think: 3, }) }) @@ -296,9 +310,8 @@ describe('deriveTrajectoryLayout', () => { const message = turns[0]?.groups.flatMap(group => group.cells) .find(cell => cell.kind === 'message') - expect(message?.text.startsWith('Investigation NAVIGATION_OK file_path')).toBe(true) - expect(message?.text.endsWith('…')).toBe(true) - expect(message?.text.length).toBeLessThanOrEqual(513) + expect(message?.text).toBe('') + expect(message?.previewMarkdown).toBe(thinking) expect(message?.thinkingDetail).toBe(thinking) }) @@ -331,7 +344,7 @@ describe('deriveTrajectoryLayout', () => { ] as unknown as ConversationSnapshot['nodes'] const turns = deriveTrajectoryLayout({ nodes, partial: null, runningCalls: [] }) const cells = turns[0]?.groups.flatMap(g => g.cells) ?? [] - const message = cells.find(c => c.kind === 'message' && c.text === 'done') + const message = cells.find(c => c.kind === 'message' && c.previewMarkdown === 'done') // From the compaction marker at 9.5s, not from context at 9s or the earlier surfaces. expect(message?.timeSeconds).toBe(0.5) // Context remains inspectable in trajectory; the Chat marker is not duplicated. @@ -394,7 +407,9 @@ describe('run_code sub-dispatch cells', () => { expect(cells[0]?.text).toBe('Tool call only') // Sequential indexes across the interleave; durations from the pair times. expect(cells.map(c => c.index)).toEqual([1, 2, 3, 4]) - expect(cells[2]).toMatchObject({ text: 'bash · {"x":1}', timeSeconds: 1 }) + expect(cells[2]).toMatchObject({ + text: 'bash', previewMarkdown: '{"x":1}', timeSeconds: 1, + }) expect(cells[3]).toMatchObject({ timeSeconds: 0.5 }) }) @@ -405,7 +420,9 @@ describe('run_code sub-dispatch cells', () => { } const turns = deriveTrajectoryLayout({ nodes: withSubCalls([running]), partial: null, runningCalls: [] }) const sub = turns[0]!.groups.flatMap(g => g.cells).find(c => c.kind === 'subtool') - expect(sub).toMatchObject({ text: 'grep · {"pattern":"x"}', timeSeconds: null }) + expect(sub).toMatchObject({ + text: 'grep', previewMarkdown: '{"pattern":"x"}', timeSeconds: null, + }) }) it('recursively flattens nested child calls immediately after their parent', () => { From 98a4cc6569fc66c8d56e94175594102963235447 Mon Sep 17 00:00:00 2001 From: imccyu <276526105+imccyu@users.noreply.github.com> Date: Tue, 11 Aug 2026 00:04:51 +0800 Subject: [PATCH 33/36] style(ui-trajectory): align presentation render tree --- .../src/client/TrajectoryTable.tsx | 432 +++++++++--------- .../client/ui-trajectory/src/client/layout.ts | 4 +- .../src/client/trajectory-search-index.ts | 14 +- 3 files changed, 225 insertions(+), 225 deletions(-) diff --git a/packages/client/ui-trajectory/src/client/TrajectoryTable.tsx b/packages/client/ui-trajectory/src/client/TrajectoryTable.tsx index 67ec1cd2d6..a1db84f50c 100644 --- a/packages/client/ui-trajectory/src/client/TrajectoryTable.tsx +++ b/packages/client/ui-trajectory/src/client/TrajectoryTable.tsx @@ -2214,241 +2214,241 @@ export function TrajectoryTable({ cell={record.cell} > {({ displayText, listDisplayText, resultText, toolCallOnly, toolCallText }) => { - const isCollapsedSummary = record.collapsedSummary !== undefined - const isRequestOnly = record.cell.requestOnly === true - const isInitialSystem = record.cell.kind === 'system' + const isCollapsedSummary = record.collapsedSummary !== undefined + const isRequestOnly = record.cell.requestOnly === true + const isInitialSystem = record.cell.kind === 'system' && record.cell.index === allRecords[0]?.cell.index - const request = record.groupStart + const request = record.groupStart && !isCollapsedSummary && (record.turn === null || !collapsedTurns.has(record.turn)) - ? requestNumbers.get(requestKey(record.turn, record.group)) - : undefined - const requestInfo = request === undefined - ? undefined - : sessionRequestNumbers?.find(candidate => candidate.number === request) - const requestStatus = requestInfo?.status + ? requestNumbers.get(requestKey(record.turn, record.group)) + : undefined + const requestInfo = request === undefined + ? undefined + : sessionRequestNumbers?.find(candidate => candidate.number === request) + const requestStatus = requestInfo?.status ?? (record.cell.isError === true ? 'error' : undefined) - const requestRunIndex = requestBoundaryRuns.get(record.cell.index) ?? 0 - const requestBoundaryStyle: RequestBoundaryStyle = { - '--request-boundary-offset': `${requestRunIndex * 8}px`, - } - const requestLabel = request === undefined - ? undefined - : `Request #${request}${requestInfo?.purpose === 'compaction' ? ' · Compaction' : ''}` - const requestSelected = request !== undefined + const requestRunIndex = requestBoundaryRuns.get(record.cell.index) ?? 0 + const requestBoundaryStyle: RequestBoundaryStyle = { + '--request-boundary-offset': `${requestRunIndex * 8}px`, + } + const requestLabel = request === undefined + ? undefined + : `Request #${request}${requestInfo?.purpose === 'compaction' ? ' · Compaction' : ''}` + const requestSelected = request !== undefined && selectedRequest?.turn === record.turn && selectedRequest.group === record.group - const sectionActive = record.turn === null - ? activeSection === record.section - : activeTurn === record.turn - return ( - { - if (record.collapsedSummaryKind === 'turn' && record.turn !== null) { + const sectionActive = record.turn === null + ? activeSection === record.section + : activeTurn === record.turn + return ( + { + if (record.collapsedSummaryKind === 'turn' && record.turn !== null) { + onToggleTurn(record.turn) + } else onToggleAssistant(trajectoryRecordId(record.cell)) + } + : () => { selectRecord(record.cell.index) }} + onDoubleClick={(event) => { + if (isCollapsedSummary || isRequestOnly) return + if (record.turn !== null && collapsedTurns.has(record.turn)) { + event.preventDefault() onToggleTurn(record.turn) - } else onToggleAssistant(trajectoryRecordId(record.cell)) - } - : () => { selectRecord(record.cell.index) }} - onDoubleClick={(event) => { - if (isCollapsedSummary || isRequestOnly) return - if (record.turn !== null && collapsedTurns.has(record.turn)) { - event.preventDefault() - onToggleTurn(record.turn) - return - } - if ( - record.cell.kind === 'message' + return + } + if ( + record.cell.kind === 'message' && assistantToolCalls(allRecords, record.cell.index).length > 0 - ) { - event.preventDefault() - onToggleAssistant(trajectoryRecordId(record.cell)) - return - } - if (!record.turnStart) return - if (record.turn === null) return - if (allRecords.filter(candidate => - candidate.turn === record.turn + ) { + event.preventDefault() + onToggleAssistant(trajectoryRecordId(record.cell)) + return + } + if (!record.turnStart) return + if (record.turn === null) return + if (allRecords.filter(candidate => + candidate.turn === record.turn && candidate.cell.requestOnly !== true && candidate.cell.kind !== 'system').length <= 1) return - event.preventDefault() - onToggleTurn(record.turn) - }} - onKeyDown={(event) => { - if (isRequestOnly) return - if (event.key !== 'Enter' && event.key !== ' ') return - event.preventDefault() - if (isCollapsedSummary) { - if (record.collapsedSummaryKind === 'turn' && record.turn !== null) { + event.preventDefault() onToggleTurn(record.turn) - } else onToggleAssistant(trajectoryRecordId(record.cell)) - return - } - selectRecord(record.cell.index) - }} - > - - {request !== undefined && ( -