From 97545d9c8fe38eb1b99cbcc949cfb1adf87035dd Mon Sep 17 00:00:00 2001 From: Huanqi Cao Date: Mon, 21 Sep 2026 15:57:08 +0800 Subject: [PATCH 01/29] fix(pty): keep the controlled prompt so persistent pwsh settles fast tool-pwsh-persistent installs its own `prompt` function after spawn, so terminal-bash prompt readiness never matched and every send degraded to the silence tier (idleSilenceMs + handoffGraceMs) under production defaults. This is the defect the persistent bash tool fixed for the bash stack. The tool now initializes without a prompt send and detects the no-end-marker fallback through the seam's stdin_read wait reason instead of matching its own prompt text. The private prompt constant and its stripping are deleted, so partial output can carry the backend's own trailing prompt. Tool calls drop from 8493/3722/3832/3759 ms to 1340/255/251/241 ms (spawn and initialization plus the first command, then three warm commands; Windows, production defaults, real Loader composition). The loader composition suite pushes idleSilenceMs beyond the send bound, so every case fails if prompt readiness regresses. --- ...ent-pwsh-keeps-controlled-prompt.i18n.yaml | 6 +++ ...persistent-pwsh-keeps-controlled-prompt.md | 37 +++++++++++++++ ...sistent-pwsh-keeps-controlled-prompt.zh.md | 37 +++++++++++++++ docs/config-catalog.i18n.yaml | 4 +- docs/config-catalog.md | 2 +- docs/config-catalog.zh.md | 2 +- .../tool-pwsh-persistent/README.i18n.yaml | 4 +- packages/shell/tool-pwsh-persistent/README.md | 12 ++--- .../shell/tool-pwsh-persistent/README.zh.md | 12 ++--- .../shell/tool-pwsh-persistent/src/index.ts | 45 +++++-------------- .../tests/loader-composition.spec.ts | 5 ++- .../tool-pwsh-persistent/tests/tools.spec.ts | 42 +++++------------ 12 files changed, 122 insertions(+), 86 deletions(-) create mode 100644 .agents/notes/implemented/bug-fix/2026-09-21-persistent-pwsh-keeps-controlled-prompt.i18n.yaml create mode 100644 .agents/notes/implemented/bug-fix/2026-09-21-persistent-pwsh-keeps-controlled-prompt.md create mode 100644 .agents/notes/implemented/bug-fix/2026-09-21-persistent-pwsh-keeps-controlled-prompt.zh.md diff --git a/.agents/notes/implemented/bug-fix/2026-09-21-persistent-pwsh-keeps-controlled-prompt.i18n.yaml b/.agents/notes/implemented/bug-fix/2026-09-21-persistent-pwsh-keeps-controlled-prompt.i18n.yaml new file mode 100644 index 0000000000..db9c9a3ad8 --- /dev/null +++ b/.agents/notes/implemented/bug-fix/2026-09-21-persistent-pwsh-keeps-controlled-prompt.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/bug-fix/2026-09-21-persistent-pwsh-keeps-controlled-prompt.md +2026-09-21-persistent-pwsh-keeps-controlled-prompt.md: 748d18f6daafaf036576a911d26647dafbe92261 +2026-09-21-persistent-pwsh-keeps-controlled-prompt.zh.md: 6425581a6dbb84dfc3b1c4cd4fb732353c4cd5e1 diff --git a/.agents/notes/implemented/bug-fix/2026-09-21-persistent-pwsh-keeps-controlled-prompt.md b/.agents/notes/implemented/bug-fix/2026-09-21-persistent-pwsh-keeps-controlled-prompt.md new file mode 100644 index 0000000000..748d18f6da --- /dev/null +++ b/.agents/notes/implemented/bug-fix/2026-09-21-persistent-pwsh-keeps-controlled-prompt.md @@ -0,0 +1,37 @@ +# Agent Note: Persistent pwsh keeps the backend's controlled prompt + +Status: implemented + +English | [中文](2026-09-21-persistent-pwsh-keeps-controlled-prompt.zh.md) + +## Problem + +`dsh-tool-pwsh-persistent` initialized its shell with a `prompt` function of its own (`'__DSH_PERSISTENT_PWSH_PROMPT__ '`), overwriting the `prompt` that `dsh-terminal-bash` installs in its pwsh startup sequence. The backend's prompt readiness requires the printable tail after the OSC `133;D` marker to exactly equal the controlled `dsh> ` prompt ([design](../feature/2026-07-16-persistent-pty-sessions.md)), so after initialization no send could settle through it and every send paid the silence tier plus handoff grace. Measured on Windows through the real Loader composition with production defaults: 8493 ms for the first call (spawn, initialization, and command) and 3722/3832/3759 ms for the next three, against 1340/255/251/241 ms with the controlled prompt intact. The package tests masked it by configuring `idleSilenceMs: 300`. + +The [persistent bash tool fixed the identical defect](../../archived/bug-fix/2026-08-15-persistent-bash-keeps-controlled-prompt.md) by giving up its own prompt override; the pwsh twin kept it. The override served the same two consumers there: a viewport-suffix fallback detecting "shell at a prompt without the end marker", and cosmetic stripping of prompt text from partial output. + +## Decision + +The tool no longer installs a prompt. `dsh-terminal-bash` owns the pwsh `prompt` function, installs it during `spawn`, and returns the session only after that startup reached `stdin_read` readiness, so the tool's initialization send had nothing left to establish and is deleted together with its `PWSH_PROMPT_SETUP` command. + +The viewport-suffix fallback is replaced with the seam's own signal: a send that settles as `stdin_read` without the end marker in scrollback returns the captured partial output. The private prompt constant and its stripping are deleted; partial output may now end with the backend's own prompt text, which the tool cannot and should not know. `stripPrompt` collapses to `trimTrailingNewline`, matching `dsh-tool-bash-persistent`. + +## Alternatives considered + +**Align the tool's prompt text with the backend's `dsh> `.** Rejected: it keeps a second installation of one protocol constant and a second owner of it, and the send is redundant because the backend had already installed the identical prompt before `spawn` resolved. + +**Import the controlled prompt into the tool.** Rejected: the prompt is one provider's protocol constant; a Consumer matching it would couple the tool to `dsh-terminal-bash` specifically, and any other mounted pwsh-dialect backend would break it again. + +**Lower `handoffGraceMs`/`idleSilenceMs` instead.** Rejected: no silence value fixes a dead fast path; it rebalances how much every call overpays, and the silence tier is also what absorbs a genuinely broken prompt. + +**Re-assert the pwsh prompt per prompt, as `PROMPT_COMMAND` does for bash.** Rejected: PowerShell has no per-prompt hook outside the `prompt` function itself, so a redefinition cannot be healed the way bash's variable is; the residue stays a documented limitation. + +## Consequences + +Windows, production defaults, real Loader composition: tool calls drop from 8493/3722/3832/3759 ms to 1340/255/251/241 ms (spawn + initialization + first command, then three warm commands). + +The `stdin_read` fallback is behavior, not only cosmetics: where a provider proves a foreground stdin wait, an interactive child now returns captured partial output instead of spinning to the command deadline, and elsewhere the call still runs to `timeoutMs`; the tool README records both. Complete marker-delimited output is unchanged. + +The loader-composition suite now sets `idleSilenceMs: 30000`, above the send bound, so silence can settle nothing and every case fails if prompt readiness regresses. The stub suite drops the initialization-handshake modes and pins the prompt text retained in partial output instead of its absence. + +A model command that redefines `prompt` still removes the readiness marker and degrades later sends to the silence tier: the backend installs its prompt once at startup and cannot re-assert it. diff --git a/.agents/notes/implemented/bug-fix/2026-09-21-persistent-pwsh-keeps-controlled-prompt.zh.md b/.agents/notes/implemented/bug-fix/2026-09-21-persistent-pwsh-keeps-controlled-prompt.zh.md new file mode 100644 index 0000000000..6425581a6d --- /dev/null +++ b/.agents/notes/implemented/bug-fix/2026-09-21-persistent-pwsh-keeps-controlled-prompt.zh.md @@ -0,0 +1,37 @@ +# Agent Note: 持久 pwsh 保留后端的受控提示符 + +Status: implemented + +[English](2026-09-21-persistent-pwsh-keeps-controlled-prompt.md) | 中文 + +## Problem + +`dsh-tool-pwsh-persistent` 用自己安装的 `prompt` 函数(`'__DSH_PERSISTENT_PWSH_PROMPT__ '`)初始化其 shell,覆盖了 `dsh-terminal-bash` 在 pwsh 启动序列中安装的 `prompt`。后端的提示符就绪检测要求 OSC `133;D` 标记之后的可打印尾部与受控提示符 `dsh> ` 完全相等([设计](../feature/2026-07-16-persistent-pty-sessions.zh.md)),因此初始化之后任何 send 都无法经由该路径结算,每次 send 都要支付静默层加交接宽限。在 Windows 上通过真实 Loader 组合以生产默认值实测:首次调用(spawn、初始化与命令)8493 毫秒,随后三次为 3722/3832/3759 毫秒;受控提示符完好时为 1340/255/251/241 毫秒。包测试把 `idleSilenceMs` 配成 300,掩盖了该问题。 + +[持久 bash 工具已修复同一缺陷](../../archived/bug-fix/2026-08-15-persistent-bash-keeps-controlled-prompt.md),方式是放弃自己的提示符覆盖;pwsh 孪生工具保留了它。该覆盖在两个工具中服务同样的两个消费点:用视口后缀检测「shell 已回到提示符但没有结束标记」的回退判定,以及从部分输出中剥离提示符文本的美化。 + +## Decision + +工具不再安装提示符。pwsh 的 `prompt` 函数由 `dsh-terminal-bash` 拥有,在 `spawn` 期间安装,且只在该启动流程达到 `stdin_read` 就绪后才返回会话,因此工具的初始化 send 已无可确立之事,与其 `PWSH_PROMPT_SETUP` 命令一并删除。 + +视口后缀回退替换为 seam 自己的信号:一次以 `stdin_read` 结算而 scrollback 中没有结束标记的 send,返回已捕获的部分输出。私有提示符常量及其剥离逻辑删除;部分输出现在可能以后端自己的提示符文本结尾,工具无法也不应知道该文本。`stripPrompt` 收敛为 `trimTrailingNewline`,与 `dsh-tool-bash-persistent` 一致。 + +## Alternatives considered + +**把工具的提示符文本对齐到后端的 `dsh> `。** 被拒绝:这保留了同一个协议常量的第二份安装与第二个拥有者,而且该 send 是多余的——后端在 `spawn` 返回前就已安装相同的提示符。 + +**把受控提示符导入工具。** 被拒绝:提示符是单个提供方的协议常量;Consumer 匹配它就把工具与 `dsh-terminal-bash` 具体耦合,换任何其他 pwsh 方言后端都会再次损坏。 + +**改为调小 `handoffGraceMs`/`idleSilenceMs`。** 被拒绝:任何静默值都修不好已死的快速路径,只是重新分配每次调用多付多少;而静默层同时也是吸收真正损坏提示符的那一层。 + +**像 bash 的 `PROMPT_COMMAND` 那样在每个提示符处重新设定 pwsh 提示符。** 被拒绝:除 `prompt` 函数本身之外,PowerShell 没有每提示符钩子,因此重定义无法像 bash 的变量那样被治好;该残余已记入已知限制。 + +## Consequences + +Windows、生产默认值、真实 Loader 组合:工具调用从 8493/3722/3832/3759 毫秒降至 1340/255/251/241 毫秒(spawn + 初始化 + 首条命令,随后三条热命令)。 + +`stdin_read` 回退是行为而不只是美化:在提供方能证明前台 stdin 等待之处,交互式子进程现在返回已捕获的部分输出,而不是空转到命令期限;其他情况下调用仍会运行到 `timeoutMs`,两者都记入工具 README。由标记界定的完整输出保持不变。 + +loader 组合套件现在把 `idleSilenceMs` 设为 30000,位于 send 上限之上,静默无法结算任何 send,提示符就绪一旦回归,每个用例都会失败。stub 套件删除了初始化握手模式,并改为锚定部分输出中保留的提示符文本,而不是它的缺席。 + +重定义 `prompt` 的模型命令仍会移除就绪标记,并把后续 send 降级到静默层:后端只在启动时安装一次提示符,无法重新设定。 diff --git a/docs/config-catalog.i18n.yaml b/docs/config-catalog.i18n.yaml index 63b1766591..cd86866daf 100644 --- a/docs/config-catalog.i18n.yaml +++ b/docs/config-catalog.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/config-catalog.md -config-catalog.md: 59b15e7bbb518abdee55308c191b109547b5185e -config-catalog.zh.md: 4e89ea92944f6e1f2ae8ae0b57f0bec9e9f835d9 +config-catalog.md: f120bf0ffdc64cf298de2e18ed10083ac96485a5 +config-catalog.zh.md: 6cb3e3a6dd92b5b4f877a5b588b4935a28f089f6 diff --git a/docs/config-catalog.md b/docs/config-catalog.md index 59b15e7bbb..f120bf0ffd 100644 --- a/docs/config-catalog.md +++ b/docs/config-catalog.md @@ -3282,7 +3282,7 @@ export interface Config { } ``` -Source: [`packages/shell/tool-pwsh-persistent/src/index.ts:480`](../packages/shell/tool-pwsh-persistent/src/index.ts) +Source: [`packages/shell/tool-pwsh-persistent/src/index.ts:455`](../packages/shell/tool-pwsh-persistent/src/index.ts) diff --git a/docs/config-catalog.zh.md b/docs/config-catalog.zh.md index 4e89ea9294..6cb3e3a6dd 100644 --- a/docs/config-catalog.zh.md +++ b/docs/config-catalog.zh.md @@ -3286,7 +3286,7 @@ export interface Config { } ``` -来源:[`packages/shell/tool-pwsh-persistent/src/index.ts:480`](../packages/shell/tool-pwsh-persistent/src/index.ts) +来源:[`packages/shell/tool-pwsh-persistent/src/index.ts:455`](../packages/shell/tool-pwsh-persistent/src/index.ts) diff --git a/packages/shell/tool-pwsh-persistent/README.i18n.yaml b/packages/shell/tool-pwsh-persistent/README.i18n.yaml index b31e3271a9..00dcbdee79 100644 --- a/packages/shell/tool-pwsh-persistent/README.i18n.yaml +++ b/packages/shell/tool-pwsh-persistent/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/shell/tool-pwsh-persistent/README.md -README.md: f90442e7e9d8a361a690f66f41a58f1a4fcdd708 -README.zh.md: d634e8e42e186318a8733ee9ef2024e2840a857c +README.md: d4c52d9209118830364b7d20e8ee4a26452ad604 +README.zh.md: eedf8e7135e9bd2c73b70e891658920b5d6c64e8 diff --git a/packages/shell/tool-pwsh-persistent/README.md b/packages/shell/tool-pwsh-persistent/README.md index f90442e7e9..d4c52d9209 100644 --- a/packages/shell/tool-pwsh-persistent/README.md +++ b/packages/shell/tool-pwsh-persistent/README.md @@ -54,7 +54,7 @@ The generated [configuration catalog](../../../docs/config-catalog.md#deepseek-a ### What the agent can rely on -Commands share one shell per agent, so cwd, `$env:` variables, functions, and background jobs persist across calls. Results exclude the private completion markers, the shell prompt, and the echoed input line. A non-zero wrapped command appends `[exit code: N]` — the exact native exit code when the command ran a native program, `1` for a terminating PowerShell error. A shell that exits before reporting that status instead appends `[shell exited: code N]`, `[shell killed by signal: SIG]`, or `[shell exited]` (Windows forced termination reports exit 1 without a signal), then resets and tells the agent the next call starts fresh. Long output keeps the earliest retained prefix plus a clipping notice; if the terminal has already dropped that prefix, the result says so explicitly. +Commands share one shell per agent, so cwd, `$env:` variables, functions, and background jobs persist across calls. Results exclude the private completion markers and the echoed input line. When the shell reads stdin again without having printed the completion marker — an interrupt, a replaced shell, or an interactive foreground child whose stdin wait the provider proves — the call returns the captured partial output, which can end with the backend's own prompt text. A non-zero wrapped command appends `[exit code: N]` — the exact native exit code when the command ran a native program, `1` for a terminating PowerShell error. A shell that exits before reporting that status instead appends `[shell exited: code N]`, `[shell killed by signal: SIG]`, or `[shell exited]` (Windows forced termination reports exit 1 without a signal), then resets and tells the agent the next call starts fresh. Long output keeps the earliest retained prefix plus a clipping notice; if the terminal has already dropped that prefix, the result says so explicitly. ### What can go wrong @@ -73,7 +73,7 @@ This section explains the design decisions behind the tool and points at the cod ### Design philosophy - **A deliberate twin of `dsh-tool-bash-persistent`.** The session registry, polling loop, and reset contract mirror the persistent bash tool by design ([pwsh persistent PTY Agent Note](../../../.agents/notes/archived/architecture/2026-08-11-pwsh-persistent-pty.md)). -- **Prompt-function readiness.** The tool installs its own `prompt` function that prints a BEL-terminated OSC marker plus a printable prompt; the OSC marker carries the last exit code and the printable prompt settles every command, so a model redefinition of `prompt` degrades readiness to the silence tier. +- **Backend-owned prompt readiness.** The shell's `prompt` function belongs to the backend: it prints a BEL-terminated OSC marker plus the controlled printable prompt, and that exact prompt text settles every command through the backend's fast path. The tool neither installs nor matches a prompt of its own, so only a model redefinition of `prompt` degrades readiness to the silence tier. - **PSReadLine echo stripped by anchoring.** PowerShell renders submitted input back into the stream; the marker-anchored extraction and a wrapper-source strip remove the echo, and a wrapper that wraps across the terminal width may leave a partial echo in partial-output results. - **Reset, never repair.** Any uncertain state — an explicit `exit`, a timeout, a send failure, an abort — closes the shell and starts the next call fresh. @@ -81,12 +81,12 @@ This section explains the design decisions behind the tool and points at the cod | File | Role | |---|---| -| [`src/index.ts`](src/index.ts) | Plugin entry: shell registry, prompt setup, command wrapping, scrollback polling, extraction and rendering | +| [`src/index.ts`](src/index.ts) | Plugin entry: shell registry, command wrapping, scrollback polling, extraction and rendering | | — | No runtime invariant companion is published; the adapter's private owner-to-shell cache has no observable event or data relation. Lifecycle tests prove its cleanup without adding a public API solely for an invariant. | ### Command flow -A first command spawns the shell through `ctx.terminals.spawn`, installs the `prompt` override, and waits for readiness. Each command is wrapped into one physical line — `Write-Output` of the start marker, the body escaped with backtick escapes into a double-quoted string, and `Write-Output` of the end marker plus the exit status — so PSReadLine's echo of a wrapped line cannot fabricate completion. The tool polls the scrollback in 1,000-line pages until the end marker or a completed prompt appears, extracts the span, strips the echoed wrapper and prompts, and renders it with any status marker. A timeout aborts the deadline, captures the partial output, and resets the shell. +A first command spawns the shell through `ctx.terminals.spawn`, whose pwsh startup installs the controlled `prompt` function and returns only once the shell reached readiness. Each command is wrapped into one physical line — `Write-Output` of the start marker, the body escaped with backtick escapes into a double-quoted string, and `Write-Output` of the end marker plus the exit status — so PSReadLine's echo of a wrapped line cannot fabricate completion. The tool polls the scrollback in 1,000-line pages until the end marker appears or the send settles as `stdin_read`, extracts the span, strips the echoed wrapper, and renders it with any status marker. A timeout aborts the deadline, captures the partial output, and resets the shell. @@ -128,7 +128,7 @@ Prefix-stable while the configured description and schema remain unchanged. #### What the model sees -Commands share one shell per Agent, so cwd, `$env:` variables, functions, and background jobs persist across calls. Results exclude private completion markers, the shell prompt, and the echoed input line (PSReadLine renders submitted input back into the stream; the marker-anchored extraction and the wrapper-source strip remove it). A nonzero wrapped command appends `[exit code: N]` — the exact native exit code when the command ran a native program, `1` for a terminating PowerShell error. A shell that exits before reporting that status instead appends `[shell exited: code N]`, `[shell killed by signal: SIG]`, or `[shell exited]` when the backend supplies neither (Windows forced termination reports exit 1 without a signal), then resets and tells the model that the next call starts fresh. Long output keeps the earliest retained prefix plus a clipping notice; if the terminal has already dropped that prefix, the result says so explicitly. Timeout returns bounded partial output, closes the uncertain shell, and reports the reset. +Commands share one shell per Agent, so cwd, `$env:` variables, functions, and background jobs persist across calls. Results exclude private completion markers and the echoed input line (PSReadLine renders submitted input back into the stream; the marker-anchored extraction and the wrapper-source strip remove it). When the shell reads stdin again without having printed the completion marker — an interrupt, a replaced shell, or an interactive foreground child whose stdin wait the provider proves — the call returns the captured partial output, which can end with the backend's own prompt text. A nonzero wrapped command appends `[exit code: N]` — the exact native exit code when the command ran a native program, `1` for a terminating PowerShell error. A shell that exits before reporting that status instead appends `[shell exited: code N]`, `[shell killed by signal: SIG]`, or `[shell exited]` when the backend supplies neither (Windows forced termination reports exit 1 without a signal), then resets and tells the model that the next call starts fresh. Long output keeps the earliest retained prefix plus a clipping notice; if the terminal has already dropped that prefix, the result says so explicitly. Timeout returns bounded partial output, closes the uncertain shell, and reports the reset. #### Token effect @@ -149,7 +149,7 @@ These limits define when the tool is a poor fit or needs special care. They are - **Input echo is unavoidable** — PowerShell's PSReadLine renders submitted input back into the terminal stream, and there is no `stty -echo` equivalent. The marker-anchored extraction excludes the echo in complete results; the wrapper-source strip covers fallback paths, but a wrapper that wraps across the terminal width may leave a partial echo in partial-output results, bounded by `maxOutputChars`. - **Raw ESC characters inside model commands are unsupported** — PSReadLine consumes them before execution. The wrapper escapes the control bytes it needs (`[char]27`-built OSC markers, backtick escapes for the body). - **A model redefinition of the `prompt` function removes the readiness marker** — the shell then settles on the silence tier instead of the marker fast path. -- **There is no interactive stdin during a command** — a foreground command that reads input blocks until the command timeout, which resets the shell. +- **There is no interactive stdin during a command** — a foreground child that reads input returns early with partial output only where the provider proves its stdin wait; elsewhere the call runs to `timeoutMs`, which resets the shell. - **SIGTSTP/SIGHUP are unavailable on Windows** (backend-rejected); SIGINT is delivered as a console-wide Ctrl-C input write, which at a prompt cancels the pending line instead of signalling a process. - **Under the Windows ACL sandbox's read-only mode, pwsh starts in ConstrainedLanguage**, which may deny the bootstrap's `[Console]::` encoding pin and prompt marker. Commands can still settle through the printable prompt and silence tier, but non-ASCII output may follow the host code page. - **The BEL-terminated OSC marker remains a readiness signal only** — a BEL event channel to the model stays deferred, aligned with the current implementation. diff --git a/packages/shell/tool-pwsh-persistent/README.zh.md b/packages/shell/tool-pwsh-persistent/README.zh.md index d634e8e42e..eedf8e7135 100644 --- a/packages/shell/tool-pwsh-persistent/README.zh.md +++ b/packages/shell/tool-pwsh-persistent/README.zh.md @@ -54,7 +54,7 @@ kind: "package-reference" ### agent 可以依赖什么 -命令共享每个 agent 一个 shell,因此 cwd、`$env:` 变量、函数与后台任务都会跨调用保留。结果排除私有完成标记、shell 提示符与回显的输入行。非零的包装命令追加 `[exit code: N]`——命令运行原生程序时给出确切原生退出码,PowerShell 终止错误则为 `1`。在报告该状态前就退出的 shell 改为追加 `[shell exited: code N]`、`[shell killed by signal: SIG]` 或 `[shell exited]`(Windows 强制终止报告 exit 1 且没有信号),然后重置并告诉 agent 下一次调用从全新状态开始。长输出保留最早的已保留前缀并附裁剪通知;若 terminal 已经丢弃该前缀,结果会明确说明。 +命令共享每个 agent 一个 shell,因此 cwd、`$env:` 变量、函数与后台任务都会跨调用保留。结果排除私有完成标记与回显的输入行。当 shell 再次读取 stdin 却没有打印完成标记时——一次中断、一个被替换的 shell,或提供方能证明其 stdin 等待的交互式前台子进程——调用返回已捕获的部分输出,其结尾可能是后端自己的提示符文本。非零的包装命令追加 `[exit code: N]`——命令运行原生程序时给出确切原生退出码,PowerShell 终止错误则为 `1`。在报告该状态前就退出的 shell 改为追加 `[shell exited: code N]`、`[shell killed by signal: SIG]` 或 `[shell exited]`(Windows 强制终止报告 exit 1 且没有信号),然后重置并告诉 agent 下一次调用从全新状态开始。长输出保留最早的已保留前缀并附裁剪通知;若 terminal 已经丢弃该前缀,结果会明确说明。 ### 可能出什么问题 @@ -73,7 +73,7 @@ kind: "package-reference" ### 设计理念 - **`dsh-tool-bash-persistent` 的刻意孪生。** 会话注册表、轮询循环与重置约定按设计镜像持久 bash 工具([pwsh 持久 PTY Agent Note](../../../.agents/notes/archived/architecture/2026-08-11-pwsh-persistent-pty.md))。 -- **prompt 函数就绪。** 工具安装自己的 `prompt` 函数,打印 BEL 结尾的 OSC 标记加可打印提示符;OSC 标记携带最后的退出码,可打印提示符让每条命令都能结算,因此模型重定义 `prompt` 会把就绪降级到静默层级。 +- **后端拥有提示符就绪。** shell 的 `prompt` 函数属于后端:它打印 BEL 结尾的 OSC 标记加受控的可打印提示符,该确切提示符文本让每条命令都经由后端快路径结算。工具既不安装也不匹配自己的提示符,因此只有模型重定义 `prompt` 才会把就绪降级到静默层级。 - **PSReadLine 回显靠锚定剥离。** PowerShell 会把提交的输入渲染回流中;标记锚定提取与包装源码剥离移除回显,而跨终端宽度换行的包装可能在部分输出结果中留下部分回显。 - **重置,而非修复。** 任何不确定状态——显式 `exit`、超时、发送失败、中止——都会关闭 shell 并让下一次调用从全新状态开始。 @@ -81,12 +81,12 @@ kind: "package-reference" | 文件 | 职责 | |---|---| -| [`src/index.ts`](src/index.ts) | 插件入口:shell 注册表、prompt 设置、命令包装、scrollback 轮询、提取与渲染 | +| [`src/index.ts`](src/index.ts) | 插件入口:shell 注册表、命令包装、scrollback 轮询、提取与渲染 | | — | 不发布运行时不变式伴生入口;适配器私有的 owner-to-shell 缓存不存在可观察的事件或数据关系。生命周期测试无需仅为不变式增加公共 API 即可验证其清理。 | ### 命令流程 -首条命令通过 `ctx.terminals.spawn` 生成 shell,安装 `prompt` 覆盖,并等待就绪。随后每条命令都包装成一行物理文本——`Write-Output` 起始标记、用反引号转义进双引号字符串的命令体、`Write-Output` 结束标记加退出状态——因此 PSReadLine 对换行包装的回显无法伪造完成。工具以 1,000 行一页轮询 scrollback,直到出现结束标记或完成的提示符,提取区间、剥离回显的包装与提示符,并连同任何状态标记一起渲染。超时会中止截止时间、捕获部分输出并重置 shell。 +首条命令通过 `ctx.terminals.spawn` 生成 shell,其 pwsh 启动流程安装受控的 `prompt` 函数,并只在该 shell 达到就绪后返回。随后每条命令都包装成一行物理文本——`Write-Output` 起始标记、用反引号转义进双引号字符串的命令体、`Write-Output` 结束标记加退出状态——因此 PSReadLine 对换行包装的回显无法伪造完成。工具以 1,000 行一页轮询 scrollback,直到出现结束标记或该 send 以 `stdin_read` 结算,提取区间、剥离回显的包装,并连同任何状态标记一起渲染。超时会中止截止时间、捕获部分输出并重置 shell。 @@ -128,7 +128,7 @@ kind: "package-reference" #### 模型看到什么 -命令共享每个 agent 一个 shell,因此 cwd、`$env:` 变量、函数与后台任务都会跨调用保留。结果排除私有完成标记、shell 提示词与回显的输入行(PSReadLine 会把提交的输入渲染回流中;标记锚定提取与包装源码剥离会移除它)。非零的包装命令追加 `[exit code: N]`——命令运行原生程序时给出确切原生退出码,PowerShell 终止错误则为 `1`。在报告该状态前就退出的 shell 改为追加 `[shell exited: code N]`、`[shell killed by signal: SIG]`,或后端两者都未提供时的 `[shell exited]`(Windows 强制终止报告 exit 1 且没有信号),然后重置并告诉模型下一次调用从全新状态开始。长输出保留最早的已保留前缀并附裁剪通知;若 terminal 已经丢弃该前缀,结果会明确说明。超时返回有界部分输出、关闭不确定的 shell 并报告重置。 +命令共享每个 agent 一个 shell,因此 cwd、`$env:` 变量、函数与后台任务都会跨调用保留。结果排除私有完成标记与回显的输入行(PSReadLine 会把提交的输入渲染回流中;标记锚定提取与包装源码剥离会移除它)。当 shell 再次读取 stdin 却没有打印完成标记时——一次中断、一个被替换的 shell,或提供方能证明其 stdin 等待的交互式前台子进程——调用返回已捕获的部分输出,其结尾可能是后端自己的提示符文本。非零的包装命令追加 `[exit code: N]`——命令运行原生程序时给出确切原生退出码,PowerShell 终止错误则为 `1`。在报告该状态前就退出的 shell 改为追加 `[shell exited: code N]`、`[shell killed by signal: SIG]`,或后端两者都未提供时的 `[shell exited]`(Windows 强制终止报告 exit 1 且没有信号),然后重置并告诉模型下一次调用从全新状态开始。长输出保留最早的已保留前缀并附裁剪通知;若 terminal 已经丢弃该前缀,结果会明确说明。超时返回有界部分输出、关闭不确定的 shell 并报告重置。 #### Token 影响 @@ -149,7 +149,7 @@ kind: "package-reference" - **输入回显不可避免**——PowerShell 的 PSReadLine 会把提交的输入渲染回终端流,而且没有 `stty -echo` 等价物。标记锚定提取在完整结果中排除回显;包装源码剥离覆盖回退路径,但跨终端宽度换行的包装可能在部分输出结果中留下部分回显,受 `maxOutputChars` 设界。 - **模型命令内的原始 ESC 字符不受支持**——PSReadLine 会在执行前消费它们。包装器会转义它需要的控制字节(`[char]27` 构造的 OSC 标记、正文的反引号转义)。 - **模型重定义 `prompt` 函数会移除就绪标记**——shell 随后在静默层级而非标记快路径上结算。 -- **命令期间没有交互 stdin**——读取输入的前台命令会一直阻塞到命令超时,随后重置 shell。 +- **命令期间没有交互 stdin**——读取输入的前台子进程仅在提供方能证明其 stdin 等待时提前返回部分输出;否则调用会运行到 `timeoutMs`,随后重置 shell。 - **Windows 上 SIGTSTP/SIGHUP 不可用**(后端拒绝);SIGINT 以控制台级 Ctrl-C 输入写入投递,在提示词处会取消待处理行而不是向进程发信号。 - **在 Windows ACL 沙箱的只读模式下,pwsh 以 ConstrainedLanguage 启动**,可能拒绝引导的 `[Console]::` 编码固定与 prompt 标记。命令仍可通过可打印提示词与静默层级结算,但非 ASCII 输出可能跟随宿主代码页。 - **BEL 结尾的 OSC 标记目前只是就绪信号**——通向模型的 BEL 事件通道仍被推迟,与当前实现保持一致。 diff --git a/packages/shell/tool-pwsh-persistent/src/index.ts b/packages/shell/tool-pwsh-persistent/src/index.ts index 34f8cf7732..84b7e622ec 100644 --- a/packages/shell/tool-pwsh-persistent/src/index.ts +++ b/packages/shell/tool-pwsh-persistent/src/index.ts @@ -9,7 +9,7 @@ import { randomUUID } from 'node:crypto' import type { Context } from '@deepseek-ai/cordis' import z from '@deepseek-ai/schemastery' import type { Agent } from '@deepseek-ai/dsh-agent' -import type { TerminalReadResult, TerminalSendResult, TerminalSessionId } from '@deepseek-ai/dsh-terminal' +import type { TerminalReadResult, TerminalSessionId } from '@deepseek-ai/dsh-terminal' import { deadline, timeoutOf } from '@deepseek-ai/dsh-timeout' import { defineTool } from '@deepseek-ai/dsh-tools' @@ -17,7 +17,6 @@ import { defineTool } from '@deepseek-ai/dsh-tools' const TRUNCATED_MESSAGE = 'To save on context only part of this file has been shown to you. You should retry this tool after you have searched inside the file with Select-String in order to find the line numbers of what you are looking for.' const LOST_PREFIX_MESSAGE = 'The beginning of this command output was dropped by the terminal scrollback limit. The following text is the earliest retained output.\n' const SHELL_RESET_MESSAGE = 'The persistent pwsh shell was reset; the next pwsh call starts from the workspace with a fresh current directory and environment.' -const SHELL_PROMPT = '__DSH_PERSISTENT_PWSH_PROMPT__ ' const TIMEOUT_CODE = 'PERSISTENT_PWSH_TIMEOUT' // One page is enough to find a just-emitted completion marker; the full // scrollback is assembled only when a command settles or needs partial output. @@ -98,12 +97,8 @@ function wrapCommand(command: string, marker: CommandMarkers): string { return `Write-Output '${marker.start}'; $LASTEXITCODE = $null; $__s = 1; try { Invoke-Expression "${body}"; $__ok = $? } catch { $__ok = $false }; if ($null -ne $LASTEXITCODE) { $__s = [int]$LASTEXITCODE } else { $__s = if ($__ok) { 0 } else { 1 } }; Write-Output ('${marker.end}' + $__s)` } -function stripPrompt(text: string): string { - let result = text.replace(/\r?\n$/, '') - while (result.endsWith(SHELL_PROMPT)) { - result = result.slice(0, -SHELL_PROMPT.length) - } - return result.endsWith('\n') ? result.slice(0, -1) : result +function trimTrailingNewline(text: string): string { + return text.replace(/\r?\n$/, '') } function commandOutput( @@ -130,12 +125,6 @@ function commandOutput( } } -function promptCompleted(result: TerminalSendResult): boolean { - return result.viewport.endsWith(SHELL_PROMPT) - || result.viewport.endsWith(`${SHELL_PROMPT}\r\n`) - || result.viewport.endsWith(`${SHELL_PROMPT}\n`) -} - function partialOutput( snapshot: RetainedOutput, marker: CommandMarkers, @@ -146,7 +135,7 @@ function partialOutput( const startMarker = snapshot.text.lastIndexOf(marker.start) if (startMarker >= 0) { return { - text: stripPrompt(snapshot.text.slice(startMarker + marker.start.length).replace(/^\r?\n/, '')), + text: trimTrailingNewline(snapshot.text.slice(startMarker + marker.start.length).replace(/^\r?\n/, '')), incomplete: false, } } @@ -157,7 +146,7 @@ function partialOutput( const fallbackEnd = afterStart.lastIndexOf(marker.end) const beforeEnd = fallbackEnd < 0 ? afterStart : afterStart.slice(0, fallbackEnd) return { - text: stripPrompt(beforeEnd.replaceAll(SHELL_PROMPT, '').replaceAll(wrapper, '')), + text: trimTrailingNewline(beforeEnd.replaceAll(wrapper, '')), incomplete: fallbackTruncated || fallbackStart < 0, } } @@ -252,15 +241,6 @@ async function respondToSessionExit( ].filter(part => part.length > 0).join('\n') } -/** - * The pwsh prompt function that overrides the backend bootstrap value with - * this tool's own prompt. `[char]27`/`[char]7` build the OSC bytes at runtime - * because raw ESC characters in submitted input are unreliable under - * PSReadLine. - */ -const PWSH_PROMPT_SETUP = - "function prompt { [Console]::Write([char]27 + ']133;D;' + [int]$LASTEXITCODE + [char]7); '" + SHELL_PROMPT + "' }" - function persistentShells(ctx: Context, config: ResolvedConfig): PersistentShells { const pending = new WeakMap>() const live = new Map() @@ -307,15 +287,6 @@ function persistentShells(ctx: Context, config: ResolvedConfig): PersistentShell live.delete(owner) }, 'tool-pwsh-persistent owner cache cleanup') } - const setup = ctx.terminals.startSend(owner, spawned.sessionId, { - text: PWSH_PROMPT_SETUP, - submit: true, - signal: combinedSignal, - }) - const result = await setup.done - if (result.sessionStatus.kind === 'exited' || result.waitReason === 'timeout') { - throw new Error('persistent pwsh shell did not accept initialization') - } return spawned.sessionId } catch (error: unknown) { await reset(owner, 'persistent pwsh initialization failed') @@ -414,7 +385,11 @@ async function executeCommand( ctx, shells, owner, id, result.sessionStatus, marker, wrapped, fallback, fallbackTruncated, config, ) } - if (promptCompleted(result)) { + // The shell reads stdin again (its prompt, or a foreground child's own + // read) without having printed the end marker — an interrupt, a replaced + // shell, or an interactive child. Return what was captured instead of + // spinning until the command deadline. + if (result.waitReason === 'stdin_read') { const snapshot = retainedScrollback(ctx, owner, id, latest) return renderCaptured( partialOutput(snapshot, marker, wrapped, fallback, fallbackTruncated), diff --git a/packages/shell/tool-pwsh-persistent/tests/loader-composition.spec.ts b/packages/shell/tool-pwsh-persistent/tests/loader-composition.spec.ts index eacd51d586..96fe69116c 100644 --- a/packages/shell/tool-pwsh-persistent/tests/loader-composition.spec.ts +++ b/packages/shell/tool-pwsh-persistent/tests/loader-composition.spec.ts @@ -95,7 +95,10 @@ describe.skipIf(!hasPwsh)('persistent pwsh through a real cordis.yml Loader comp ' shellDialect: pwsh', ' pollIntervalMs: 10', ' exactProbeAfterMs: 20', - ' idleSilenceMs: 300', + // The silence tier is pushed beyond the send bound, so no send below can + // settle as inferred_idle: every case proves the controlled-prompt fast + // path that the production defaults (3.5s silence) would otherwise mask. + ' idleSilenceMs: 30000', ' handoffGraceMs: 300', ' scrollbackLines: 20000', // The first call pays the full pwsh cold-start latency (spawn + .NET + diff --git a/packages/shell/tool-pwsh-persistent/tests/tools.spec.ts b/packages/shell/tool-pwsh-persistent/tests/tools.spec.ts index c260f818eb..bf2ff8454b 100644 --- a/packages/shell/tool-pwsh-persistent/tests/tools.spec.ts +++ b/packages/shell/tool-pwsh-persistent/tests/tools.spec.ts @@ -93,8 +93,6 @@ type StubMode = | 'torn-status' | 'finish-torn-status' | 'end-only' - | 'init-exit' - | 'init-timeout' | 'spawn-error' | 'send-error' | 'prompt-after-idle' @@ -109,7 +107,7 @@ const START_PATTERN = /__DSH_PERSISTENT_PWSH_START_[^_]+(?:-[^_]+)*__/ const END_PATTERN = /__DSH_PERSISTENT_PWSH_END_[^:]+:/ class StubTerminalSession implements TerminalBackendSession { - readonly motd = '__DSH_PERSISTENT_PWSH_PROMPT__ ' + readonly motd = 'stub> ' readonly pid = 123 statusValue: TerminalSessionStatus = { kind: 'running' } scrollback = this.motd @@ -126,16 +124,6 @@ class StubTerminalSession implements TerminalBackendSession { startSend(request: TerminalSendRequest): TerminalSendOperation { this.sends += 1 - if (request.text.startsWith('function prompt')) { - if (this.mode === 'init-exit') { - this.statusValue = { kind: 'exited', exitCode: 1, signal: null } - return this.operation(Promise.resolve(this.result('', 'session_exit'))) - } - if (this.mode === 'init-timeout') { - return this.operation(Promise.resolve(this.result('', 'timeout'))) - } - return this.operation(Promise.resolve(this.result(this.motd, 'stdin_read'))) - } if (this.mode === 'send-error') throw new Error('stub send failed') if (this.throwOnSend) throw new Error('PTY session has exited') if (this.mode === 'wait-for-abort' || this.mode === 'end-on-abort') { @@ -346,7 +334,7 @@ describe('tool-pwsh-persistent', () => { expect(text(await call(ctx, owner, 'Write-Output one'))).toBe('hello from stub') expect(text(await call(ctx, owner, 'Write-Output two'))).toBe('hello from stub') expect(stub.sessions).toHaveLength(1) - expect(stub.sessions[0]?.sends).toBe(3) + expect(stub.sessions[0]?.sends).toBe(2) const ownerWithoutCwd = await agent(ctx, undefined) expect(text(await call(ctx, ownerWithoutCwd, 'pwd'))).toBe('hello from stub') @@ -392,7 +380,7 @@ describe('tool-pwsh-persistent', () => { expect(stub.sessions).toHaveLength(2) }) - it('handles inferred idle, prompt fallback, shell exit, clipping, and cleanup', async () => { + it('handles inferred idle, stdin_read fallback, shell exit, clipping, and cleanup', async () => { const { ctx, owner, stub, fiber } = await setup({ backendType: 'stub', maxOutputChars: 10, @@ -405,18 +393,16 @@ describe('tool-pwsh-persistent', () => { session.mode = 'incremental-fallback' session.scrollback = '' - expect(text(await call(ctx, owner, 'incremental fallback'))).toBe('increment') + expect(text(await call(ctx, owner, 'incremental fallback'))).toContain('increment') session.mode = 'prompt-only' const promptFallback = text(await call(ctx, owner, 'bad {')) expect(promptFallback).toContain('pwsh: synt') - expect(promptFallback).not.toContain('DSH_PERSISTENT_PWSH_PROMPT') session.mode = 'prompt-crlf' session.scrollback = '' const crlfPromptFallback = text(await call(ctx, owner, 'bad {')) expect(crlfPromptFallback).toContain('pwsh: synt') - expect(crlfPromptFallback).not.toContain('DSH_PERSISTENT_PWSH_PROMPT') session.mode = 'end-only' session.scrollback = '' @@ -502,7 +488,7 @@ describe('tool-pwsh-persistent', () => { expect(text(await call(ctx, owner, 'paged output'))).toBe('hello from stub') }) - it('sanitizes a prompt fallback reached after multiple polling rounds', async () => { + it('returns a stdin_read fallback reached after multiple polling rounds', async () => { const { ctx, owner, stub } = await setup({ backendType: 'stub', maxOutputChars: 1_000 }) await call(ctx, owner, 'warm up') const session = stub.sessions[0]! @@ -511,7 +497,8 @@ describe('tool-pwsh-persistent', () => { const result = text(await call(ctx, owner, 'bad {')) expect(result).toContain('partial syntax output') expect(result).toContain('pwsh: syntax error') - expect(result).not.toContain('DSH_PERSISTENT_PWSH_PROMPT') + // The backend owns the prompt text, so the fallback retains it verbatim. + expect(result.endsWith('stub> ')).toBe(true) expect(result).not.toContain('DSH_PERSISTENT_PWSH_START') }) @@ -546,7 +533,7 @@ describe('tool-pwsh-persistent', () => { const cancelled = call(ctx, owner, 'hang', controller.signal) const queued = call(ctx, owner, 'after cancellation') try { - await expect.poll(() => stub.sessions[0]!.sends).toBe(3) + await expect.poll(() => stub.sessions[0]!.sends).toBe(2) controller.abort({ kind: 'user' }) const result = await cancelled @@ -577,14 +564,14 @@ describe('tool-pwsh-persistent', () => { const running = call(ctx, owner, 'hang', runningController.signal) const queued = call(ctx, owner, 'never sent', queuedController.signal) try { - await expect.poll(() => session.sends).toBe(3) + await expect.poll(() => session.sends).toBe(2) await expect.poll(() => execute.mock.calls.length).toBe(2) queuedController.abort({ kind: 'user' }) runningController.abort({ kind: 'user' }) const result = await queued expect(text(result)).toBe('Error: tool call aborted') expect(result.error?.info).toEqual({ name: 'AbortError', code: 'ABORTED' }) - expect(session.sends).toBe(3) + expect(session.sends).toBe(2) expect(stub.sessions).toHaveLength(1) expect(session.closed).toContain('persistent pwsh command aborted') } finally { @@ -702,15 +689,6 @@ describe('tool-pwsh-persistent', () => { expect(stub.sessions).toEqual([]) }) - it.each(['init-exit', 'init-timeout'] as const)( - 'fails initialization and closes the unusable shell for %s', - async (mode) => { - const { ctx, owner, stub } = await setup({ backendType: 'stub' }, mode) - expect((await call(ctx, owner, 'pwd')).isError).toBe(true) - expect(stub.sessions[0]?.closed).toContain('persistent pwsh initialization failed') - }, - ) - it('clears a failed spawn without trying to close an unpublished shell', async () => { const { ctx, owner, stub } = await setup({ backendType: 'stub' }, 'spawn-error') expect((await call(ctx, owner, 'pwd')).isError).toBe(true) From 74f4c438de902567e8f28d82e58a654a627bc426 Mon Sep 17 00:00:00 2001 From: Huanqi Cao Date: Mon, 21 Sep 2026 16:53:15 +0800 Subject: [PATCH 02/29] test(pty): pin the pwsh fast path by settle reason The composition suite's idleSilenceMs: 30000 was below the suite's own send bound (dsh-terminal-bash timeoutMs: 300000), so the comment claiming silence could settle nothing was wrong: a regressed send still settled as inferred_idle after ~30 s and only the accumulated case timeout caught it. The case now records every send's waitReason and requires at least six stdin_read settlements with no inferred_idle. Reinstating the removed prompt override fails it in 30 s with 'expected 0 to be greater than or equal to 6' while the output assertions still pass. The silence tier returns to its product default. Also renames the two stale test titles ('private shell prompt', and the cancellation phase that no longer covers an initialization send), pins the stdin_read fallback's session retention, and records the interactive-child consequence of that retention in the package README pair and the Agent Note. --- ...ent-pwsh-keeps-controlled-prompt.i18n.yaml | 4 +-- ...persistent-pwsh-keeps-controlled-prompt.md | 4 +-- ...sistent-pwsh-keeps-controlled-prompt.zh.md | 4 +-- .../tool-pwsh-persistent/README.i18n.yaml | 4 +-- packages/shell/tool-pwsh-persistent/README.md | 2 +- .../shell/tool-pwsh-persistent/README.zh.md | 2 +- .../tests/loader-composition.spec.ts | 31 ++++++++++++++++--- .../tool-pwsh-persistent/tests/tools.spec.ts | 14 ++++++--- 8 files changed, 46 insertions(+), 19 deletions(-) diff --git a/.agents/notes/implemented/bug-fix/2026-09-21-persistent-pwsh-keeps-controlled-prompt.i18n.yaml b/.agents/notes/implemented/bug-fix/2026-09-21-persistent-pwsh-keeps-controlled-prompt.i18n.yaml index db9c9a3ad8..4f16b7775b 100644 --- a/.agents/notes/implemented/bug-fix/2026-09-21-persistent-pwsh-keeps-controlled-prompt.i18n.yaml +++ b/.agents/notes/implemented/bug-fix/2026-09-21-persistent-pwsh-keeps-controlled-prompt.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/bug-fix/2026-09-21-persistent-pwsh-keeps-controlled-prompt.md -2026-09-21-persistent-pwsh-keeps-controlled-prompt.md: 748d18f6daafaf036576a911d26647dafbe92261 -2026-09-21-persistent-pwsh-keeps-controlled-prompt.zh.md: 6425581a6dbb84dfc3b1c4cd4fb732353c4cd5e1 +2026-09-21-persistent-pwsh-keeps-controlled-prompt.md: 3fd42b77d4536215f34c32643526dbb03d21674f +2026-09-21-persistent-pwsh-keeps-controlled-prompt.zh.md: 88d4e2deef26af4ad92ef4a69d8ae17403027f70 diff --git a/.agents/notes/implemented/bug-fix/2026-09-21-persistent-pwsh-keeps-controlled-prompt.md b/.agents/notes/implemented/bug-fix/2026-09-21-persistent-pwsh-keeps-controlled-prompt.md index 748d18f6da..3fd42b77d4 100644 --- a/.agents/notes/implemented/bug-fix/2026-09-21-persistent-pwsh-keeps-controlled-prompt.md +++ b/.agents/notes/implemented/bug-fix/2026-09-21-persistent-pwsh-keeps-controlled-prompt.md @@ -30,8 +30,8 @@ The viewport-suffix fallback is replaced with the seam's own signal: a send that Windows, production defaults, real Loader composition: tool calls drop from 8493/3722/3832/3759 ms to 1340/255/251/241 ms (spawn + initialization + first command, then three warm commands). -The `stdin_read` fallback is behavior, not only cosmetics: where a provider proves a foreground stdin wait, an interactive child now returns captured partial output instead of spinning to the command deadline, and elsewhere the call still runs to `timeoutMs`; the tool README records both. Complete marker-delimited output is unchanged. +The `stdin_read` fallback is behavior, not only cosmetics: where a provider proves a foreground stdin wait, an interactive child returns captured partial output instead of spinning to the command deadline, and elsewhere the call still runs to `timeoutMs`. That early return keeps the session, so a child still reading stdin can consume the next call's command until that call reaches `timeoutMs` and resets the shell; `dsh-tool-bash-persistent` behaves the same way, and distinguishing the shell's own prompt readiness from a child's stdin wait belongs to the seam rather than to either tool. Complete marker-delimited output is unchanged. -The loader-composition suite now sets `idleSilenceMs: 30000`, above the send bound, so silence can settle nothing and every case fails if prompt readiness regresses. The stub suite drops the initialization-handshake modes and pins the prompt text retained in partial output instead of its absence. +The loader-composition suite records every send's `waitReason` and requires at least six `stdin_read` settlements and no `inferred_idle`: the regression is reported by the settle reason itself, not by how long silence takes. Reinstating the removed prompt override fails that assertion after 30 s with `expected 0 to be greater than or equal to 6`, while the case's output assertions still pass. The stub suite drops the initialization-handshake modes and pins the prompt text retained in partial output instead of its absence. A model command that redefines `prompt` still removes the readiness marker and degrades later sends to the silence tier: the backend installs its prompt once at startup and cannot re-assert it. diff --git a/.agents/notes/implemented/bug-fix/2026-09-21-persistent-pwsh-keeps-controlled-prompt.zh.md b/.agents/notes/implemented/bug-fix/2026-09-21-persistent-pwsh-keeps-controlled-prompt.zh.md index 6425581a6d..88d4e2deef 100644 --- a/.agents/notes/implemented/bug-fix/2026-09-21-persistent-pwsh-keeps-controlled-prompt.zh.md +++ b/.agents/notes/implemented/bug-fix/2026-09-21-persistent-pwsh-keeps-controlled-prompt.zh.md @@ -30,8 +30,8 @@ Status: implemented Windows、生产默认值、真实 Loader 组合:工具调用从 8493/3722/3832/3759 毫秒降至 1340/255/251/241 毫秒(spawn + 初始化 + 首条命令,随后三条热命令)。 -`stdin_read` 回退是行为而不只是美化:在提供方能证明前台 stdin 等待之处,交互式子进程现在返回已捕获的部分输出,而不是空转到命令期限;其他情况下调用仍会运行到 `timeoutMs`,两者都记入工具 README。由标记界定的完整输出保持不变。 +`stdin_read` 回退是行为而不只是美化:在提供方能证明前台 stdin 等待之处,交互式子进程会返回已捕获的部分输出,而不是空转到命令期限;其他情况下调用仍会运行到 `timeoutMs`。该提前返回保留会话,因此仍在读取 stdin 的子进程可能吞掉下一次调用的命令,直到那次调用到达 `timeoutMs` 并重置 shell;`dsh-tool-bash-persistent` 行为相同,而区分「shell 自身的提示符就绪」与「子进程的 stdin 等待」属于 seam,而不是任一工具。由标记界定的完整输出保持不变。 -loader 组合套件现在把 `idleSilenceMs` 设为 30000,位于 send 上限之上,静默无法结算任何 send,提示符就绪一旦回归,每个用例都会失败。stub 套件删除了初始化握手模式,并改为锚定部分输出中保留的提示符文本,而不是它的缺席。 +loader 组合套件记录每次 send 的 `waitReason`,要求至少六次 `stdin_read` 且没有 `inferred_idle`:回归由结算原因本身报告,而不是靠静默层耗时。把删掉的提示符覆盖加回去,该断言会在 30 秒后以 `expected 0 to be greater than or equal to 6` 失败,而同一用例的输出断言仍然通过。stub 套件删除了初始化握手模式,并改为锚定部分输出中保留的提示符文本,而不是它的缺席。 重定义 `prompt` 的模型命令仍会移除就绪标记,并把后续 send 降级到静默层:后端只在启动时安装一次提示符,无法重新设定。 diff --git a/packages/shell/tool-pwsh-persistent/README.i18n.yaml b/packages/shell/tool-pwsh-persistent/README.i18n.yaml index 00dcbdee79..d0e2b2e198 100644 --- a/packages/shell/tool-pwsh-persistent/README.i18n.yaml +++ b/packages/shell/tool-pwsh-persistent/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/shell/tool-pwsh-persistent/README.md -README.md: d4c52d9209118830364b7d20e8ee4a26452ad604 -README.zh.md: eedf8e7135e9bd2c73b70e891658920b5d6c64e8 +README.md: cd78f224f9f85899cca1f578fd0316c6f4caab2f +README.zh.md: 53b0b4cdd69ac94556f16621ccd3d9ca205cc6f4 diff --git a/packages/shell/tool-pwsh-persistent/README.md b/packages/shell/tool-pwsh-persistent/README.md index d4c52d9209..cd78f224f9 100644 --- a/packages/shell/tool-pwsh-persistent/README.md +++ b/packages/shell/tool-pwsh-persistent/README.md @@ -149,7 +149,7 @@ These limits define when the tool is a poor fit or needs special care. They are - **Input echo is unavoidable** — PowerShell's PSReadLine renders submitted input back into the terminal stream, and there is no `stty -echo` equivalent. The marker-anchored extraction excludes the echo in complete results; the wrapper-source strip covers fallback paths, but a wrapper that wraps across the terminal width may leave a partial echo in partial-output results, bounded by `maxOutputChars`. - **Raw ESC characters inside model commands are unsupported** — PSReadLine consumes them before execution. The wrapper escapes the control bytes it needs (`[char]27`-built OSC markers, backtick escapes for the body). - **A model redefinition of the `prompt` function removes the readiness marker** — the shell then settles on the silence tier instead of the marker fast path. -- **There is no interactive stdin during a command** — a foreground child that reads input returns early with partial output only where the provider proves its stdin wait; elsewhere the call runs to `timeoutMs`, which resets the shell. +- **There is no interactive stdin during a command** — where the provider proves a foreground stdin wait, a child that reads input returns early with partial output and leaves the session open, so that child can consume the next call's command until the call reaches `timeoutMs` and resets the shell. Everywhere else the original call itself runs to `timeoutMs`, which resets the shell. - **SIGTSTP/SIGHUP are unavailable on Windows** (backend-rejected); SIGINT is delivered as a console-wide Ctrl-C input write, which at a prompt cancels the pending line instead of signalling a process. - **Under the Windows ACL sandbox's read-only mode, pwsh starts in ConstrainedLanguage**, which may deny the bootstrap's `[Console]::` encoding pin and prompt marker. Commands can still settle through the printable prompt and silence tier, but non-ASCII output may follow the host code page. - **The BEL-terminated OSC marker remains a readiness signal only** — a BEL event channel to the model stays deferred, aligned with the current implementation. diff --git a/packages/shell/tool-pwsh-persistent/README.zh.md b/packages/shell/tool-pwsh-persistent/README.zh.md index eedf8e7135..53b0b4cdd6 100644 --- a/packages/shell/tool-pwsh-persistent/README.zh.md +++ b/packages/shell/tool-pwsh-persistent/README.zh.md @@ -149,7 +149,7 @@ kind: "package-reference" - **输入回显不可避免**——PowerShell 的 PSReadLine 会把提交的输入渲染回终端流,而且没有 `stty -echo` 等价物。标记锚定提取在完整结果中排除回显;包装源码剥离覆盖回退路径,但跨终端宽度换行的包装可能在部分输出结果中留下部分回显,受 `maxOutputChars` 设界。 - **模型命令内的原始 ESC 字符不受支持**——PSReadLine 会在执行前消费它们。包装器会转义它需要的控制字节(`[char]27` 构造的 OSC 标记、正文的反引号转义)。 - **模型重定义 `prompt` 函数会移除就绪标记**——shell 随后在静默层级而非标记快路径上结算。 -- **命令期间没有交互 stdin**——读取输入的前台子进程仅在提供方能证明其 stdin 等待时提前返回部分输出;否则调用会运行到 `timeoutMs`,随后重置 shell。 +- **命令期间没有交互 stdin**——在提供方能证明前台 stdin 等待之处,读取输入的子进程会提前返回部分输出并保留会话,因此该子进程可能吞掉下一次调用的命令,直到那次调用到达 `timeoutMs` 并重置 shell。其他情况下原调用本身会运行到 `timeoutMs`,随后重置 shell。 - **Windows 上 SIGTSTP/SIGHUP 不可用**(后端拒绝);SIGINT 以控制台级 Ctrl-C 输入写入投递,在提示词处会取消待处理行而不是向进程发信号。 - **在 Windows ACL 沙箱的只读模式下,pwsh 以 ConstrainedLanguage 启动**,可能拒绝引导的 `[Console]::` 编码固定与 prompt 标记。命令仍可通过可打印提示词与静默层级结算,但非 ASCII 输出可能跟随宿主代码页。 - **BEL 结尾的 OSC 标记目前只是就绪信号**——通向模型的 BEL 事件通道仍被推迟,与当前实现保持一致。 diff --git a/packages/shell/tool-pwsh-persistent/tests/loader-composition.spec.ts b/packages/shell/tool-pwsh-persistent/tests/loader-composition.spec.ts index 96fe69116c..8641952fb4 100644 --- a/packages/shell/tool-pwsh-persistent/tests/loader-composition.spec.ts +++ b/packages/shell/tool-pwsh-persistent/tests/loader-composition.spec.ts @@ -3,7 +3,7 @@ import { mkdtemp, realpath, rm, writeFile } from 'node:fs/promises' import { tmpdir } from 'node:os' import { join } from 'node:path' import { pathToFileURL } from 'node:url' -import { afterEach, describe, expect, it } from 'vitest' +import { afterEach, describe, expect, it, vi } from 'vitest' import { Context } from '@deepseek-ai/cordis' import Loader from '@deepseek-ai/cordis-plugin-loader' import Include from '@deepseek-ai/cordis-plugin-include' @@ -13,6 +13,7 @@ import AgentRegistry from '@deepseek-ai/dsh-agent' import SessionProjectionRegistry from '@deepseek-ai/dsh-session-projection' import type { Agent } from '@deepseek-ai/dsh-agent' import TerminalSessionService from '@deepseek-ai/dsh-terminal' +import type { TerminalWaitReason } from '@deepseek-ai/dsh-terminal' import * as TerminalBash from '@deepseek-ai/dsh-terminal-bash' import SandboxProvider from '@deepseek-ai/dsh-sandbox' import type { ConfinedArgv, SandboxPolicy } from '@deepseek-ai/dsh-sandbox' @@ -95,10 +96,9 @@ describe.skipIf(!hasPwsh)('persistent pwsh through a real cordis.yml Loader comp ' shellDialect: pwsh', ' pollIntervalMs: 10', ' exactProbeAfterMs: 20', - // The silence tier is pushed beyond the send bound, so no send below can - // settle as inferred_idle: every case proves the controlled-prompt fast - // path that the production defaults (3.5s silence) would otherwise mask. - ' idleSilenceMs: 30000', + // The silence tier keeps its product default; the case body records each + // send's wait reason, which pins the controlled-prompt fast path directly + // instead of relying on how long silence would take to settle. ' handoffGraceMs: 300', ' scrollbackLines: 20000', // The first call pays the full pwsh cold-start latency (spawn + .NET + @@ -143,6 +143,22 @@ describe.skipIf(!hasPwsh)('persistent pwsh through a real cordis.yml Loader comp await context.loader.create({ name: 'cordis:include', config: { path: pathToFileURL(configPath).href } }) await context.loader.await() + const terminals = context.terminals + const startSend = terminals.startSend.bind(terminals) + // A send that lost the controlled-prompt fast path settles as inferred_idle + // after the silence tier, so recording why every send settled detects that + // regression immediately instead of through accumulated wall-clock. + const settleReasons: TerminalWaitReason[] = [] + vi.spyOn(terminals, 'startSend').mockImplementation((owner, id, request) => { + const operation = startSend(owner, id, request) + void operation.done.then( + (settled) => { settleReasons.push(settled.waitReason) }, + // A rejected send is the tool's error path, not a settle reason. + () => {}, + ) + return operation + }) + const owner = await agent(context, root) const signal = new AbortController().signal const execute = (id: string, command: string) => context!.tools.execute({ @@ -180,5 +196,10 @@ describe.skipIf(!hasPwsh)('persistent pwsh through a real cordis.yml Loader comp const exited = text(await execute('exit', 'exit')) expect(exited).toContain('next pwsh call starts from the workspace') expect(text(await execute('after-exit', 'Write-Output "$PWD"'))).toBe(root) + + // Six commands settle on the controlled prompt; no send may fall back to the + // silence tier, which is the 3.5 s-per-call degradation this suite pins. + expect(settleReasons.filter(reason => reason === 'stdin_read').length).toBeGreaterThanOrEqual(6) + expect(settleReasons).not.toContain('inferred_idle') }, 120_000) }) diff --git a/packages/shell/tool-pwsh-persistent/tests/tools.spec.ts b/packages/shell/tool-pwsh-persistent/tests/tools.spec.ts index bf2ff8454b..2957c34b54 100644 --- a/packages/shell/tool-pwsh-persistent/tests/tools.spec.ts +++ b/packages/shell/tool-pwsh-persistent/tests/tools.spec.ts @@ -356,7 +356,7 @@ describe('tool-pwsh-persistent', () => { expect(result).not.toContain('Invoke-Expression') }) - it('preserves command output that equals the private shell prompt', async () => { + it("preserves command output that equals the backend's prompt text", async () => { const { ctx, owner, stub } = await setup({ backendType: 'stub' }) await call(ctx, owner, 'warm up') const session = stub.sessions[0]! @@ -404,6 +404,12 @@ describe('tool-pwsh-persistent', () => { const crlfPromptFallback = text(await call(ctx, owner, 'bad {')) expect(crlfPromptFallback).toContain('pwsh: synt') + // The stdin_read fallback returns captured output without resetting the + // shell, so later calls keep the same session; the README names the + // interactive-child consequence of that retention. + expect(session.closed).toEqual([]) + expect(stub.sessions).toHaveLength(1) + session.mode = 'end-only' session.scrollback = '' const missingStart = text(await call(ctx, owner, 'recover marker')) @@ -656,14 +662,14 @@ describe('tool-pwsh-persistent', () => { } }) - it.each(['initialization', 'command', 'cleanup'] as const)('preserves a distinct %s failure during cancellation', async (phase) => { + it.each(['command', 'cleanup'] as const)('preserves a distinct %s failure during cancellation', async (phase) => { const { ctx, owner } = await setup() - if (phase === 'command') await call(ctx, owner, 'warm up') + await call(ctx, owner, 'warm up') const controller = new AbortController() const failure = new Error(`${phase} failed`) vi.spyOn(ctx.terminals, 'startSend').mockImplementationOnce(() => { controller.abort({ kind: 'user' }) - throw phase === 'cleanup' ? new Error('initialization failed') : failure + throw phase === 'cleanup' ? new Error('send failed') : failure }) if (phase === 'cleanup') vi.spyOn(ctx.terminals, 'kill').mockRejectedValueOnce(failure) const result = await call(ctx, owner, 'fails', controller.signal) From 8d2cd0cf72090cc58fe8cfc9258ebbdf58ac9f1e Mon Sep 17 00:00:00 2001 From: yixiangihsiang Date: Mon, 21 Sep 2026 21:56:10 +0800 Subject: [PATCH 03/29] feat(web): unify code block styling and icon controls --- apps/web/tests/document-preview.e2e.ts | 7 +- .../clickable-links-gallery/ui.expected.md | 6 +- .../navigation-panes/code-card.expected.md | 4 + apps/web/tests/navigation-panes.e2e.ts | 23 +++++ packages/client/locale/src/locales/en.ts | 3 + packages/client/locale/src/locales/zh.ts | 3 + .../src/client/PresetGuideDialog.tsx | 9 +- .../ui-chat/src/client/markdown-labels.ts | 2 +- .../client/ui-plan/src/client/PlanPreview.tsx | 2 +- .../client/ui-primitives/README.i18n.yaml | 4 +- packages/client/ui-primitives/README.md | 2 + packages/client/ui-primitives/README.zh.md | 2 + .../ui-primitives/src/CodeCard.module.css | 81 ++++++++++++++++ .../client/ui-primitives/src/CodeToolbar.tsx | 62 ++++++++++++ .../ui-primitives/src/DiffBlock.module.css | 67 ++++--------- .../client/ui-primitives/src/DiffBlock.tsx | 15 ++- .../ui-primitives/src/ReadBlock.module.css | 92 +++--------------- .../client/ui-primitives/src/ReadBlock.tsx | 29 +++--- .../src/markdown/CodeBlock.module.css | 19 ++++ .../ui-primitives/src/markdown/CodeBlock.tsx | 20 +++- .../src/markdown/MarkdownText.tsx | 5 +- .../ui-primitives/src/markdown/render.tsx | 3 + .../tests/code-card-controls.client.spec.tsx | 96 +++++++++++++++++++ .../ui-primitives/tests/labels.client.ts | 2 + .../tests/read-block.client.spec.tsx | 7 +- .../README.i18n.yaml | 4 +- .../ui-sidebar-documentpreview/README.md | 2 +- .../ui-sidebar-documentpreview/README.zh.md | 2 +- .../src/client/code/CodeBody.module.css | 1 + .../src/client/code/CodeBody.tsx | 2 + .../src/client/markdown/MarkdownBody.tsx | 7 +- .../tests/code-body.client.spec.tsx | 11 ++- packages/client/ui-theme/src/styles/shiki.css | 7 ++ .../tool/components/ToolDetails.module.css | 8 +- .../client/tool/components/ToolDetails.tsx | 3 +- .../client/tool/components/ToolRow.module.css | 6 -- .../src/client/tool/components/ToolRow.tsx | 5 +- .../client/tool/models/primitive-labels.ts | 14 ++- .../ui-tool/tests/diff-card.client.spec.tsx | 2 +- .../src/client/QuestionComposer.tsx | 2 +- .../ui-cordis/src/client/CordisDefineRow.tsx | 1 + 41 files changed, 449 insertions(+), 193 deletions(-) create mode 100644 apps/web/tests/expected/navigation-panes/code-card.expected.md create mode 100644 packages/client/ui-primitives/src/CodeCard.module.css create mode 100644 packages/client/ui-primitives/src/CodeToolbar.tsx create mode 100644 packages/client/ui-primitives/tests/code-card-controls.client.spec.tsx diff --git a/apps/web/tests/document-preview.e2e.ts b/apps/web/tests/document-preview.e2e.ts index 07e7397d12..fd0ebd02ad 100644 --- a/apps/web/tests/document-preview.e2e.ts +++ b/apps/web/tests/document-preview.e2e.ts @@ -797,7 +797,12 @@ else process.exit(1); })).toEqual({ scrollTop, scrollportBelowBanner: true, firstLineAbove: true }) await page.context().grantPermissions(['clipboard-read', 'clipboard-write'], { origin: new URL(page.url()).origin }) await page.evaluate(() => navigator.clipboard.writeText('')) - await codeBlock.getByRole('button', { name: 'Copy', exact: true }).click() + const copyCode = codeBlock.getByRole('button', { name: 'Copy', exact: true }) + expect(await codeBlock.getByRole('button').count()).toBe(1) + expect(await copyCode.textContent()).toBe('') + await copyCode.hover() + await page.getByRole('tooltip', { name: 'Copy', exact: true }).waitFor() + await copyCode.click() await expect.poll(() => page.evaluate(() => navigator.clipboard.readText())).toBe(codeLines.join('\n')) sections.push([ '## Code paging', '', diff --git a/apps/web/tests/expected/clickable-links-gallery/ui.expected.md b/apps/web/tests/expected/clickable-links-gallery/ui.expected.md index 43b462deac..feaeaa2468 100644 --- a/apps/web/tests/expected/clickable-links-gallery/ui.expected.md +++ b/apps/web/tests/expected/clickable-links-gallery/ui.expected.md @@ -32,6 +32,8 @@ - text: Edit - button "src/tokens.css" - text: +1 -1 +- text: css +- button "Wrap lines" - button "Copy" - text: "src/tokens.css - --inline-code: #EBEEF2; + --inline-code: #F5F5F5; └ +1 -1 · 1 file" - button "Inspect" @@ -43,7 +45,8 @@ - button "Read docs/guide.md" [expanded]: - text: Read - button "docs/guide.md" -- text: docs/guide.md +- text: Code block docs/guide.md +- button "Wrap lines" - button "Copy" - text: "# Link style guide guide line 2 guide line 3 guide line 4" - button "Expand 4 more lines": … 4 more lines @@ -134,6 +137,7 @@ - paragraph: - img "Token preview" - text: css +- button "Do not wrap lines" [pressed] - button "Copy" - code: "--inline-code: #F5F5F5;" - paragraph: LINK_GALLERY_DONE diff --git a/apps/web/tests/expected/navigation-panes/code-card.expected.md b/apps/web/tests/expected/navigation-panes/code-card.expected.md new file mode 100644 index 0000000000..3e48942224 --- /dev/null +++ b/apps/web/tests/expected/navigation-panes/code-card.expected.md @@ -0,0 +1,4 @@ +- text: Code block +- button "Do not wrap lines" [pressed] +- button "Copy" +- code: echo WATERFALL diff --git a/apps/web/tests/navigation-panes.e2e.ts b/apps/web/tests/navigation-panes.e2e.ts index 4ab75b3ba0..f43b020a60 100644 --- a/apps/web/tests/navigation-panes.e2e.ts +++ b/apps/web/tests/navigation-panes.e2e.ts @@ -27,6 +27,7 @@ const TRAJECTORY_EXPECTED = join(SNAPSHOT_DIR, 'trajectory.expected.md') const TIMING_EXPECTED = join(SNAPSHOT_DIR, 'timing.expected.md') const SEARCH_EXPECTED = join(SNAPSHOT_DIR, 'search-results.expected.md') const TERMINAL_EXPECTED = join(SNAPSHOT_DIR, 'terminal-card.expected.md') +const CODE_CARD_EXPECTED = fileURLToPath(new URL('./expected/navigation-panes/code-card.expected.md', import.meta.url)) const MODE = webSnapshotMode() const SEED_ID = 'navigation-panes-web-e2e' const EXPORTED_LOG_FILE = `session.v${SESSION_FORMAT_VERSION}.jsonl` @@ -218,6 +219,28 @@ describe('web e2e: navigation & panes over a rich seeded session', () => { await expect.poll(() => page.getByRole('heading', { name: 'Navigation Summary' }).count(), { timeout: 15_000 }).toBe(1) }, 90_000) + it.skipIf(MODE === 'record')('renders recorded Markdown with icon tooltips and switchable wrapping', async () => { + onTestFailed(() => saveFailureShot(page, 'web-e2e-navigation-code-card')) + await ensureSeedOpen(page) + const selector = '.md-code-block:has-text("echo WATERFALL")' + const block = page.locator(selector) + await block.waitFor({ timeout: 15_000 }) + await compareOrRefreshGolden(CODE_CARD_EXPECTED, await captureStableAria(page, selector, scaffold.workspaceCwd), MODE) + const code = block.locator('pre') + const source = await code.textContent() + const copy = block.getByRole('button', { name: 'Copy', exact: true }) + await copy.hover() + await page.getByRole('tooltip', { name: 'Copy', exact: true }).waitFor() + const unwrap = block.getByRole('button', { name: 'Do not wrap lines', exact: true }) + await unwrap.hover() + await page.getByRole('tooltip', { name: 'Do not wrap lines', exact: true }).waitFor() + await unwrap.click() + await expect.poll(() => code.evaluate(element => getComputedStyle(element).whiteSpace)).toBe('pre') + await block.getByRole('button', { name: 'Wrap lines', exact: true }).click() + await expect.poll(() => code.evaluate(element => getComputedStyle(element).whiteSpace)).toBe('pre-wrap') + expect(await code.textContent()).toBe(source) + }, 60_000) + it.skipIf(MODE === 'record')('renders the trajectory ledger and opens its local record inspector', async () => { onTestFailed(() => saveFailureShot(page, 'web-e2e-navigation-trajectory')) await ensureSeedOpen(page) diff --git a/packages/client/locale/src/locales/en.ts b/packages/client/locale/src/locales/en.ts index d16b4913ae..d21b7d67f7 100644 --- a/packages/client/locale/src/locales/en.ts +++ b/packages/client/locale/src/locales/en.ts @@ -7,6 +7,9 @@ export const en = { 'close': 'Close', 'copy': 'Copy', 'copied': 'Copied', + 'codeBlock.title': 'Code block', + 'codeBlock.wrap': 'Wrap lines', + 'codeBlock.unwrap': 'Do not wrap lines', 'copy.failed': 'Copy failed', 'copy.value': 'Copy value', 'copy.json': 'Copy JSON', diff --git a/packages/client/locale/src/locales/zh.ts b/packages/client/locale/src/locales/zh.ts index 2e932cef41..d7b215babd 100644 --- a/packages/client/locale/src/locales/zh.ts +++ b/packages/client/locale/src/locales/zh.ts @@ -5,6 +5,9 @@ export const zh = { 'close': '关闭', 'copy': '复制', 'copied': '复制成功', + 'codeBlock.title': '代码块', + 'codeBlock.wrap': '自动换行', + 'codeBlock.unwrap': '取消自动换行', 'copy.failed': '复制失败', 'copy.value': '复制值', 'copy.json': '复制 JSON', diff --git a/packages/client/ui-agent-preset/src/client/PresetGuideDialog.tsx b/packages/client/ui-agent-preset/src/client/PresetGuideDialog.tsx index 6ecb534f02..8ca5270d52 100644 --- a/packages/client/ui-agent-preset/src/client/PresetGuideDialog.tsx +++ b/packages/client/ui-agent-preset/src/client/PresetGuideDialog.tsx @@ -1,6 +1,7 @@ /** Read-only help stays local to Settings and never changes the selected preset. */ import { useId, useLayoutEffect, useRef, useState } from 'react' import type { KeyboardEvent, ReactNode } from 'react' +import type { TranslateNS } from '@deepseek-ai/dsh-client-ui-slots' import { Button, IconCloseOutlineRegular, IconListPenOutlineRegular, MarkdownText, Modal, SegmentedTabs, Tag } from '@deepseek-ai/dsh-client-ui-primitives' import type { AgentPresetSettingsKey } from './locales.ts' import css from './PresetGuideDialog.module.css' @@ -35,10 +36,10 @@ export function presetGuide(id: string, trust: string): PresetGuide | undefined /** Curated usage dictionaries contain only level-three example sections. */ function GuideUsage({ text, t }: { text: string - t: (key: AgentPresetSettingsKey) => string + t: TranslateNS<'settings.agentPreset'> }): ReactNode { const labels = { - code: { copyLabel: t('guideCopy'), copiedLabel: t('guideCopied') }, + code: { copyLabel: t('guideCopy'), copiedLabel: t('guideCopied'), toolbarLabels: { codeLabel: t('codeBlock.title'), wrapLabel: t('codeBlock.wrap'), unwrapLabel: t('codeBlock.unwrap') } }, footnotes: t('guideFootnotes'), } return text.split(/(?=^### )/m).map((section) => { @@ -67,7 +68,7 @@ function GuideUsage({ text, t }: { export function PresetGuideDialog({ guide, initialPage, t, onClose }: { guide: PresetGuide initialPage: PresetGuidePage - t: (key: AgentPresetSettingsKey) => string + t: TranslateNS<'settings.agentPreset'> onClose: () => void }): ReactNode { const [page, setPage] = useState(initialPage) @@ -144,7 +145,7 @@ export function PresetGuideDialog({ guide, initialPage, t, onClose }: { diff --git a/packages/client/ui-chat/src/client/markdown-labels.ts b/packages/client/ui-chat/src/client/markdown-labels.ts index 6c30b99396..8818ea8f14 100644 --- a/packages/client/ui-chat/src/client/markdown-labels.ts +++ b/packages/client/ui-chat/src/client/markdown-labels.ts @@ -10,7 +10,7 @@ import type { ChatViewSlotProps } from './contract/slots.ts' */ export function markdownLabels(t: ChatViewSlotProps['t']): MarkdownLabels { return { - code: { copyLabel: t('copy'), copiedLabel: t('copied') }, + code: { copyLabel: t('copy'), copiedLabel: t('copied'), toolbarLabels: { codeLabel: t('codeBlock.title'), wrapLabel: t('codeBlock.wrap'), unwrapLabel: t('codeBlock.unwrap') } }, footnotes: t('markdown.footnotes'), } } diff --git a/packages/client/ui-plan/src/client/PlanPreview.tsx b/packages/client/ui-plan/src/client/PlanPreview.tsx index b1e1689fe8..fdee35e7b9 100644 --- a/packages/client/ui-plan/src/client/PlanPreview.tsx +++ b/packages/client/ui-plan/src/client/PlanPreview.tsx @@ -22,7 +22,7 @@ export function PlanPreview({ useTabInfo, useResource, t }: PlanPreviewProps) { const params = tab.tab.navigation.params const plan = temporary ? (params !== undefined && 'planReview' in params ? params.planReview : undefined) : resource.value const labels = useMemo(() => ({ - code: { copyLabel: t('copy'), copiedLabel: t('copied') }, + code: { copyLabel: t('copy'), copiedLabel: t('copied'), toolbarLabels: { codeLabel: t('codeBlock.title'), wrapLabel: t('codeBlock.wrap'), unwrapLabel: t('codeBlock.unwrap') } }, footnotes: t('markdown.footnotes'), }), [t]) if (plan === undefined) return ( diff --git a/packages/client/ui-primitives/README.i18n.yaml b/packages/client/ui-primitives/README.i18n.yaml index 38355c398f..c14c318535 100644 --- a/packages/client/ui-primitives/README.i18n.yaml +++ b/packages/client/ui-primitives/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-primitives/README.md -README.md: 7dafaf759ac329a4162b7138e58ed13ca5afd651 -README.zh.md: db38df0a298f567287e9cc99e623287465213c74 +README.md: 069aea78dd08175a9ebb1e590bb03e97dc08daab +README.zh.md: d235e19a9f9c829d4d5d6587fdd147fda9a2884e diff --git a/packages/client/ui-primitives/README.md b/packages/client/ui-primitives/README.md index 7dafaf759a..069aea78dd 100644 --- a/packages/client/ui-primitives/README.md +++ b/packages/client/ui-primitives/README.md @@ -87,6 +87,8 @@ The nearest `MarkdownDelegateProvider` supplies optional `openExternalLink` and `MarkdownText` defaults to `variant="body"`. Use `variant="compact"` for secondary content: its 13px text and 20px line height follow the content-size setting, all heading levels use the same size with weight 600, and paragraphs and lists use tighter spacing. Text, links, and code keep the tertiary color; dotted underlines distinguish links. Code headers scroll with their blocks. Tables and math stay enabled at the surrounding text size and scroll horizontally within the available width. Both variants share the parser and streaming cache. +`CodeBlock.toolbarLabels` enables the shared code-card header and spacing. `ReadBlock` and `DiffBlock` use the same header: secondary-colored language text, copy and wrap icons, and hover or keyboard-focus tooltips. Missing or unsupported languages use the owner’s localized code-block title; mixed-language diffs use that title too. Code cards share typography and content insets. Wrapping is local to each mounted card and never changes copied text; code fences start wrapped, while reads and diffs preserve source columns until wrapping is enabled. Compact Markdown omits this toolbar. With `toolbarLabels`, source previews can pass `wrap` to follow their owner’s preference and show only the language and copy icon; owner CSS retains the source layout. + `DiffBlock` compares the old and new content by line. It shows actual additions and deletions with up to three neutral context lines on each side, separates distant changes with `⋯`, and excludes shared context from both summary and footer totals. Search stops beyond 256 line additions/deletions per fragment; those fragments display and count the complete old and new contents as a coarse replacement, including shared lines. Copy includes the full displayed diff with its prefixes. A final newline is treated as a terminator; differences only in the presence of a final newline are not displayed. `JsonTree` clamps collapsed strings to `collapsedStringLines` (three by default). Expanded strings show raw text, retain sibling commas, and fit within the window and outer scrolling containers. Resize and ancestor-scroll events update that limit. Row copy feedback updates independently of JSON value rendering; pending clipboard writes cannot update a different row or an unmounted tree. diff --git a/packages/client/ui-primitives/README.zh.md b/packages/client/ui-primitives/README.zh.md index db38df0a29..d235e19a9f 100644 --- a/packages/client/ui-primitives/README.zh.md +++ b/packages/client/ui-primitives/README.zh.md @@ -87,6 +87,8 @@ kind: "package-library" `MarkdownText` 默认为 `variant="body"`。次级内容使用 `variant="compact"`:其 13px 字号与 20px 行高跟随内容字号设置,各级标题保持同一字号并使用 600 字重,段落与列表采用更紧凑的间距。正文、链接和代码均保持 tertiary 颜色,以点状下划线区分链接。代码标题栏随代码块滚动。表格和公式仍然启用,使用周围文字的字号,并在可用宽度内横向滚动。两个变体共享解析器与流式缓存。 +`CodeBlock.toolbarLabels` 启用共享代码卡片的标题栏和间距。`ReadBlock` 与 `DiffBlock` 使用相同的标题栏:secondary 色的语言名称、复制与换行图标,以及悬停或键盘聚焦时的提示。语言缺失或不受支持时显示调用方提供的本地化代码块标题;混合语言的 Diff 也使用该标题。代码卡片共用字体和内容内边距。换行设置仅属于当前挂载的卡片,不改变复制的文本;代码围栏默认换行,读取和差异卡片则在启用换行前保留源码列位置。紧凑 Markdown 不使用此工具栏。源码预览传入 `toolbarLabels` 后,可用 `wrap` 跟随所属视图的换行设置,仅显示语言和复制图标;所属视图的 CSS 保留源码布局。 + `DiffBlock` 按行比较新旧内容。它显示实际增删行及两侧最多三行中性上下文,用 `⋯` 分隔远距离改动,摘要和底部统计都不计入共享上下文。若一个片段需要超过 256 次行新增或删除,则停止精确比较;该片段按完整新旧内容显示和统计为粗粒度替换,包含共享行。复制包含完整显示 diff 及其前缀。末尾换行视为行终止符;仅末尾换行不同不会显示为改动。 `JsonTree` 把折叠字符串限制为 `collapsedStringLines` 行(默认三行)。展开后显示原始文本、保留同级逗号,并限制在窗口与外层滚动容器内;尺寸变化和祖先滚动事件会更新此限制。行复制反馈独立于 JSON 值渲染更新;尚未完成的剪贴板写入不会更新另一行或已卸载的树。 diff --git a/packages/client/ui-primitives/src/CodeCard.module.css b/packages/client/ui-primitives/src/CodeCard.module.css new file mode 100644 index 0000000000..fa3a6e579a --- /dev/null +++ b/packages/client/ui-primitives/src/CodeCard.module.css @@ -0,0 +1,81 @@ +.card { + position: relative; + margin: 16px 0; + color: var(--dsw-alias-label-primary); + background: var(--dsw-alias-markdown-code-block); + border-radius: 12px; + font: var(--dsw-font-markdown-code-block); +} + +.header { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; + padding: 10px 18px 4px; + background: var(--dsw-alias-markdown-code-block-banner); + border-top-left-radius: inherit; + border-top-right-radius: inherit; + color: var(--dsw-alias-label-secondary); + font: 11px/18px var(--dsw-font-family); +} + +.heading { + display: flex; + align-items: baseline; + gap: 12px; + min-width: 0; +} + +.language { + flex: none; + font-family: var(--ds-font-family-code); +} + +.title { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.actions { + display: flex; + align-items: center; + gap: 4px; + flex: none; +} + +.status { + margin-right: 8px; + color: var(--dsw-alias-label-tertiary); + white-space: nowrap; +} + +.action { + display: inline-flex; + align-items: center; + justify-content: center; + width: 24px; + height: 24px; + padding: 0; + border: 0; + border-radius: 6px; + color: var(--dsw-alias-label-secondary); + background: transparent; + cursor: pointer; +} + +.action:hover { + background: var(--dsw-alias-interactive-bg-hover); +} + +.action:focus-visible { + outline: 1px solid var(--dsw-alias-state-business-primary); + outline-offset: 2px; +} + +.body { + padding: 6px 18px 16px; + font: var(--dsw-font-markdown-code-block); + overflow-x: auto; +} diff --git a/packages/client/ui-primitives/src/CodeToolbar.tsx b/packages/client/ui-primitives/src/CodeToolbar.tsx new file mode 100644 index 0000000000..755753e894 --- /dev/null +++ b/packages/client/ui-primitives/src/CodeToolbar.tsx @@ -0,0 +1,62 @@ +/** Shared language, wrapping, and clipboard controls for code cards. */ +import { + IconCheckOutlineRegular, IconCopyOutlineRegular, IconNowrapFillRegular, IconWrapFillRegular, +} from './icons/index.tsx' +import { Tooltip } from './Tooltip.tsx' +import { supportsHighlighting } from './markdown/highlight.ts' +import css from './CodeCard.module.css' + +/** Localized language fallback and wrapping actions supplied by the card owner. */ +export interface CodeToolbarLabels { + /** Title for an absent or unsupported language. */ + codeLabel: string + /** Action that enables wrapping. */ + wrapLabel: string + /** Action that preserves source columns with horizontal scrolling. */ + unwrapLabel: string +} + +/** Display state and callbacks for a code card's toolbar. */ +interface CodeToolbarProps { + lang?: string | undefined + title?: string | undefined + status?: string | undefined + labels: CodeToolbarLabels + copyLabel: string + copiedLabel: string + copied: boolean + wrapped: boolean + onCopy?: (() => void) | undefined + onWrap?: (() => void) | undefined +} + +/** + * Render a language label and keyboard-accessible icon actions with tooltips. + * @param props - Localized labels, current state, and card-owned actions. + * @returns The shared code-card header. + */ +export function CodeToolbar({ lang, title, status, labels, copyLabel, copiedLabel, copied, wrapped, onCopy, onWrap }: CodeToolbarProps) { + const wrapLabel = wrapped ? labels.unwrapLabel : labels.wrapLabel + const clipboardLabel = copied ? copiedLabel : copyLabel + return ( +
+
+ {supportsHighlighting(lang) ? lang : labels.codeLabel} + {title !== undefined && {title}} +
+
+ {status !== undefined && {status}} + {onWrap !== undefined && + + } + {onCopy !== undefined && + + } +
+
+ ) +} diff --git a/packages/client/ui-primitives/src/DiffBlock.module.css b/packages/client/ui-primitives/src/DiffBlock.module.css index dd1d621aeb..649237832c 100644 --- a/packages/client/ui-primitives/src/DiffBlock.module.css +++ b/packages/client/ui-primitives/src/DiffBlock.module.css @@ -1,79 +1,52 @@ .block { - --dsl-diff-radius: 12px; - --dsl-diff-line-height: 22px; - - position: relative; - margin: 16px 0; - color: var(--dsw-alias-label-primary); - background: var(--dsw-alias-markdown-code-block); - border-radius: var(--dsl-diff-radius); -} - -/* The copy control floats in the top-right corner over the body, so the card - has no empty banner row above its first diff line (the TUI diff card has no - banner either — only the footer). The block is position: relative, so this - anchors to the card. */ -.copyButton { - position: absolute; - top: 8px; - right: 12px; - z-index: 1; - background-color: transparent; - border: none; - padding: 0; - margin: 0; - color: var(--dsw-alias-label-secondary); - cursor: pointer; - font: var(--dsw-font-xs-13); + overflow: hidden; } .body { - padding: 12px 14px; + padding: 6px 0 16px; font: var(--dsw-font-markdown-code-block); overflow-x: auto; - overflow-y: hidden; } -/* No wrapping, no word-break: a diff is read by its indentation. */ .line { - min-height: var(--dsl-diff-line-height); + box-sizing: border-box; + min-height: 1lh; + padding: 0 18px; white-space: pre; } -/* A file header: the path in the primary tone, set apart by weight. The copy - button floats over this first row's top-right corner, so reserve space at the - line's end for it — a long path scrolls under the button otherwise, and the - button's hit area would eat clicks on the path's tail. */ +.block[data-code-wrap='true'] .line { + white-space: pre-wrap; + overflow-wrap: anywhere; +} + .path { - color: var(--dsw-alias-label-primary); - font-weight: 600; - padding-right: 56px; + color: var(--dsw-alias-label-secondary); + font-weight: 500; } -/* A same-file second hunk's separator (a scattered edit), in the dim tone. */ .gap { color: var(--dsw-alias-label-tertiary); } -/* The diff's own meaning-carrying colors: removed on the error token, added on - the success token. A `- `/`+ ` prefix is drawn here so a copied line and the - shown line agree, and so the sign reads without relying on color alone. */ .del::before { content: '- '; - color: var(--dsw-alias-state-error-primary); } .del { color: var(--dsw-alias-state-error-primary); + background: var(--dsw-alias-code-diff-deleted); + box-shadow: inset 3px 0 0 var(--dsw-alias-state-error-primary); } .add::before { content: '+ '; - color: var(--dsw-alias-state-success-primary); } .add { color: var(--dsw-alias-state-success-primary); + background: var(--dsw-alias-code-diff-added); + box-shadow: inset 3px 0 0 var(--dsw-alias-state-success-primary); } .context { @@ -87,9 +60,9 @@ .expand { display: block; width: 100%; - padding: 0; + padding: 0 18px; border: none; - background-color: transparent; + background: transparent; color: var(--dsw-alias-label-tertiary); cursor: pointer; font: inherit; @@ -100,10 +73,8 @@ color: var(--dsw-alias-label-secondary); } -/* The change summary, dim under the body: `└ +A -R · N file(s)`, the same - footer the TUI transcript's diff card draws. */ .footer { - padding: 0 14px 12px; + padding: 0 18px 16px; font: var(--dsw-font-markdown-code-block); color: var(--dsw-alias-label-tertiary); } diff --git a/packages/client/ui-primitives/src/DiffBlock.tsx b/packages/client/ui-primitives/src/DiffBlock.tsx index 339c4a4af1..d9acc67fff 100644 --- a/packages/client/ui-primitives/src/DiffBlock.tsx +++ b/packages/client/ui-primitives/src/DiffBlock.tsx @@ -3,6 +3,9 @@ import clsx from 'clsx' import { structuredPatch } from 'diff' import { FoldToggle } from './FoldToggle.tsx' import { writeClipboard } from './clipboard.ts' +import { CodeToolbar, type CodeToolbarLabels } from './CodeToolbar.tsx' +import { languageForPath } from './code-highlighting.ts' +import cardCss from './CodeCard.module.css' import css from './DiffBlock.module.css' /** Output lines shown before the height cap collapses the middle. */ @@ -33,7 +36,7 @@ export interface DiffBlockProps { } /** Localized chrome for {@link DiffBlock}. */ -export interface DiffBlockLabels { +export interface DiffBlockLabels extends CodeToolbarLabels { copy: string copied: string collapseAria: string @@ -174,6 +177,9 @@ export function DiffBlock({ diffs, labels, maxLines = DEFAULT_DIFF_MAX_LINES, cl const { rows, added, removed, files } = useMemo(() => buildRows(diffs), [diffs]) const [expanded, setExpanded] = useState(false) const [copied, setCopied] = useState(false) + const [wrapped, setWrapped] = useState(false) + const firstLanguage = diffs[0] === undefined ? undefined : languageForPath(diffs[0].path) + const language = diffs.every(diff => languageForPath(diff.path) === firstLanguage) ? firstLanguage : undefined const onCopy = useCallback(() => { if (copied) return @@ -198,10 +204,9 @@ export function DiffBlock({ diffs, labels, maxLines = DEFAULT_DIFF_MAX_LINES, cl const tail = capped ? rows.slice(rows.length - tailLines) : [] return ( -
- +
+ { setWrapped(value => !value) }} />
{head.map((row, index) => (
{row.text}
diff --git a/packages/client/ui-primitives/src/ReadBlock.module.css b/packages/client/ui-primitives/src/ReadBlock.module.css index 2c4cf0370d..fbff018f50 100644 --- a/packages/client/ui-primitives/src/ReadBlock.module.css +++ b/packages/client/ui-primitives/src/ReadBlock.module.css @@ -1,105 +1,41 @@ .block { - --dsl-read-radius: 12px; - --dsl-read-line-height: 22px; - /* Fixed-width gutter column for the line numbers, so the content edge stays - put down the whole window regardless of how wide the numbers grow. */ - --dsl-read-gutter: 48px; - - position: relative; - margin: 16px 0; - color: var(--dsw-alias-label-primary); - background: var(--dsw-alias-markdown-code-block); - border-radius: var(--dsl-read-radius); + --dsl-read-gutter: 3ch; } -.banner { - display: flex; - justify-content: space-between; - align-items: center; - gap: 12px; - padding: 9px 14px; - background: var(--dsw-alias-markdown-code-block-banner); - border-top-left-radius: var(--dsl-read-radius); - border-top-right-radius: var(--dsl-read-radius); -} - -.label { - min-width: 0; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - color: var(--dsw-alias-label-primary); - font-family: var(--ds-font-family-code); - font-size: 12px; - line-height: 18px; -} - -.action { - display: flex; - align-items: center; - flex-shrink: 0; - gap: 12px; -} - -.count { - color: var(--dsw-alias-label-tertiary); - font: var(--dsw-font-xs-13); -} - -.lang { - color: var(--dsw-alias-label-tertiary); - font-family: var(--ds-font-family-code); - font-size: 12px; - line-height: 18px; -} - -.copyButton { - background-color: transparent; - border: none; - padding: 0; - margin: 0; - color: var(--dsw-alias-label-secondary); - cursor: pointer; - font: var(--dsw-font-xs-13); -} - -.body { - padding: 12px 0; - font: var(--dsw-font-markdown-code-block); - overflow-x: auto; - overflow-y: hidden; -} - -/* One row per file line: a fixed gutter column, then the content. No wrapping — - a source line's leading whitespace is meaningful and scrolls sideways. */ .line { display: flex; - min-height: var(--dsl-read-line-height); - line-height: var(--dsl-read-line-height); + min-height: 1lh; white-space: pre; } .gutter { flex: none; width: var(--dsl-read-gutter); - padding-right: 14px; + margin-right: 12px; text-align: right; color: var(--dsw-alias-label-tertiary); - /* The gutter is chrome, not content: keep it out of a text selection so a - copy of the visible rows carries the source, not the line numbers. */ user-select: none; } .content { + min-width: 0; color: var(--dsw-alias-label-primary); } +.block[data-code-wrap='true'] .line { + white-space: pre-wrap; +} + +.block[data-code-wrap='true'] .content { + overflow-wrap: anywhere; +} + .expand { display: block; width: 100%; - padding: 0 0 0 var(--dsl-read-gutter); + padding: 0 0 0 calc(var(--dsl-read-gutter) + 12px); border: none; - background-color: transparent; + background: transparent; color: var(--dsw-alias-label-tertiary); cursor: pointer; font: inherit; diff --git a/packages/client/ui-primitives/src/ReadBlock.tsx b/packages/client/ui-primitives/src/ReadBlock.tsx index 6c1b2eaec9..e1493e3316 100644 --- a/packages/client/ui-primitives/src/ReadBlock.tsx +++ b/packages/client/ui-primitives/src/ReadBlock.tsx @@ -2,6 +2,8 @@ import { useCallback, useMemo, useRef, useState, useSyncExternalStore } from 're import clsx from 'clsx' import { FoldToggle } from './FoldToggle.tsx' import { writeClipboard } from './clipboard.ts' +import { CodeToolbar, type CodeToolbarLabels } from './CodeToolbar.tsx' +import cardCss from './CodeCard.module.css' import { grammarLoadCount, highlightLines, @@ -44,7 +46,7 @@ export interface ReadBlockProps { } /** Localized chrome for {@link ReadBlock}. */ -export interface ReadBlockLabels { +export interface ReadBlockLabels extends CodeToolbarLabels { window: (shown: number, total: number) => string copy: string copied: string @@ -88,6 +90,7 @@ export function ReadBlock({ ) const [expanded, setExpanded] = useState(false) const [copied, setCopied] = useState(false) + const [wrapped, setWrapped] = useState(false) const onCopy = useCallback(() => { if (copied) return @@ -120,23 +123,13 @@ export function ReadBlock({ [line, highlighted?.[index]]) return ( -
-
-
{label ?? ''}
-
- {windowed && ( - {labels.window(lines.length, totalLines)} - )} - {lang ?? ''} - {/* Empty files omit Copy to avoid replacing the clipboard with an empty string. */} - {lines.length > 0 && ( - - )} -
-
-
+
+ 0 ? onCopy : undefined} onWrap={() => { setWrapped(value => !value) }} + /> +
{rows(capped ? paired.slice(0, headLines) : paired)} {hidden > 0 && ( { if (copied) return @@ -178,21 +185,26 @@ export function CodeBlock({ ) return ( -
{/* These paired attributes are stable semantic hooks for owner styling and DOM tests. */} {showHeader &&
-
+ {toolbarLabels !== undefined ? { setWrapped(value => !value) } : undefined} + /> :
{lang ?? ''}
-
+
}
}
{body}
diff --git a/packages/client/ui-primitives/src/markdown/MarkdownText.tsx b/packages/client/ui-primitives/src/markdown/MarkdownText.tsx index ab2c0b380a..25b9a00172 100644 --- a/packages/client/ui-primitives/src/markdown/MarkdownText.tsx +++ b/packages/client/ui-primitives/src/markdown/MarkdownText.tsx @@ -172,7 +172,7 @@ class StreamingRenderer { * absolute HTTP(S) images render directly. */ export const MarkdownText = memo(function MarkdownText({ - text, streaming = false, labels, fileMentions, pathImages, variant = 'body', + text, streaming = false, labels: providedLabels, fileMentions, pathImages, variant = 'body', }: { text: string streaming?: boolean @@ -181,6 +181,9 @@ export const MarkdownText = memo(function MarkdownText({ pathImages?: MarkdownPathImages | undefined variant?: 'body' | 'compact' }) { + const labels = useMemo(() => variant === 'compact' + ? { ...providedLabels, code: { ...providedLabels.code, toolbarLabels: undefined } } + : providedLabels, [providedLabels, variant]) const streamRef = useRef(null) const streamLabelsRef = useRef(labels) const children = useMemo(() => { diff --git a/packages/client/ui-primitives/src/markdown/render.tsx b/packages/client/ui-primitives/src/markdown/render.tsx index c378dacd2a..cdf1b62ec9 100644 --- a/packages/client/ui-primitives/src/markdown/render.tsx +++ b/packages/client/ui-primitives/src/markdown/render.tsx @@ -36,6 +36,8 @@ export interface MarkdownCodeLabels { copyLabel: string /** Copy-button label during the post-copy confirmation window. */ copiedLabel: string + /** Shared card controls; omitted in compact and owner-styled source views. */ + toolbarLabels?: import('../CodeToolbar.tsx').CodeToolbarLabels | undefined } /** Localized chrome for a Markdown document. */ @@ -399,6 +401,7 @@ function renderCode(node: Md.Code, key: Key, context: MarkdownRenderContext): Re streaming={context.streaming} copyLabel={context.labels.code.copyLabel} copiedLabel={context.labels.code.copiedLabel} + toolbarLabels={context.labels.code.toolbarLabels} /> ) } diff --git a/packages/client/ui-primitives/tests/code-card-controls.client.spec.tsx b/packages/client/ui-primitives/tests/code-card-controls.client.spec.tsx new file mode 100644 index 0000000000..467aa5e833 --- /dev/null +++ b/packages/client/ui-primitives/tests/code-card-controls.client.spec.tsx @@ -0,0 +1,96 @@ +// @vitest-environment jsdom + +import { afterEach, describe, expect, it, vi } from 'vitest' +import { act, cleanup, fireEvent, render, screen } from '@testing-library/react' +import { CodeBlock } from '../src/markdown/CodeBlock.tsx' +import { MarkdownText } from '../src/markdown/MarkdownText.tsx' +import { ReadBlock } from '../src/ReadBlock.tsx' +import { DiffBlock } from '../src/DiffBlock.tsx' +import { diffBlockLabels, readBlockLabels } from './labels.client.ts' + +const toolbarLabels = { codeLabel: 'Code block', wrapLabel: 'Wrap lines', unwrapLabel: 'Do not wrap lines' } +const labels = { copyLabel: 'Copy', copiedLabel: 'Copied', toolbarLabels } + +afterEach(() => { + cleanup() + vi.clearAllTimers() + vi.useRealTimers() +}) + +describe('code-card controls', () => { + it.each([undefined, 'unregistered'])('labels the %s language with the localized code title', (lang) => { + render() + expect(screen.getByText('Code block')).toBeTruthy() + expect(screen.getByRole('button', { name: 'Copy' }).textContent).toBe('') + }) + + it('keeps a known grammar name while its highlighter is not yet visible', () => { + render() + expect(screen.getByText('typescript')).toBeTruthy() + expect(screen.queryByText('Code block')).toBeNull() + }) + + it.each(['code', 'read', 'diff'] as const)('toggles %s wrapping without changing source text', (kind) => { + const code = 'const longName = "a long value whose source must stay intact"' + const view = render(kind === 'code' + ? + : kind === 'read' + ? + : ) + const button = screen.getByRole('button', { name: kind === 'code' ? 'Do not wrap lines' : 'Wrap lines' }) + const wasWrapped = button.getAttribute('aria-pressed') === 'true' + fireEvent.click(button) + expect(button.getAttribute('aria-pressed')).toBe(String(!wasWrapped)) + expect(view.container.textContent).toContain(code) + fireEvent.click(button) + expect(button.getAttribute('aria-pressed')).toBe(String(wasWrapped)) + }) + + it('shows hover tooltips for copying and wrapping and updates the wrapping action', () => { + render() + const copy = screen.getByRole('button', { name: 'Copy' }) + fireEvent.mouseEnter(copy) + expect(screen.getByRole('tooltip').textContent).toBe('Copy') + fireEvent.mouseLeave(copy) + const wrap = screen.getByRole('button', { name: 'Do not wrap lines' }) + fireEvent.mouseEnter(wrap) + expect(screen.getByRole('tooltip').textContent).toBe('Do not wrap lines') + fireEvent.click(wrap) + expect(screen.queryByRole('tooltip')).toBeNull() + fireEvent.mouseEnter(wrap) + expect(screen.getByRole('tooltip').textContent).toBe('Wrap lines') + }) + + it('copies source through the icon and announces success', async () => { + vi.useFakeTimers() + const original = Object.getOwnPropertyDescriptor(navigator, 'clipboard') + const writeText = vi.fn<(text: string) => Promise>().mockResolvedValue() + Object.defineProperty(navigator, 'clipboard', { configurable: true, value: { writeText } }) + try { + render() + await act(async () => { fireEvent.click(screen.getByRole('button', { name: 'Copy' })) }) + expect(writeText).toHaveBeenCalledWith('const x = 1') + expect(screen.getByRole('button', { name: 'Copied' })).toBeTruthy() + } finally { + if (original === undefined) Reflect.deleteProperty(navigator, 'clipboard') + else Object.defineProperty(navigator, 'clipboard', original) + } + }) + + it('preserves compact Markdown and owner-styled source controls', () => { + const view = render() + expect(screen.queryByRole('button', { name: 'Wrap lines' })).toBeNull() + expect(screen.queryByRole('button', { name: 'Do not wrap lines' })).toBeNull() + expect(screen.getByRole('button', { name: 'Copy' }).textContent).toBe('Copy') + view.rerender() + expect(screen.getByRole('button', { name: 'Copy' }).textContent).toBe('Copy') + }) + + it('uses the fallback title for diffs containing different languages', () => { + render() + expect(screen.getByText('Code block')).toBeTruthy() + }) +}) diff --git a/packages/client/ui-primitives/tests/labels.client.ts b/packages/client/ui-primitives/tests/labels.client.ts index 7849d8e9c7..80b8cb7305 100644 --- a/packages/client/ui-primitives/tests/labels.client.ts +++ b/packages/client/ui-primitives/tests/labels.client.ts @@ -14,6 +14,7 @@ export const markdownLabels: MarkdownLabels = { } export const diffBlockLabels: DiffBlockLabels = { + codeLabel: '代码块', wrapLabel: '自动换行', unwrapLabel: '取消自动换行', copy: '复制', copied: '复制成功', collapseAria: '收起差异', expandAria: hidden => `展开其余 ${hidden} 行差异`, collapse: '收起', expand: hidden => `… 其余 ${hidden} 行`, @@ -21,6 +22,7 @@ export const diffBlockLabels: DiffBlockLabels = { } export const readBlockLabels: ReadBlockLabels = { + codeLabel: '代码块', wrapLabel: '自动换行', unwrapLabel: '取消自动换行', window: (shown, total) => `显示 ${shown} / ${total} 行`, copy: '复制', copied: '复制成功', collapseAria: '收起内容', expandAria: hidden => `展开其余 ${hidden} 行`, diff --git a/packages/client/ui-primitives/tests/read-block.client.spec.tsx b/packages/client/ui-primitives/tests/read-block.client.spec.tsx index 4ad939838d..1e3c7f95a7 100644 --- a/packages/client/ui-primitives/tests/read-block.client.spec.tsx +++ b/packages/client/ui-primitives/tests/read-block.client.spec.tsx @@ -134,10 +134,9 @@ describe('ReadBlock banner', () => { expect(view.queryByText(/显示/u)).toBeNull() }) - it('draws an empty label and empty language when neither is given', () => { - const view = render() - expect(view.container.querySelector('[class^="_label_"]')?.textContent).toBe('') - expect(view.container.querySelector('[class^="_lang_"]')?.textContent).toBe('') + it('uses the localized code title when no language is given', () => { + render() + expect(screen.getByText('代码块')).toBeTruthy() }) }) diff --git a/packages/client/ui-sidebar-documentpreview/README.i18n.yaml b/packages/client/ui-sidebar-documentpreview/README.i18n.yaml index d46092d14f..89c03993c4 100644 --- a/packages/client/ui-sidebar-documentpreview/README.i18n.yaml +++ b/packages/client/ui-sidebar-documentpreview/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-sidebar-documentpreview/README.md -README.md: 510e43fb723039b918672a58ec2bd26cf3b6023a -README.zh.md: 5bd9fba7c7f60f7f477afb82b0e88a5dd8b5ac30 +README.md: f5d664db612f67d71ce509e44981a4678845b50d +README.zh.md: 0361adcc79d13f06ba14cb3f6c6072e3f78dcf18 diff --git a/packages/client/ui-sidebar-documentpreview/README.md b/packages/client/ui-sidebar-documentpreview/README.md index 510e43fb72..f5d664db61 100644 --- a/packages/client/ui-sidebar-documentpreview/README.md +++ b/packages/client/ui-sidebar-documentpreview/README.md @@ -61,7 +61,7 @@ PNG, JPEG, GIF, WebP, BMP, ICO, and SVG render through Blob URLs in an `` s Shared copy comes from `sidebarDocumentPreview`; each builtin renderer owns its localized labels. PDF and converted Office previews use a graphite background in light mode and a matte-black background in dark mode, with subtle page shadows and original document colors. PDF and image previews share a floating control with **Fit width**, 25%, 50%, 100%, 150%, and 200% choices plus 25% incremental zoom across the 25%–400% fixed range. Fit width is the default and tracks pane resizing; 100% means the PDF's 96-DPI page size or the image's intrinsic CSS-pixel size. On fine pointers, the control starts hidden, slides up when the pointer enters the bottom 72 CSS pixels, and slides down after a 420 ms leave delay; hover, keyboard focus, an open menu, and an active gesture keep it visible, while devices without hover keep it visible continuously. Chromium maps a macOS trackpad pinch to the same live, pointer-anchored path as Ctrl+wheel; the control displays the gesture percentage, and the settled value survives body remounts until the tab closes. HTML previews do not expose zoom controls. -Initial reads, additional pages, and HTML/PDF/image preparation share the ongoing `StateDot` loader, which exposes its label to assistive technology and respects reduced-motion preferences; every wait before content exists centres the loader in the pane, so opening a file shows one indicator in one position until the body appears. Loaded pages stay visible while another page loads. The PDF body loads its package-local `client.pdf.js` chunk only when a PDF preview mounts; PDF.js, its Worker source, and embedded support data stay out of the startup `client.js`. PDF pages fill the pane's width edge to edge as one vertical sequence and render lazily near the viewport; an unrendered page holds its place as a quiet 3:4 placeholder block. PDF.js’s official TextLayerBuilder manages selection boundaries and normalized copying over an aligned text layer. Its companion styles keep blank line breaks unhighlighted; alignment accounts for PDF page units, page rotation, and viewport resizing, and page disposal cancels both layers. Image-only PDFs contain no selectable text. Code previews show source line numbers by default without including them in copied text; plain text uses the same font size and line height as code. Code sits on the pane's own background rather than the chat card's fill; its banner is adjacent to a full-height inner scrollport, so both scrollbars begin below the copy control. +Initial reads, additional pages, and HTML/PDF/image preparation share the ongoing `StateDot` loader, which exposes its label to assistive technology and respects reduced-motion preferences; every wait before content exists centres the loader in the pane, so opening a file shows one indicator in one position until the body appears. Loaded pages stay visible while another page loads. The PDF body loads its package-local `client.pdf.js` chunk only when a PDF preview mounts; PDF.js, its Worker source, and embedded support data stay out of the startup `client.js`. PDF pages fill the pane's width edge to edge as one vertical sequence and render lazily near the viewport; an unrendered page holds its place as a quiet 3:4 placeholder block. PDF.js’s official TextLayerBuilder manages selection boundaries and normalized copying over an aligned text layer. Its companion styles keep blank line breaks unhighlighted; alignment accounts for PDF page units, page rotation, and viewport resizing, and page disposal cancels both layers. Image-only PDFs contain no selectable text. Code previews show a secondary-colored language label and a copy icon with a tooltip; wrapping remains in the document toolbar. They show source line numbers by default without including them in copied text; plain text uses the same font size and line height as code. Code sits on the pane's own background rather than the chat card's fill; its banner is adjacent to a full-height inner scrollport, so both scrollbars begin below the copy control. ## Excel preview diff --git a/packages/client/ui-sidebar-documentpreview/README.zh.md b/packages/client/ui-sidebar-documentpreview/README.zh.md index 5bd9fba7c7..0361adcc79 100644 --- a/packages/client/ui-sidebar-documentpreview/README.zh.md +++ b/packages/client/ui-sidebar-documentpreview/README.zh.md @@ -61,7 +61,7 @@ PNG、JPEG、GIF、WebP、BMP、ICO 和 SVG 通过 Blob URL 在 `` 静态 共享文案来自 `sidebarDocumentPreview`;各内置渲染器拥有自己的本地化标签。PDF 与转换后的 Office 预览在浅色模式下使用石墨灰底色,在深色模式下使用哑黑底色,页面带有轻微阴影并保留文档原色。PDF 与图片预览共用浮动控件,提供**适应宽度**、25%、50%、100%、150% 和 200% 选项,并在 25%–400% 固定范围内按 25% 逐级缩放。适应宽度是默认模式并跟随面板尺寸;100% 表示 PDF 的 96 DPI 页面尺寸或图片的固有 CSS 像素尺寸。在精细指针设备上,控件初始隐藏;指针进入底部 72 个 CSS 像素时向上滑入,离开 420 ms 后向下退出;控件悬停、键盘焦点、菜单展开和手势进行期间保持显示,无 hover 的设备则始终显示。Chromium 将 macOS 触控板捏合映射到与 Ctrl+滚轮相同的实时指针锚定路径;控件同步显示手势比例,静止后的值在正文重新挂载后继续保留,直至 tab 关闭。HTML 预览不显示缩放控件。 -首次读取、追加页及 HTML/PDF/图片准备共用 ongoing `StateDot` loading,其标签暴露给辅助技术,并遵循减少动态效果偏好;内容出现前的每个等待都把 loading 居中在面板中,打开文件到正文出现始终是同一位置的一个标记。下一页加载期间保留已显示的内容。PDF 正文仅在 PDF 预览挂载时加载包内 `client.pdf.js` chunk;PDF.js、Worker 源码和内嵌支持数据不会进入启动 `client.js`。PDF 页面贴边占满面板宽度,组成一个纵向连续序列并在接近视口时惰性渲染;未渲染的页以安静的 3:4 占位块保持位置。PDF.js 官方 TextLayerBuilder 在与画面重合的文字层上管理选区边界和复制文本规范化。配套样式不高亮空白换行;对齐同时考虑 PDF 页面单位、页面旋转与视口宽度变化,页面释放时取消两层渲染。纯图片 PDF 不包含可选取的文字。代码预览默认显示源码行号,但复制文本不包含行号;纯文本与代码使用相同字号和行高。代码直接坐在分栏自身的背景上,而不是会话卡片的填充色;复制条与占满剩余高度的内部滚动区相邻,因此横纵滚动条都从复制控件下方开始。 +首次读取、追加页及 HTML/PDF/图片准备共用 ongoing `StateDot` loading,其标签暴露给辅助技术,并遵循减少动态效果偏好;内容出现前的每个等待都把 loading 居中在面板中,打开文件到正文出现始终是同一位置的一个标记。下一页加载期间保留已显示的内容。PDF 正文仅在 PDF 预览挂载时加载包内 `client.pdf.js` chunk;PDF.js、Worker 源码和内嵌支持数据不会进入启动 `client.js`。PDF 页面贴边占满面板宽度,组成一个纵向连续序列并在接近视口时惰性渲染;未渲染的页以安静的 3:4 占位块保持位置。PDF.js 官方 TextLayerBuilder 在与画面重合的文字层上管理选区边界和复制文本规范化。配套样式不高亮空白换行;对齐同时考虑 PDF 页面单位、页面旋转与视口宽度变化,页面释放时取消两层渲染。纯图片 PDF 不包含可选取的文字。代码预览使用 secondary 色的语言名称和带提示的复制图标;换行仍由文档工具栏控制。默认显示源码行号,但复制文本不包含行号;纯文本与代码使用相同字号和行高。代码直接坐在分栏自身的背景上,而不是会话卡片的填充色;复制条与占满剩余高度的内部滚动区相邻,因此横纵滚动条都从复制控件下方开始。 ## Excel 预览 diff --git a/packages/client/ui-sidebar-documentpreview/src/client/code/CodeBody.module.css b/packages/client/ui-sidebar-documentpreview/src/client/code/CodeBody.module.css index 9e284f9ce9..c430564b19 100644 --- a/packages/client/ui-sidebar-documentpreview/src/client/code/CodeBody.module.css +++ b/packages/client/ui-sidebar-documentpreview/src/client/code/CodeBody.module.css @@ -43,6 +43,7 @@ .renderer .code pre { box-sizing: border-box; + padding: 16px; min-width: 100%; overflow: visible; white-space: pre; diff --git a/packages/client/ui-sidebar-documentpreview/src/client/code/CodeBody.tsx b/packages/client/ui-sidebar-documentpreview/src/client/code/CodeBody.tsx index a643654d5b..898c0eb596 100644 --- a/packages/client/ui-sidebar-documentpreview/src/client/code/CodeBody.tsx +++ b/packages/client/ui-sidebar-documentpreview/src/client/code/CodeBody.tsx @@ -24,9 +24,11 @@ export function CodeBody({ resourceAddress, content, wrap, scrollportRef, t }: C code={content.text} lang={language} streaming={!content.eof} + wrap={wrap} lineNumbers copyLabel={t('copy')} copiedLabel={t('copied')} + toolbarLabels={{ codeLabel: t('codeBlock.title'), wrapLabel: t('codeBlock.wrap'), unwrapLabel: t('codeBlock.unwrap') }} />
) diff --git a/packages/client/ui-sidebar-documentpreview/src/client/markdown/MarkdownBody.tsx b/packages/client/ui-sidebar-documentpreview/src/client/markdown/MarkdownBody.tsx index f6164af6f3..27c672c60e 100644 --- a/packages/client/ui-sidebar-documentpreview/src/client/markdown/MarkdownBody.tsx +++ b/packages/client/ui-sidebar-documentpreview/src/client/markdown/MarkdownBody.tsx @@ -24,9 +24,12 @@ export function MarkdownBody({ content, resourceAddress, useResource, t }: Markd const copyLabel = t('code.copy') const copiedLabel = t('code.copied') const footnotes = t('footnotes') + const codeLabel = t('codeBlock.title') + const wrapLabel = t('codeBlock.wrap') + const unwrapLabel = t('codeBlock.unwrap') const labels = useMemo(() => ({ - code: { copyLabel, copiedLabel }, footnotes, - }), [copyLabel, copiedLabel, footnotes]) + code: { copyLabel, copiedLabel, toolbarLabels: { codeLabel, wrapLabel, unwrapLabel } }, footnotes, + }), [copyLabel, copiedLabel, footnotes, codeLabel, wrapLabel, unwrapLabel]) if (content.kind !== 'text') return null return (
diff --git a/packages/client/ui-sidebar-documentpreview/tests/code-body.client.spec.tsx b/packages/client/ui-sidebar-documentpreview/tests/code-body.client.spec.tsx index c2b3f0daae..ce8e6b548f 100644 --- a/packages/client/ui-sidebar-documentpreview/tests/code-body.client.spec.tsx +++ b/packages/client/ui-sidebar-documentpreview/tests/code-body.client.spec.tsx @@ -4,7 +4,7 @@ import { readFileSync } from 'node:fs' import { dirname, resolve } from 'node:path' import { fileURLToPath } from 'node:url' import { afterEach, describe, expect, it } from 'vitest' -import { cleanup, render, waitFor } from '@testing-library/react' +import { cleanup, fireEvent, render, waitFor } from '@testing-library/react' import type { SessionId } from '@deepseek-ai/dsh-session/types' import { absoluteFileAddress, sessionFileAddress } from '@deepseek-ai/dsh-util-workspace-path' import { CodeBody } from '../src/client/code/CodeBody.tsx' @@ -84,7 +84,11 @@ describe('CodeBody', () => { expect(view.getByText(language, { exact: true })).toBeTruthy() expect(element(view.container, '.shiki').textContent).toBe('const answer = 42') expect(view.container.querySelector('[data-line-numbers]')).not.toBeNull() - expect(view.getByRole('button', { name: 'Copy' })).toBeTruthy() + const copy = view.getByRole('button', { name: 'Copy' }) + expect(copy.textContent).toBe('') + expect(view.getAllByRole('button')).toHaveLength(1) + fireEvent.mouseEnter(copy) + expect(view.getByRole('tooltip').textContent).toBe('Copy') }) it('carries multiline grammar state across pages and preserves completed lines through settlement', () => { @@ -155,6 +159,7 @@ describe('CodeBody', () => { const view = render() const pre = element(view.container, '.shiki') const block = element(view.container, '.md-code-block') + expect(block.getAttribute('data-code-wrap')).toBe('false') const scrollport = element(view.container, '[data-code-block-content]') expect(getComputedStyle(block).marginTop).toBe('0px') expect(getComputedStyle(block).position).toBe('static') @@ -165,6 +170,8 @@ describe('CodeBody', () => { expect(getComputedStyle(pre).overflow).toBe('visible') expect(getComputedStyle(pre).wordBreak).toBe('normal') view.rerender() + expect(block.getAttribute('data-code-wrap')).toBe('true') + expect(view.getAllByRole('button')).toHaveLength(1) expect(element(view.container, '.shiki')).toBe(pre) expect(element(view.container, '[data-code-block-content]')).toBe(scrollport) expect(getComputedStyle(pre).whiteSpace).toBe('pre-wrap') diff --git a/packages/client/ui-theme/src/styles/shiki.css b/packages/client/ui-theme/src/styles/shiki.css index c7a3c5d272..f969d1b264 100644 --- a/packages/client/ui-theme/src/styles/shiki.css +++ b/packages/client/ui-theme/src/styles/shiki.css @@ -4,6 +4,11 @@ cascade as every other token sheet. Background/foreground deliberately alias the markdown code-block tokens so highlighted and plain blocks agree. */ +body { + --dsw-alias-code-diff-added: color-mix(in srgb, var(--dsw-alias-state-success-primary) 8%, transparent); + --dsw-alias-code-diff-deleted: color-mix(in srgb, var(--dsw-alias-state-error-primary) 8%, transparent); +} + :root { --shiki-foreground: var(--dsw-alias-label-primary); --shiki-background: var(--dsw-alias-markdown-code-block); @@ -19,6 +24,8 @@ } body[data-ds-dark-theme] { + --dsw-alias-code-diff-added: color-mix(in srgb, var(--dsw-alias-state-success-primary) 12%, transparent); + --dsw-alias-code-diff-deleted: color-mix(in srgb, var(--dsw-alias-state-error-primary) 12%, transparent); --shiki-token-constant: #4dabf7; --shiki-token-string: #69db7c; --shiki-token-comment: #adb5bd; diff --git a/packages/client/ui-tool/src/client/tool/components/ToolDetails.module.css b/packages/client/ui-tool/src/client/tool/components/ToolDetails.module.css index 824bd18fde..c813c772cc 100644 --- a/packages/client/ui-tool/src/client/tool/components/ToolDetails.module.css +++ b/packages/client/ui-tool/src/client/tool/components/ToolDetails.module.css @@ -232,15 +232,13 @@ overflow: auto; } +.root .item:has(> .code:only-child) { padding: 0; } +.root .item > .code:only-child { margin: 0; } + .root .group .item:has(> .code:only-child) { padding: 4px 0 0 20px; } -.root .group .item > .code:only-child { margin: 0; } - -.root .code [data-code-block-banner] { padding: 4px 10px; } -.root .code pre { padding: 6px 10px 8px; } - .path { flex: 1; min-width: 0; diff --git a/packages/client/ui-tool/src/client/tool/components/ToolDetails.tsx b/packages/client/ui-tool/src/client/tool/components/ToolDetails.tsx index 801be3c7a0..618d998ce3 100644 --- a/packages/client/ui-tool/src/client/tool/components/ToolDetails.tsx +++ b/packages/client/ui-tool/src/client/tool/components/ToolDetails.tsx @@ -4,7 +4,7 @@ import { } from '@deepseek-ai/dsh-client-ui-primitives' import type { TranslateNS } from '@deepseek-ai/dsh-client-ui-slots' import type { OpenFileOptions } from '@deepseek-ai/dsh-client-ui-chat/client' -import { markdownLabels } from '../models/primitive-labels.ts' +import { codeToolbarLabels, markdownLabels } from '../models/primitive-labels.ts' import css from './ToolDetails.module.css' /** One recorded entity, receipt, or collapsible group of related values. */ @@ -89,6 +89,7 @@ function DetailItem({ item, t, onOpenFile }: { item: ToolDetailItem } & DetailCo {item.markdown !== undefined &&
} {item.code !== undefined && ( diff --git a/packages/client/ui-tool/src/client/tool/components/ToolRow.module.css b/packages/client/ui-tool/src/client/tool/components/ToolRow.module.css index 1478b06961..5e54eeb7e5 100644 --- a/packages/client/ui-tool/src/client/tool/components/ToolRow.module.css +++ b/packages/client/ui-tool/src/client/tool/components/ToolRow.module.css @@ -324,12 +324,6 @@ color: var(--dsw-alias-label-tertiary); } -/* In-row code renders at the smaller code size (12/18) via each primitive's - rebindable content-font seam; standalone markdown code blocks keep 13/22. */ -.codeBody { - --dsl-code-block-content-font: var(--dsw-font-markdown-code-block-small); -} - /* The terminal card scrolls its OUTPUT inside its own surface (same l1 hairline as the IN/OUT card): the banner stays pinned and the scrollbar never rides over it. 224px = the 260px card cap minus the ~36px banner. */ diff --git a/packages/client/ui-tool/src/client/tool/components/ToolRow.tsx b/packages/client/ui-tool/src/client/tool/components/ToolRow.tsx index 62b91189fc..76fc93d13d 100644 --- a/packages/client/ui-tool/src/client/tool/components/ToolRow.tsx +++ b/packages/client/ui-tool/src/client/tool/components/ToolRow.tsx @@ -16,7 +16,7 @@ import { localizeTerminalCardModel, terminalBlockLabels, type TerminalCardModel, } from '../models/terminal-card-model.ts' import { - diffBlockLabels, readBlockLabels, searchBlockLabels, webBlockLabels, + codeToolbarLabels, diffBlockLabels, readBlockLabels, searchBlockLabels, webBlockLabels, } from '../models/primitive-labels.ts' import type { AskQuestionCardModel } from '../models/ask-question-card-model.ts' import { @@ -289,7 +289,8 @@ export const ToolRow = memo(function ToolRow({ <> {variant === 'code' && bodyText !== null && (
- +
)} {(cardBody !== null || outputText !== null) && ( diff --git a/packages/client/ui-tool/src/client/tool/models/primitive-labels.ts b/packages/client/ui-tool/src/client/tool/models/primitive-labels.ts index 4b48cf4f8e..156a1f3c21 100644 --- a/packages/client/ui-tool/src/client/tool/models/primitive-labels.ts +++ b/packages/client/ui-tool/src/client/tool/models/primitive-labels.ts @@ -1,6 +1,7 @@ /** Localized copy adapters for Cordis-free UI primitives used by Tool cards. */ import type { + CodeBlockProps, DiffBlockLabels, MarkdownLabels, ReadBlockLabels, @@ -11,6 +12,15 @@ import type { TranslateNS } from '@deepseek-ai/dsh-client-ui-slots' type T = TranslateNS<'conversation'> +/** + * Localize the shared code-card toolbar. + * @param t - Conversation locale seat. + * @returns Language fallback and wrapping actions. + */ +export function codeToolbarLabels(t: T): NonNullable { + return { codeLabel: t('codeBlock.title'), wrapLabel: t('codeBlock.wrap'), unwrapLabel: t('codeBlock.unwrap') } +} + /** * Build localized Markdown chrome labels. * @param t - Conversation locale seat. @@ -18,7 +28,7 @@ type T = TranslateNS<'conversation'> */ export function markdownLabels(t: T): MarkdownLabels { return { - code: { copyLabel: t('copy'), copiedLabel: t('copied') }, + code: { copyLabel: t('copy'), copiedLabel: t('copied'), toolbarLabels: codeToolbarLabels(t) }, footnotes: t('markdown.footnotes'), } } @@ -30,6 +40,7 @@ export function markdownLabels(t: T): MarkdownLabels { */ export function diffBlockLabels(t: T): DiffBlockLabels { return { + ...codeToolbarLabels(t), copy: t('copy'), copied: t('copied'), collapseAria: t('diff.collapseAria'), @@ -47,6 +58,7 @@ export function diffBlockLabels(t: T): DiffBlockLabels { */ export function readBlockLabels(t: T): ReadBlockLabels { return { + ...codeToolbarLabels(t), window: (shown, total) => t('read.window', { shown, total }), copy: t('copy'), copied: t('copied'), diff --git a/packages/client/ui-tool/tests/diff-card.client.spec.tsx b/packages/client/ui-tool/tests/diff-card.client.spec.tsx index d7e37d6962..57233ea381 100644 --- a/packages/client/ui-tool/tests/diff-card.client.spec.tsx +++ b/packages/client/ui-tool/tests/diff-card.client.spec.tsx @@ -224,7 +224,7 @@ describe('FileMutationRow diff card', () => { toggleRow(view) expect(view.container.querySelector('[data-diff]')).not.toBeNull() expect(view.getByText('hello fixture')).toBeTruthy() - expect(view.getByText('复制')).toBeTruthy() + expect(view.getByRole('button', { name: '复制' })).toBeTruthy() }) it('the summary is a path link that opens the tool path through the host', () => { diff --git a/packages/client/ui-user-questions/src/client/QuestionComposer.tsx b/packages/client/ui-user-questions/src/client/QuestionComposer.tsx index 4b99d20991..4068deb520 100644 --- a/packages/client/ui-user-questions/src/client/QuestionComposer.tsx +++ b/packages/client/ui-user-questions/src/client/QuestionComposer.tsx @@ -131,7 +131,7 @@ type QuestionFlowProps = function QuestionFlow({ pending, t, useStore, actions }: QuestionFlowProps) { const questions = pending.questions const markdownLabels = useMemo(() => ({ - code: { copyLabel: t('copy'), copiedLabel: t('copied') }, + code: { copyLabel: t('copy'), copiedLabel: t('copied'), toolbarLabels: { codeLabel: t('codeBlock.title'), wrapLabel: t('codeBlock.wrap'), unwrapLabel: t('codeBlock.unwrap') } }, footnotes: t('markdown.footnotes'), }), [t]) const initialProgress = useMemo(() => ({ diff --git a/packages/extensions/ui-cordis/src/client/CordisDefineRow.tsx b/packages/extensions/ui-cordis/src/client/CordisDefineRow.tsx index 0c0806a1ef..b36b62b599 100644 --- a/packages/extensions/ui-cordis/src/client/CordisDefineRow.tsx +++ b/packages/extensions/ui-cordis/src/client/CordisDefineRow.tsx @@ -134,6 +134,7 @@ export function CordisDefineRow({ aria-labelledby={`${sourcePanelId}-${activeSource}`} > Date: Mon, 21 Sep 2026 22:40:55 +0800 Subject: [PATCH 04/29] fix(web): cover code-card overflow and refresh browser expectations --- apps/web/tests/code-card-layout.e2e.ts | 160 ++++++++++++++++++ .../clickable-links-gallery/ui.expected.md | 2 +- .../expected/cordis-history/ui.expected.md | 1 + .../navigation-panes/code-card.expected.md | 2 +- apps/web/tests/navigation-panes.e2e.ts | 6 +- .../mid-stream.expected.md | 1 + .../tests/streaming-fence-highlight.e2e.ts | 2 +- apps/web/tsconfig.json | 1 + .../client/ui-primitives/README.i18n.yaml | 4 +- packages/client/ui-primitives/README.md | 2 +- packages/client/ui-primitives/README.zh.md | 2 +- .../client/ui-primitives/src/CodeToolbar.tsx | 2 +- .../ui-primitives/src/DiffBlock.module.css | 6 + .../ui-primitives/src/ReadBlock.module.css | 4 - .../client/ui-primitives/src/ReadBlock.tsx | 8 +- packages/client/ui-primitives/src/index.ts | 1 + .../src/markdown/CodeBlock.module.css | 4 - .../ui-primitives/src/markdown/render.tsx | 3 +- .../tests/code-card-controls.client.spec.tsx | 5 +- packages/client/ui-theme/README.i18n.yaml | 4 +- packages/client/ui-theme/README.md | 2 +- packages/client/ui-theme/README.zh.md | 2 +- .../ui-theme/src/styles/design-platform.css | 12 ++ packages/client/ui-theme/src/styles/shiki.css | 7 - .../client/tool/models/primitive-labels.ts | 4 +- snapshots/web/diff-bounded/ui.expected.md | 2 + snapshots/web/diff-context/ui.expected.md | 2 + .../ui-expanded.expected.md | 14 +- .../goal-multi-turn-actions/ui.expected.md | 10 +- snapshots/web/tool-details/ui.expected.md | 14 +- tsconfig.host.json | 1 + 31 files changed, 248 insertions(+), 42 deletions(-) create mode 100644 apps/web/tests/code-card-layout.e2e.ts diff --git a/apps/web/tests/code-card-layout.e2e.ts b/apps/web/tests/code-card-layout.e2e.ts new file mode 100644 index 0000000000..172d2d2ec9 --- /dev/null +++ b/apps/web/tests/code-card-layout.e2e.ts @@ -0,0 +1,160 @@ +/** Browser geometry for read offsets and horizontally scrolled diff fills. */ +import type { Browser, Page } from 'playwright' +import { chromium } from 'playwright' +import { afterAll, beforeAll, describe, expect, it, onTestFailed } from 'vitest' +import { ToolCallId, createAssistantMessage, createToolResultMessage, createUserMessage } from '@deepseek-ai/dsh-llm' +import { SESSION_FORMAT_VERSION, Session, SessionId } from '@deepseek-ai/dsh-session' +import type { JsonValue } from '@deepseek-ai/dsh-util-values' +import { launchWebScaffold, seedSession, watchConsole, type WebScaffold } from './scaffold.ts' +import { expandTurnProcesses, newEnglishPage, saveFailureShot } from './support.ts' + +const LONG_LINE = 'source_columns_'.repeat(80) +const OFFSETS = [999, 99_999] + +/** Seed durable tool results without invoking a model or allocating a large file. */ +function layoutFixture(): string { + const calls: { name: string; args: Record; result: string; meta: JsonValue }[] = OFFSETS.map((offset) => { + const path = `offset-${offset}.txt` + const lines = [{ number: offset, text: 'short' }, { number: offset + 1, text: LONG_LINE }] + return { + name: 'read', args: { file_path: path, offset }, + result: `${path}\nfile\n\n${lines.map(line => `${line.number}: ${line.text}`).join('\n')}\n`, + meta: { path, offset, lines, totalLines: offset + 2 }, + } + }) + const oldText = `old_${LONG_LINE}\nshort old` + const newText = `new_${LONG_LINE}\nshort new` + calls.push({ + name: 'edit', args: { file_path: 'long.txt', old_string: oldText, new_string: newText }, + result: 'Edited long.txt', meta: { diffs: [{ path: 'long.txt', oldText, newText }] }, + }) + const session = Session.create(SessionId('code-card-layout-source')) + session.append('turn/start', { turn: 1 }) + session.append('user/message', createUserMessage({ + content: [{ type: 'text', text: 'Inspect the source windows and edit the long lines.' }], source: { kind: 'user' }, + }), { surfaceOp: 'append' }) + session.append('step/start', { turn: 1, step: 1 }) + const namedCalls = calls.map((call, index) => ({ ...call, id: ToolCallId(`layout-${index}`), arguments: JSON.stringify(call.args) })) + session.append('assistant/message', { + stream: [], turn: 1, step: 1, + message: createAssistantMessage({ + content: namedCalls.map(call => ({ type: 'tool-call', id: call.id, name: call.name, arguments: call.arguments })), + source: { provider: 'fixture', model: 'fixture' }, + }), + }, { surfaceOp: 'append' }) + for (const call of namedCalls) { + const source = session.append('tool/call', { turn: 1, step: 1, callId: call.id, name: call.name, arguments: call.arguments }) + session.append('tool/result', { + turn: 1, step: 1, meta: call.meta, + message: createToolResultMessage({ callId: call.id, content: [{ type: 'text', text: call.result }], isError: false }), + }, { surfaceOp: 'append', sourceEventSeqs: [source.seq] }) + } + session.append('step/end', { turn: 1, step: 1 }) + session.append('step/start', { turn: 1, step: 2 }) + session.append('assistant/message', { + stream: [], turn: 1, step: 2, + message: createAssistantMessage({ + content: [{ type: 'text', text: 'CODE_LAYOUT_DONE' }], source: { provider: 'fixture', model: 'fixture' }, + }), + }, { surfaceOp: 'append' }) + session.append('step/end', { turn: 1, step: 2 }) + session.append('turn/end', { turn: 1, reason: { kind: 'completed' } }) + return [ + JSON.stringify({ type: 'session', version: SESSION_FORMAT_VERSION, id: '{{sessionId}}', createdAt: 0, cwd: '{{cwd}}', isSeeded: false, delegationDepth: 0 }), + ...session.snapshotEvents().map(event => JSON.stringify(event)), '', + ].join('\n') +} + +describe('web e2e: code-card layout', () => { + let scaffold: WebScaffold + let browser: Browser + let page: Page + let tripwire: ReturnType + + beforeAll(async () => { + scaffold = await launchWebScaffold({}) + await seedSession(scaffold, layoutFixture(), 'code-card-layout') + browser = await chromium.launch() + page = await newEnglishPage(browser) + tripwire = watchConsole(page) + await page.goto(scaffold.authenticatedUrl, { waitUntil: 'load' }) + await page.locator('[role="treeitem"]').first().click() + await page.locator('[role="treeitem"]').nth(1).click() + await page.getByText('CODE_LAYOUT_DONE', { exact: true }).waitFor() + await expandTurnProcesses(page) + for (const row of await page.locator('[data-variant="read"], [data-variant="edit"]').all()) { + await row.locator('[data-expandable]').click() + } + await page.locator('[data-read]').nth(1).waitFor() + await page.locator('[data-diff]').waitFor() + }) + + afterAll(async () => { + try { await browser?.close() } finally { await scaffold?.close() } + }) + + it.each(OFFSETS)('keeps offset %i line numbers clear of aligned source in both wrap modes', async (offset) => { + onTestFailed(() => saveFailureShot(page, `code-card-offset-${offset}`)) + const card = page.locator('[data-read]').filter({ hasText: `offset-${offset}.txt` }) + const wrap = card.getByRole('button', { name: 'Wrap lines', exact: true }) + const heights: number[] = [] + for (const wrapped of [false, true]) { + if (wrapped) await wrap.click() + expect(await wrap.getAttribute('aria-pressed')).toBe(String(wrapped)) + const rows = await card.locator('[class*="gutter"]').evaluateAll(gutters => gutters.map((gutter) => { + const content = gutter.nextElementSibling! + const range = document.createRange() + range.selectNodeContents(gutter) + const glyphs = range.getBoundingClientRect() + const slot = gutter.getBoundingClientRect() + const source = content.getBoundingClientRect() + return { + fits: glyphs.left >= slot.left - 1 && glyphs.right <= slot.right + 1, + gap: source.left - glyphs.right, left: source.left, height: source.height, + } + })) + expect(rows).toHaveLength(2) + expect(rows.every(row => row.fits && row.gap >= 11)).toBe(true) + expect(rows[0]!.left).toBe(rows[1]!.left) + heights.push(rows[1]!.height) + } + expect(heights[1]!).toBeGreaterThan(heights[0]!) + await wrap.click() + }) + + it.each([false, true])('fills long diff rows through horizontal scrolling with dark=%s', async (dark) => { + onTestFailed(() => saveFailureShot(page, `code-card-diff-${dark}`)) + await page.evaluate(value => document.body.toggleAttribute('data-ds-dark-theme', value), dark) + const card = page.locator('[data-diff]') + const body = card.locator(':scope > div').nth(1) + const wrap = card.getByRole('button', { name: 'Wrap lines', exact: true }) + for (const wrapped of [false, true]) { + if (wrapped) await wrap.click() + const result = await body.evaluate((element) => { + element.scrollLeft = element.scrollWidth + const viewport = element.getBoundingClientRect() + const rows = [...element.children].filter(row => ['+ ', '- '].includes(getComputedStyle(row, '::before').content.replaceAll('"', ''))) + return { + overflow: element.scrollWidth - element.clientWidth, + fills: rows.map(row => ({ + width: row.getBoundingClientRect().width, right: row.getBoundingClientRect().right, + fill: getComputedStyle(row).backgroundColor, marker: getComputedStyle(row).boxShadow, + })), + scrollWidth: element.scrollWidth, right: viewport.right, + } + }) + expect(result.fills).toHaveLength(4) + if (wrapped) expect(result.overflow).toBeLessThanOrEqual(1) + else expect(result.overflow).toBeGreaterThan(100) + for (const row of result.fills) { + expect(row.width).toBeGreaterThanOrEqual(result.scrollWidth - 1) + expect(row.right).toBeGreaterThanOrEqual(result.right - 1) + expect(row.fill).toMatch(dark ? /0\.12\)$/ : /0\.08\)$/) + expect(row.marker).toContain('inset') + } + } + await wrap.click() + expect(tripwire.pageErrors).toEqual([]) + expect(tripwire.warnings).toEqual([]) + }) +}) diff --git a/apps/web/tests/expected/clickable-links-gallery/ui.expected.md b/apps/web/tests/expected/clickable-links-gallery/ui.expected.md index feaeaa2468..dea186cddd 100644 --- a/apps/web/tests/expected/clickable-links-gallery/ui.expected.md +++ b/apps/web/tests/expected/clickable-links-gallery/ui.expected.md @@ -137,7 +137,7 @@ - paragraph: - img "Token preview" - text: css -- button "Do not wrap lines" [pressed] +- button "Wrap lines" [pressed] - button "Copy" - code: "--inline-code: #F5F5F5;" - paragraph: LINK_GALLERY_DONE diff --git a/apps/web/tests/expected/cordis-history/ui.expected.md b/apps/web/tests/expected/cordis-history/ui.expected.md index 1b37b0484f..d492597420 100644 --- a/apps/web/tests/expected/cordis-history/ui.expected.md +++ b/apps/web/tests/expected/cordis-history/ui.expected.md @@ -22,6 +22,7 @@ - tab "Host" [selected] - tabpanel "Host": - text: javascript + - button "Wrap lines" [pressed] - button "Copy" - code: "return { name: \"snapshot-noop\", apply(ctx) {} }" - text: Result Defined snap-1/pkg-1 (snapshot noop); it is not running yet. Use cordis_run to activate this Package. Run controls live in the Cordis panel above Settings diff --git a/apps/web/tests/expected/navigation-panes/code-card.expected.md b/apps/web/tests/expected/navigation-panes/code-card.expected.md index 3e48942224..20b377502a 100644 --- a/apps/web/tests/expected/navigation-panes/code-card.expected.md +++ b/apps/web/tests/expected/navigation-panes/code-card.expected.md @@ -1,4 +1,4 @@ - text: Code block -- button "Do not wrap lines" [pressed] +- button "Wrap lines" [pressed] - button "Copy" - code: echo WATERFALL diff --git a/apps/web/tests/navigation-panes.e2e.ts b/apps/web/tests/navigation-panes.e2e.ts index f43b020a60..2aaaaf5d0a 100644 --- a/apps/web/tests/navigation-panes.e2e.ts +++ b/apps/web/tests/navigation-panes.e2e.ts @@ -27,7 +27,8 @@ const TRAJECTORY_EXPECTED = join(SNAPSHOT_DIR, 'trajectory.expected.md') const TIMING_EXPECTED = join(SNAPSHOT_DIR, 'timing.expected.md') const SEARCH_EXPECTED = join(SNAPSHOT_DIR, 'search-results.expected.md') const TERMINAL_EXPECTED = join(SNAPSHOT_DIR, 'terminal-card.expected.md') -const CODE_CARD_EXPECTED = fileURLToPath(new URL('./expected/navigation-panes/code-card.expected.md', import.meta.url)) +const CODE_CARD_DIR = fileURLToPath(new URL('./expected/navigation-panes', import.meta.url)) +const CODE_CARD_EXPECTED = join(CODE_CARD_DIR, 'code-card.expected.md') const MODE = webSnapshotMode() const SEED_ID = 'navigation-panes-web-e2e' const EXPORTED_LOG_FILE = `session.v${SESSION_FORMAT_VERSION}.jsonl` @@ -231,7 +232,7 @@ describe('web e2e: navigation & panes over a rich seeded session', () => { const copy = block.getByRole('button', { name: 'Copy', exact: true }) await copy.hover() await page.getByRole('tooltip', { name: 'Copy', exact: true }).waitFor() - const unwrap = block.getByRole('button', { name: 'Do not wrap lines', exact: true }) + const unwrap = block.getByRole('button', { name: 'Wrap lines', exact: true }) await unwrap.hover() await page.getByRole('tooltip', { name: 'Do not wrap lines', exact: true }).waitFor() await unwrap.click() @@ -544,6 +545,7 @@ describe('web e2e: navigation & panes over a rich seeded session', () => { }, 60_000) it.skipIf(MODE === 'record')('keeps the recorded fixture inventory exact', async () => { + await assertFixtureInventory(CODE_CARD_DIR, ['code-card.expected.md']) await assertFixtureInventory(SNAPSHOT_DIR, [ 'session.v3.jsonl', 'search-results.expected.md', 'trajectory.expected.md', 'terminal-card.expected.md', 'timing.expected.md', diff --git a/apps/web/tests/snapshots/streaming-fence-highlight/mid-stream.expected.md b/apps/web/tests/snapshots/streaming-fence-highlight/mid-stream.expected.md index 19c2becc76..87f67da186 100644 --- a/apps/web/tests/snapshots/streaming-fence-highlight/mid-stream.expected.md +++ b/apps/web/tests/snapshots/streaming-fence-highlight/mid-stream.expected.md @@ -10,6 +10,7 @@ - button "Copy" - button "Context injection runtime-context" - text: ts +- button "Wrap lines" [pressed] - button "Copy" - code: "const first: number = 1 const second = \"two\" let tail" - status: Deep diving... diff --git a/apps/web/tests/streaming-fence-highlight.e2e.ts b/apps/web/tests/streaming-fence-highlight.e2e.ts index 6d65cdca0d..48017c982d 100644 --- a/apps/web/tests/streaming-fence-highlight.e2e.ts +++ b/apps/web/tests/streaming-fence-highlight.e2e.ts @@ -85,7 +85,7 @@ async function fenceTree(block: ReturnType): Promise const pre = element.querySelector('pre.shiki') if (pre === null) throw new Error('streaming fence did not render through the shiki arm') return { - language: element.querySelector('[class*="infostring"]')?.textContent ?? '', + language: element.querySelector('[data-code-block-banner] [class*="language"]')?.textContent ?? '', pre: { className: pre.className, style: pre.style.cssText, diff --git a/apps/web/tsconfig.json b/apps/web/tsconfig.json index 9af71ce894..e7cc7396eb 100644 --- a/apps/web/tsconfig.json +++ b/apps/web/tsconfig.json @@ -24,6 +24,7 @@ "exclude": [ "tests/default-product-isolation.e2e.ts", "tests/diff-context.e2e.ts", + "tests/code-card-layout.e2e.ts", "tests/scaffold.ts", "tests/voice-input.e2e.ts", "tests/voice-setup.e2e.ts", diff --git a/packages/client/ui-primitives/README.i18n.yaml b/packages/client/ui-primitives/README.i18n.yaml index c14c318535..6f7cab38b8 100644 --- a/packages/client/ui-primitives/README.i18n.yaml +++ b/packages/client/ui-primitives/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-primitives/README.md -README.md: 069aea78dd08175a9ebb1e590bb03e97dc08daab -README.zh.md: d235e19a9f9c829d4d5d6587fdd147fda9a2884e +README.md: 09eab3840b7cfea7f84d12688787f6bd0344efc0 +README.zh.md: c5e46728f9ae8dfe33dc3e67812602ecc6d58af0 diff --git a/packages/client/ui-primitives/README.md b/packages/client/ui-primitives/README.md index 069aea78dd..09eab3840b 100644 --- a/packages/client/ui-primitives/README.md +++ b/packages/client/ui-primitives/README.md @@ -87,7 +87,7 @@ The nearest `MarkdownDelegateProvider` supplies optional `openExternalLink` and `MarkdownText` defaults to `variant="body"`. Use `variant="compact"` for secondary content: its 13px text and 20px line height follow the content-size setting, all heading levels use the same size with weight 600, and paragraphs and lists use tighter spacing. Text, links, and code keep the tertiary color; dotted underlines distinguish links. Code headers scroll with their blocks. Tables and math stay enabled at the surrounding text size and scroll horizontally within the available width. Both variants share the parser and streaming cache. -`CodeBlock.toolbarLabels` enables the shared code-card header and spacing. `ReadBlock` and `DiffBlock` use the same header: secondary-colored language text, copy and wrap icons, and hover or keyboard-focus tooltips. Missing or unsupported languages use the owner’s localized code-block title; mixed-language diffs use that title too. Code cards share typography and content insets. Wrapping is local to each mounted card and never changes copied text; code fences start wrapped, while reads and diffs preserve source columns until wrapping is enabled. Compact Markdown omits this toolbar. With `toolbarLabels`, source previews can pass `wrap` to follow their owner’s preference and show only the language and copy icon; owner CSS retains the source layout. +`CodeBlock.toolbarLabels` enables the shared code-card header and spacing. `ReadBlock` and `DiffBlock` use the same header: secondary-colored language text, copy and wrap icons, and hover or keyboard-focus tooltips. Missing or unsupported languages use the owner’s localized code-block title; mixed-language diffs use that title too. Code cards share typography and content insets. Read gutters fit the largest returned line number, and diff fills cover the full scrollable row. The wrap toggle keeps a fixed accessible name and exposes its state through `aria-pressed`; its tooltip describes the next action. Wrapping is local to each mounted card and never changes copied text; code fences start wrapped, while reads and diffs preserve source columns until wrapping is enabled. Compact Markdown omits this toolbar. With `toolbarLabels`, source previews can pass `wrap` to follow their owner’s preference and show only the language and copy icon; owner CSS retains the source layout. `DiffBlock` compares the old and new content by line. It shows actual additions and deletions with up to three neutral context lines on each side, separates distant changes with `⋯`, and excludes shared context from both summary and footer totals. Search stops beyond 256 line additions/deletions per fragment; those fragments display and count the complete old and new contents as a coarse replacement, including shared lines. Copy includes the full displayed diff with its prefixes. A final newline is treated as a terminator; differences only in the presence of a final newline are not displayed. diff --git a/packages/client/ui-primitives/README.zh.md b/packages/client/ui-primitives/README.zh.md index d235e19a9f..c5e46728f9 100644 --- a/packages/client/ui-primitives/README.zh.md +++ b/packages/client/ui-primitives/README.zh.md @@ -87,7 +87,7 @@ kind: "package-library" `MarkdownText` 默认为 `variant="body"`。次级内容使用 `variant="compact"`:其 13px 字号与 20px 行高跟随内容字号设置,各级标题保持同一字号并使用 600 字重,段落与列表采用更紧凑的间距。正文、链接和代码均保持 tertiary 颜色,以点状下划线区分链接。代码标题栏随代码块滚动。表格和公式仍然启用,使用周围文字的字号,并在可用宽度内横向滚动。两个变体共享解析器与流式缓存。 -`CodeBlock.toolbarLabels` 启用共享代码卡片的标题栏和间距。`ReadBlock` 与 `DiffBlock` 使用相同的标题栏:secondary 色的语言名称、复制与换行图标,以及悬停或键盘聚焦时的提示。语言缺失或不受支持时显示调用方提供的本地化代码块标题;混合语言的 Diff 也使用该标题。代码卡片共用字体和内容内边距。换行设置仅属于当前挂载的卡片,不改变复制的文本;代码围栏默认换行,读取和差异卡片则在启用换行前保留源码列位置。紧凑 Markdown 不使用此工具栏。源码预览传入 `toolbarLabels` 后,可用 `wrap` 跟随所属视图的换行设置,仅显示语言和复制图标;所属视图的 CSS 保留源码布局。 +`CodeBlock.toolbarLabels` 启用共享代码卡片的标题栏和间距。`ReadBlock` 与 `DiffBlock` 使用相同的标题栏:secondary 色的语言名称、复制与换行图标,以及悬停或键盘聚焦时的提示。语言缺失或不受支持时显示调用方提供的本地化代码块标题;混合语言的 Diff 也使用该标题。代码卡片共用字体和内容内边距。读取卡片的行号栏容纳返回窗口中的最大行号,Diff 底色覆盖完整可滚动行。换行按钮保留固定的无障碍名称,以 `aria-pressed` 表达状态;提示文本说明下一步操作。换行设置仅属于当前挂载的卡片,不改变复制的文本;代码围栏默认换行,读取和差异卡片则在启用换行前保留源码列位置。紧凑 Markdown 不使用此工具栏。源码预览传入 `toolbarLabels` 后,可用 `wrap` 跟随所属视图的换行设置,仅显示语言和复制图标;所属视图的 CSS 保留源码布局。 `DiffBlock` 按行比较新旧内容。它显示实际增删行及两侧最多三行中性上下文,用 `⋯` 分隔远距离改动,摘要和底部统计都不计入共享上下文。若一个片段需要超过 256 次行新增或删除,则停止精确比较;该片段按完整新旧内容显示和统计为粗粒度替换,包含共享行。复制包含完整显示 diff 及其前缀。末尾换行视为行终止符;仅末尾换行不同不会显示为改动。 diff --git a/packages/client/ui-primitives/src/CodeToolbar.tsx b/packages/client/ui-primitives/src/CodeToolbar.tsx index 755753e894..897d4cd1f7 100644 --- a/packages/client/ui-primitives/src/CodeToolbar.tsx +++ b/packages/client/ui-primitives/src/CodeToolbar.tsx @@ -47,7 +47,7 @@ export function CodeToolbar({ lang, title, status, labels, copyLabel, copiedLabe
{status !== undefined && {status}} {onWrap !== undefined && - } diff --git a/packages/client/ui-primitives/src/DiffBlock.module.css b/packages/client/ui-primitives/src/DiffBlock.module.css index 649237832c..8e78a0b708 100644 --- a/packages/client/ui-primitives/src/DiffBlock.module.css +++ b/packages/client/ui-primitives/src/DiffBlock.module.css @@ -3,6 +3,8 @@ } .body { + display: grid; + grid-template-columns: minmax(max-content, 1fr); padding: 6px 0 16px; font: var(--dsw-font-markdown-code-block); overflow-x: auto; @@ -15,6 +17,10 @@ white-space: pre; } +.block[data-code-wrap='true'] .body { + grid-template-columns: minmax(0, 1fr); +} + .block[data-code-wrap='true'] .line { white-space: pre-wrap; overflow-wrap: anywhere; diff --git a/packages/client/ui-primitives/src/ReadBlock.module.css b/packages/client/ui-primitives/src/ReadBlock.module.css index fbff018f50..601bb29f48 100644 --- a/packages/client/ui-primitives/src/ReadBlock.module.css +++ b/packages/client/ui-primitives/src/ReadBlock.module.css @@ -1,7 +1,3 @@ -.block { - --dsl-read-gutter: 3ch; -} - .line { display: flex; min-height: 1lh; diff --git a/packages/client/ui-primitives/src/ReadBlock.tsx b/packages/client/ui-primitives/src/ReadBlock.tsx index e1493e3316..0eaf96374f 100644 --- a/packages/client/ui-primitives/src/ReadBlock.tsx +++ b/packages/client/ui-primitives/src/ReadBlock.tsx @@ -1,4 +1,4 @@ -import { useCallback, useMemo, useRef, useState, useSyncExternalStore } from 'react' +import { useCallback, useMemo, useRef, useState, useSyncExternalStore, type CSSProperties } from 'react' import clsx from 'clsx' import { FoldToggle } from './FoldToggle.tsx' import { writeClipboard } from './clipboard.ts' @@ -119,14 +119,18 @@ export function ReadBlock({
)) + const gutterDigits = lines.reduce((digits, line) => Math.max(digits, String(line.number).length), 3) + const gutterStyle = { '--dsl-read-gutter': `${gutterDigits}ch` } as CSSProperties + const paired = lines.map((line, index): readonly [ReadBlockLine, readonly HighlightSpan[] | undefined] => [line, highlighted?.[index]]) return ( -
+
0 ? onCopy : undefined} onWrap={() => { setWrapped(value => !value) }} />
diff --git a/packages/client/ui-primitives/src/index.ts b/packages/client/ui-primitives/src/index.ts index 12518ed198..b8ec370298 100644 --- a/packages/client/ui-primitives/src/index.ts +++ b/packages/client/ui-primitives/src/index.ts @@ -2,6 +2,7 @@ * Cordis-free React primitives styled only through `--dsw-*` tokens. */ +export type { CodeToolbarLabels } from './CodeToolbar.tsx' export { StateDot } from './StateDot.tsx' export type { StateDotState } from './StateDot.tsx' export { DisclosureRow } from './DisclosureRow.tsx' diff --git a/packages/client/ui-primitives/src/markdown/CodeBlock.module.css b/packages/client/ui-primitives/src/markdown/CodeBlock.module.css index 3c2cf7eebe..49bcfe33a7 100644 --- a/packages/client/ui-primitives/src/markdown/CodeBlock.module.css +++ b/packages/client/ui-primitives/src/markdown/CodeBlock.module.css @@ -104,10 +104,6 @@ color: var(--dsw-alias-label-primary); } -.card { - --dsl-code-block-content-font: var(--dsw-font-markdown-code-block); -} - .card :where(pre) { padding: 6px 18px 16px; word-break: normal; diff --git a/packages/client/ui-primitives/src/markdown/render.tsx b/packages/client/ui-primitives/src/markdown/render.tsx index cdf1b62ec9..a7bb8a2365 100644 --- a/packages/client/ui-primitives/src/markdown/render.tsx +++ b/packages/client/ui-primitives/src/markdown/render.tsx @@ -22,6 +22,7 @@ import clsx from 'clsx' import type * as Md from 'mdast' import type {} from 'mdast-util-math' import { normalizeUri } from 'micromark-util-sanitize-uri' +import type { CodeToolbarLabels } from '../CodeToolbar.tsx' import { CodeBlock } from './CodeBlock.tsx' import { parseFileLink } from './file-link.ts' import { renderTexToReact } from './katex.tsx' @@ -37,7 +38,7 @@ export interface MarkdownCodeLabels { /** Copy-button label during the post-copy confirmation window. */ copiedLabel: string /** Shared card controls; omitted in compact and owner-styled source views. */ - toolbarLabels?: import('../CodeToolbar.tsx').CodeToolbarLabels | undefined + toolbarLabels?: CodeToolbarLabels | undefined } /** Localized chrome for a Markdown document. */ diff --git a/packages/client/ui-primitives/tests/code-card-controls.client.spec.tsx b/packages/client/ui-primitives/tests/code-card-controls.client.spec.tsx index 467aa5e833..e4b152650f 100644 --- a/packages/client/ui-primitives/tests/code-card-controls.client.spec.tsx +++ b/packages/client/ui-primitives/tests/code-card-controls.client.spec.tsx @@ -37,10 +37,11 @@ describe('code-card controls', () => { : kind === 'read' ? : ) - const button = screen.getByRole('button', { name: kind === 'code' ? 'Do not wrap lines' : 'Wrap lines' }) + const button = screen.getByRole('button', { name: 'Wrap lines' }) const wasWrapped = button.getAttribute('aria-pressed') === 'true' fireEvent.click(button) expect(button.getAttribute('aria-pressed')).toBe(String(!wasWrapped)) + expect(button.getAttribute('aria-label')).toBe('Wrap lines') expect(view.container.textContent).toContain(code) fireEvent.click(button) expect(button.getAttribute('aria-pressed')).toBe(String(wasWrapped)) @@ -52,7 +53,7 @@ describe('code-card controls', () => { fireEvent.mouseEnter(copy) expect(screen.getByRole('tooltip').textContent).toBe('Copy') fireEvent.mouseLeave(copy) - const wrap = screen.getByRole('button', { name: 'Do not wrap lines' }) + const wrap = screen.getByRole('button', { name: 'Wrap lines' }) fireEvent.mouseEnter(wrap) expect(screen.getByRole('tooltip').textContent).toBe('Do not wrap lines') fireEvent.click(wrap) diff --git a/packages/client/ui-theme/README.i18n.yaml b/packages/client/ui-theme/README.i18n.yaml index e48e09fdac..819e09548b 100644 --- a/packages/client/ui-theme/README.i18n.yaml +++ b/packages/client/ui-theme/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-theme/README.md -README.md: 9526078829a882f18b08e5cc7ac8a9bb5ac7dfe4 -README.zh.md: e487d85191d1afdb4d1d013459f94c0742d93b1d +README.md: f1fb30221bb176648cc99f1b2a39984ff3b84871 +README.zh.md: c1e44eb5b9307dbb49e0868b0c68af3410b38928 diff --git a/packages/client/ui-theme/README.md b/packages/client/ui-theme/README.md index 9526078829..f1fb30221b 100644 --- a/packages/client/ui-theme/README.md +++ b/packages/client/ui-theme/README.md @@ -51,7 +51,7 @@ The service owns theme and font-size state and publishes snapshots. The ui-layou ### Stylesheets -`src/styles/` holds six sheets imported in order by ui-theme's dynamic client entry: `base.css`, `corner-shape.css`, `design-platform.css`, `scrollbar.css`, `gradient-shadow-text.css`, and `shiki.css`. The client bundle compiles and injects them as plugin-owned global styles, so unload and HMR remove them with ui-theme. `scrollbar.css` consumes the `--dsw-alias-scrollbar-*` tokens and must follow `design-platform.css`, which declares them. Status marks use their own semantic state tokens. +`src/styles/` holds six sheets imported in order by ui-theme's dynamic client entry: `base.css`, `corner-shape.css`, `design-platform.css`, `scrollbar.css`, `gradient-shadow-text.css`, and `shiki.css`. The client bundle compiles and injects them as plugin-owned global styles, so unload and HMR remove them with ui-theme. `scrollbar.css` consumes the `--dsw-alias-scrollbar-*` tokens and must follow `design-platform.css`, which declares them. Status marks use their own semantic state tokens. `design-platform.css` also owns the code-diff fill aliases and their static alpha palette entries; `shiki.css` owns syntax colors. `corner-shape.css` smooths every rounded corner: inside `@supports (corner-shape: superellipse(1.5))` it defines `--dsw-corner-shape` and applies it to all elements and their `::before`/`::after` through the universal selector, so engines without `corner-shape` keep circular corners. Full-round shapes — `border-radius: 50%` circles and pill radii — pair `corner-shape: round` with their radius in the owning component sheet because a superellipse deforms them; the corner-shape stylesheet spec enforces that pairing across every package stylesheet. diff --git a/packages/client/ui-theme/README.zh.md b/packages/client/ui-theme/README.zh.md index e487d85191..c1e44eb5b9 100644 --- a/packages/client/ui-theme/README.zh.md +++ b/packages/client/ui-theme/README.zh.md @@ -51,7 +51,7 @@ kind: "package-reference" ### 样式表 -`src/styles/` 下有六张样式表,由 ui-theme 的动态客户端 entry 依次导入:`base.css`、`corner-shape.css`、`design-platform.css`、`scrollbar.css`、`gradient-shadow-text.css` 与 `shiki.css`。客户端 bundle 将其编译并注入为插件持有的全局样式,因此卸载与 HMR(热模块替换)会随 ui-theme 一同移除。`scrollbar.css` 消费 `--dsw-alias-scrollbar-*` token,必须排在声明这些 token 的 `design-platform.css` 之后。状态标记使用各自的语义状态 token。 +`src/styles/` 下有六张样式表,由 ui-theme 的动态客户端 entry 依次导入:`base.css`、`corner-shape.css`、`design-platform.css`、`scrollbar.css`、`gradient-shadow-text.css` 与 `shiki.css`。客户端 bundle 将其编译并注入为插件持有的全局样式,因此卸载与 HMR(热模块替换)会随 ui-theme 一同移除。`scrollbar.css` 消费 `--dsw-alias-scrollbar-*` token,必须排在声明这些 token 的 `design-platform.css` 之后。状态标记使用各自的语义状态 token。`design-platform.css` 还负责代码差异底色的别名及其静态透明度色阶;`shiki.css` 负责语法颜色。 `corner-shape.css` 平滑所有圆角:在 `@supports (corner-shape: superellipse(1.5))` 内定义 `--dsw-corner-shape`,并通过通配选择器应用到所有元素及其 `::before`/`::after`,因此不支持 `corner-shape` 的引擎保持普通圆弧。正圆形状——`border-radius: 50%` 的圆与胶囊半径——因超级椭圆会使其变形,须在所属组件样式表中把 `corner-shape: round` 与半径声明配对;corner-shape 样式表 spec 跨全部包样式表强制这一配对。 diff --git a/packages/client/ui-theme/src/styles/design-platform.css b/packages/client/ui-theme/src/styles/design-platform.css index 4cc18f3be5..929b24be6c 100644 --- a/packages/client/ui-theme/src/styles/design-platform.css +++ b/packages/client/ui-theme/src/styles/design-platform.css @@ -34,6 +34,8 @@ body { --dsw-static-green-100: rgb(230, 250, 237); --dsw-static-green-400: rgb(78, 209, 126); --dsw-static-green-500: rgb(34, 197, 94); + --dsw-static-green-500-a08: rgb(34 197 94 / 8%); + --dsw-static-green-500-a12: rgb(34 197 94 / 12%); --dsw-static-green-900: rgb(35, 60, 44); --dsw-static-neutral-00: rgb(255, 255, 255); --dsw-static-neutral-1000: rgb(0, 0, 0); @@ -72,9 +74,11 @@ body { --dsw-static-neutral-bluish-950: rgb(21, 21, 23); --dsw-static-red-100: rgb(254, 226, 226); --dsw-static-red-400: rgb(242, 90, 90); + --dsw-static-red-400-a12: rgb(242 90 90 / 12%); --dsw-static-red-500: rgb(239, 68, 68); --dsw-static-red-50: rgb(254, 242, 242); --dsw-static-red-600: rgb(236, 19, 19); + --dsw-static-red-600-a08: rgb(236 19 19 / 8%); --dsw-static-red-900: rgb(87, 12, 12); } @@ -111,6 +115,8 @@ body[data-ds-dark-theme] { --dsw-static-green-100: rgb(230, 250, 237); --dsw-static-green-400: rgb(78, 209, 126); --dsw-static-green-500: rgb(34, 197, 94); + --dsw-static-green-500-a08: rgb(34 197 94 / 8%); + --dsw-static-green-500-a12: rgb(34 197 94 / 12%); --dsw-static-green-900: rgb(35, 60, 44); --dsw-static-neutral-00: rgb(255, 255, 255); --dsw-static-neutral-1000: rgb(0, 0, 0); @@ -149,9 +155,11 @@ body[data-ds-dark-theme] { --dsw-static-neutral-bluish-950: rgb(21, 21, 23); --dsw-static-red-100: rgb(254, 226, 226); --dsw-static-red-400: rgb(242, 90, 90); + --dsw-static-red-400-a12: rgb(242 90 90 / 12%); --dsw-static-red-500: rgb(239, 68, 68); --dsw-static-red-50: rgb(254, 242, 242); --dsw-static-red-600: rgb(236, 19, 19); + --dsw-static-red-600-a08: rgb(236 19 19 / 8%); --dsw-static-red-900: rgb(87, 12, 12); } @@ -226,6 +234,8 @@ body { --dsw-alias-scrollbar-hover-l2: var(--dsw-static-neutral-300); --dsw-alias-state-business-primary: var(--dsw-static-deepseek-500); --dsw-alias-state-business-tertiary: var(--dsw-static-deepseek-100); + --dsw-alias-code-diff-added: var(--dsw-static-green-500-a08); + --dsw-alias-code-diff-deleted: var(--dsw-static-red-600-a08); --dsw-alias-state-error-primary: var(--dsw-static-red-600); --dsw-alias-state-error-secondary: var(--dsw-static-red-400); --dsw-alias-state-idle-primary: var(--dsw-static-neutral-300); @@ -324,6 +334,8 @@ body[data-ds-dark-theme] { --dsw-alias-scrollbar-hover-l2: var(--dsw-static-neutral-550); --dsw-alias-state-business-primary: var(--dsw-static-deepseek-400); --dsw-alias-state-business-tertiary: var(--dsw-static-deepseek-800); + --dsw-alias-code-diff-added: var(--dsw-static-green-500-a12); + --dsw-alias-code-diff-deleted: var(--dsw-static-red-400-a12); --dsw-alias-state-error-primary: var(--dsw-static-red-400); --dsw-alias-state-error-secondary: var(--dsw-static-red-400); --dsw-alias-state-idle-primary: var(--dsw-static-neutral-600); diff --git a/packages/client/ui-theme/src/styles/shiki.css b/packages/client/ui-theme/src/styles/shiki.css index f969d1b264..c7a3c5d272 100644 --- a/packages/client/ui-theme/src/styles/shiki.css +++ b/packages/client/ui-theme/src/styles/shiki.css @@ -4,11 +4,6 @@ cascade as every other token sheet. Background/foreground deliberately alias the markdown code-block tokens so highlighted and plain blocks agree. */ -body { - --dsw-alias-code-diff-added: color-mix(in srgb, var(--dsw-alias-state-success-primary) 8%, transparent); - --dsw-alias-code-diff-deleted: color-mix(in srgb, var(--dsw-alias-state-error-primary) 8%, transparent); -} - :root { --shiki-foreground: var(--dsw-alias-label-primary); --shiki-background: var(--dsw-alias-markdown-code-block); @@ -24,8 +19,6 @@ body { } body[data-ds-dark-theme] { - --dsw-alias-code-diff-added: color-mix(in srgb, var(--dsw-alias-state-success-primary) 12%, transparent); - --dsw-alias-code-diff-deleted: color-mix(in srgb, var(--dsw-alias-state-error-primary) 12%, transparent); --shiki-token-constant: #4dabf7; --shiki-token-string: #69db7c; --shiki-token-comment: #adb5bd; diff --git a/packages/client/ui-tool/src/client/tool/models/primitive-labels.ts b/packages/client/ui-tool/src/client/tool/models/primitive-labels.ts index 156a1f3c21..af1e13679b 100644 --- a/packages/client/ui-tool/src/client/tool/models/primitive-labels.ts +++ b/packages/client/ui-tool/src/client/tool/models/primitive-labels.ts @@ -1,7 +1,7 @@ /** Localized copy adapters for Cordis-free UI primitives used by Tool cards. */ import type { - CodeBlockProps, + CodeToolbarLabels, DiffBlockLabels, MarkdownLabels, ReadBlockLabels, @@ -17,7 +17,7 @@ type T = TranslateNS<'conversation'> * @param t - Conversation locale seat. * @returns Language fallback and wrapping actions. */ -export function codeToolbarLabels(t: T): NonNullable { +export function codeToolbarLabels(t: T): CodeToolbarLabels { return { codeLabel: t('codeBlock.title'), wrapLabel: t('codeBlock.wrap'), unwrapLabel: t('codeBlock.unwrap') } } diff --git a/snapshots/web/diff-bounded/ui.expected.md b/snapshots/web/diff-bounded/ui.expected.md index 056f1e2156..1883ed4a1c 100644 --- a/snapshots/web/diff-bounded/ui.expected.md +++ b/snapshots/web/diff-bounded/ui.expected.md @@ -2,6 +2,8 @@ - text: Edit - button "large.txt" - text: +130 -130 +- text: Code block +- button "Wrap lines" - button "Copy" - text: large.txt - shared heading - old setting 0 - old setting 1 - old setting 2 - button "Expand 252 more diff lines": … 252 more lines diff --git a/snapshots/web/diff-context/ui.expected.md b/snapshots/web/diff-context/ui.expected.md index 628877899b..44e1810526 100644 --- a/snapshots/web/diff-context/ui.expected.md +++ b/snapshots/web/diff-context/ui.expected.md @@ -2,6 +2,8 @@ - text: Edit - button "config.txt" - text: +1 -1 +- text: Code block +- button "Wrap lines" - button "Copy" - text: config.txt - mode=DEBUG + mode=RELEASE level=info └ +1 -1 · 1 file - button "Inspect" diff --git a/snapshots/web/goal-multi-turn-actions/ui-expanded.expected.md b/snapshots/web/goal-multi-turn-actions/ui-expanded.expected.md index 7c9f533f8c..1492d81803 100644 --- a/snapshots/web/goal-multi-turn-actions/ui-expanded.expected.md +++ b/snapshots/web/goal-multi-turn-actions/ui-expanded.expected.md @@ -31,8 +31,12 @@ - text: — 随机选中的包: - code: packages/context/session-reference - text: 📦 +- text: Code block +- button "Wrap lines" [pressed] - button "Copy" - code: session-reference ├── README.md ├── package.json ├── src │ ├── index.ts │ └── uri.ts └── tests └── session-reference.spec.ts +- text: Code block +- button "Wrap lines" [pressed] - button "Copy" - code: "session-reference/ ├── README.md # 包说明文档 ├── package.json # 包元数据与依赖声明 ├── src/ │ ├── index.ts # 入口,导出公共 API │ └── uri.ts # 会话引用 URI 相关实现 └── tests/ └── session-reference.spec.ts # 单元测试" - paragraph: 这是一个很典型的轻量 TypeScript 包结构:入口 + 实现 + 测试。这一轮到此结束,等系统开启下一个 turn。 @@ -54,8 +58,12 @@ - text: — 随机选中的包: - code: packages/llm/token-meter - text: 📦 +- text: Code block +- button "Wrap lines" [pressed] - button "Copy" - code: token-meter ├── README.md ├── package.json ├── src │ └── index.ts └── tests └── token-meter.spec.ts +- text: Code block +- button "Wrap lines" [pressed] - button "Copy" - code: "token-meter/ ├── README.md # 包说明文档 ├── package.json # 包元数据与依赖声明 ├── src/ │ └── index.ts # 入口,导出公共 API(token 计量逻辑) └── tests/ └── token-meter.spec.ts # 单元测试" - paragraph: @@ -76,14 +84,16 @@ - strong: Turn 1 - text: — 随机选中 - code: packages/context/session-reference - - text: ,输出了文件结构: + - text: ,输出了文件结构: Code block + - button "Wrap lines" [pressed] - button "Copy" - code: session-reference/ ├── README.md ├── package.json ├── src/ │ ├── index.ts │ └── uri.ts └── tests/ └── session-reference.spec.ts - listitem: - strong: Turn 2 - text: — 随机选中 - code: packages/llm/token-meter - - text: ,输出了文件结构: + - text: ,输出了文件结构: Code block + - button "Wrap lines" [pressed] - button "Copy" - code: token-meter/ ├── README.md ├── package.json ├── src/ │ └── index.ts └── tests/ └── token-meter.spec.ts - paragraph: diff --git a/snapshots/web/goal-multi-turn-actions/ui.expected.md b/snapshots/web/goal-multi-turn-actions/ui.expected.md index 2d7d6a5d24..0251c8d0e7 100644 --- a/snapshots/web/goal-multi-turn-actions/ui.expected.md +++ b/snapshots/web/goal-multi-turn-actions/ui.expected.md @@ -17,8 +17,12 @@ - text: — 随机选中的包: - code: packages/context/session-reference - text: 📦 +- text: Code block +- button "Wrap lines" [pressed] - button "Copy" - code: session-reference ├── README.md ├── package.json ├── src │ ├── index.ts │ └── uri.ts └── tests └── session-reference.spec.ts +- text: Code block +- button "Wrap lines" [pressed] - button "Copy" - code: "session-reference/ ├── README.md # 包说明文档 ├── package.json # 包元数据与依赖声明 ├── src/ │ ├── index.ts # 入口,导出公共 API │ └── uri.ts # 会话引用 URI 相关实现 └── tests/ └── session-reference.spec.ts # 单元测试" - paragraph: 这是一个很典型的轻量 TypeScript 包结构:入口 + 实现 + 测试。这一轮到此结束,等系统开启下一个 turn。 @@ -36,14 +40,16 @@ - strong: Turn 1 - text: — 随机选中 - code: packages/context/session-reference - - text: ,输出了文件结构: + - text: ,输出了文件结构: Code block + - button "Wrap lines" [pressed] - button "Copy" - code: session-reference/ ├── README.md ├── package.json ├── src/ │ ├── index.ts │ └── uri.ts └── tests/ └── session-reference.spec.ts - listitem: - strong: Turn 2 - text: — 随机选中 - code: packages/llm/token-meter - - text: ,输出了文件结构: + - text: ,输出了文件结构: Code block + - button "Wrap lines" [pressed] - button "Copy" - code: token-meter/ ├── README.md ├── package.json ├── src/ │ └── index.ts └── tests/ └── token-meter.spec.ts - paragraph: diff --git a/snapshots/web/tool-details/ui.expected.md b/snapshots/web/tool-details/ui.expected.md index bd5a22851a..4a7cc83df9 100644 --- a/snapshots/web/tool-details/ui.expected.md +++ b/snapshots/web/tool-details/ui.expected.md @@ -129,6 +129,7 @@ - list: - listitem: - text: json + - button "Wrap lines" [pressed] - button "Copy" - code: "{ \"type\": \"object\", \"properties\": { \"service\": { \"type\": \"string\" } } }" - group: @@ -136,6 +137,7 @@ - list: - listitem: - text: json + - button "Wrap lines" [pressed] - button "Copy" - code: "{ \"type\": \"object\" }" - listitem: @@ -154,6 +156,7 @@ - list: - listitem: - text: json + - button "Wrap lines" [pressed] - button "Copy" - code: "{ \"type\": \"object\", \"properties\": { \"root\": { \"type\": \"string\" } } }" - group: @@ -161,6 +164,7 @@ - list: - listitem: - text: json + - button "Wrap lines" [pressed] - button "Copy" - code: "{ \"type\": \"object\" }" - button "Inspect" @@ -224,6 +228,7 @@ - list: - listitem: - text: javascript + - button "Wrap lines" [pressed] - button "Copy" - code: "return { reviewed: 12, needsDetails: [\"list_agents\", \"job_list\", \"terminal_list\"] };" - listitem: @@ -440,7 +445,8 @@ - text: Recorded result - list: - listitem: - - text: job-demo-build Running + - text: job-demo-build Running Code block + - button "Wrap lines" [pressed] - button "Copy" - code: Building client assets… ✓ 184 modules transformed. dist/index.js 92.4 kB - button "Inspect" @@ -458,6 +464,8 @@ - text: preview Started terminal-demo-1 - term: Type - definition: shell + - text: Code block + - button "Wrap lines" [pressed] - button "Copy" - code: /workspace/demo % - button "Inspect" @@ -465,7 +473,8 @@ - text: Recorded result - list: - listitem: - - text: terminal-demo-1 Lines 16–18 of 18 + - text: terminal-demo-1 Lines 16–18 of 18 Code block + - button "Wrap lines" [pressed] - button "Copy" - code: "VITE v7.0.0 ready in {{duration}} Local: http://localhost:5173/ Watching for file changes…" - button "Inspect" @@ -545,6 +554,7 @@ - listitem: - button "src/tool-details.ts:24:1" - text: typescript + - button "Wrap lines" [pressed] - button "Copy" - code: "function renderToolDetails(model: ToolDetailsModel): ReactNode" - paragraph: Render compact fields and list rows from a recorded tool result. diff --git a/tsconfig.host.json b/tsconfig.host.json index 140e9f5894..f359eaba9a 100644 --- a/tsconfig.host.json +++ b/tsconfig.host.json @@ -12,6 +12,7 @@ "apps/web/product-isolation.ts", "apps/web/tests/default-product-isolation.e2e.ts", "apps/web/tests/diff-context.e2e.ts", + "apps/web/tests/code-card-layout.e2e.ts", "apps/web/tests/scaffold.ts", "apps/web/tests/voice-input.e2e.ts", "apps/web/tests/voice-setup.e2e.ts", From adbb0e0dc4c0b8a5cf97b9be736490453631df03 Mon Sep 17 00:00:00 2001 From: lsdsjy <1356263+lsdsjy@users.noreply.github.com> Date: Tue, 22 Sep 2026 11:39:14 +0800 Subject: [PATCH 05/29] fix(client): update the contact form URL and drop its account UID prefill The Contact us entry now opens the current Feishu questionnaire, and the URL no longer carries the signed-in account UID: contactUs stops reading the account profile, contactUrl stops writing prefill_uid and hide_uid, and the remaining build and browser context fields keep their existing behavior. The url, package tests and the bilingual README and account-login note state the same current facts. --- ...026-09-14-deepseek-account-login.i18n.yaml | 4 ++-- .../2026-09-14-deepseek-account-login.md | 2 +- .../2026-09-14-deepseek-account-login.zh.md | 2 +- .../ui-settings-account/README.i18n.yaml | 4 ++-- packages/client/ui-settings-account/README.md | 2 +- .../client/ui-settings-account/README.zh.md | 2 +- .../src/client/contact-url.ts | 6 ++--- .../ui-settings-account/src/client/index.ts | 2 -- .../ui-settings-account/src/contact-config.ts | 2 +- .../tests/apply.client.spec.ts | 7 ++++-- .../tests/contact-url.client.spec.ts | 23 ++++++++++--------- 11 files changed, 28 insertions(+), 28 deletions(-) diff --git a/.agents/notes/implemented/architecture/2026-09-14-deepseek-account-login.i18n.yaml b/.agents/notes/implemented/architecture/2026-09-14-deepseek-account-login.i18n.yaml index a97feda0c1..3d6874cde0 100644 --- a/.agents/notes/implemented/architecture/2026-09-14-deepseek-account-login.i18n.yaml +++ b/.agents/notes/implemented/architecture/2026-09-14-deepseek-account-login.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-09-14-deepseek-account-login.md -2026-09-14-deepseek-account-login.md: 65405b293cdea14a231d8d700589f9c3e7ef6db7 -2026-09-14-deepseek-account-login.zh.md: 0aca011826006a0fb8f0557464187b73da377238 +2026-09-14-deepseek-account-login.md: 9b323e03d6c60612092ac5834064770719d71560 +2026-09-14-deepseek-account-login.zh.md: ab50c4758de0567a96a59cfe8966e378d6b8de14 diff --git a/.agents/notes/implemented/architecture/2026-09-14-deepseek-account-login.md b/.agents/notes/implemented/architecture/2026-09-14-deepseek-account-login.md index 65405b293c..9b323e03d6 100644 --- a/.agents/notes/implemented/architecture/2026-09-14-deepseek-account-login.md +++ b/.agents/notes/implemented/architecture/2026-09-14-deepseek-account-login.md @@ -36,7 +36,7 @@ The account plugin supplies choice, waiting, failure and timeout dialogs through Platform embedding transfers a grant from Host to Electron over private Node IPC and then once to the trusted Platform main frame through a sandboxed preload. Preload performs one synchronous IPC before page scripts execute; the main process only validates the sender and returns prepared memory. Platform reads the token synchronously thereafter without a readiness API. A failed initialization retains embedded mode and a throwing getter. Account UI projections remain credential-free. The Platform document can read this credential, so its script security is part of account protection; context isolation protects native capabilities, not a token intentionally returned to the document. Replacing or removing the grant destroys the document and its temporary session. -Support questionnaires receive only the Platform UID and available environment metadata through explicit prefill fields. Account tokens and masked contact details stay out of questionnaire URLs. The account provider projects the current-user UID for this purpose; the UI uses the latest account snapshot so sign-out cannot reuse a previous UID. +Support questionnaires receive only available environment metadata through explicit prefill fields. Account UIDs, tokens and masked contact details stay out of questionnaire URLs. Private proxy development can explicitly map authorization and completion URLs to platformOrigin with rewriteBrowserOrigin. Both pages retain their fixed paths and full query strings; allowing a remote origin without mapping it would send the browser outside the configured environment. Shipped configuration requires same-origin URLs. diff --git a/.agents/notes/implemented/architecture/2026-09-14-deepseek-account-login.zh.md b/.agents/notes/implemented/architecture/2026-09-14-deepseek-account-login.zh.md index 0aca011826..ab50c4758d 100644 --- a/.agents/notes/implemented/architecture/2026-09-14-deepseek-account-login.zh.md +++ b/.agents/notes/implemented/architecture/2026-09-14-deepseek-account-login.zh.md @@ -36,7 +36,7 @@ API Key 与账号记录独立保存。账号 token 没有过期或刷新流程 Platform 内嵌通过私有 Node IPC 将授权从 Host 传给 Electron,再经沙箱 preload 一次性传给受信任的 Platform 主 frame。preload 在页面脚本执行前执行一次同步 IPC;主进程仅校验调用来源并返回已准备的内存数据。Platform 此后同步读取 token,无需就绪接口。初始化失败时保留内嵌模式,由 getter 抛错。账号 UI 投影仍不包含凭证。Platform 文档能够读取此凭证,因此其脚本安全也是账号保护的一部分;上下文隔离保护原生能力,不能隐藏有意返回给文档的 token。替换或移除授权会销毁文档及其临时会话。 -支持问卷仅通过显式预填字段接收 Platform UID 和已有的环境信息,URL 不包含账号 token 或脱敏联系方式。账号提供者为此投影 current-user 的 UID;UI 使用最新账号快照,避免退出登录后复用旧 UID。 +支持问卷仅通过显式预填字段接收已有的环境信息,URL 不包含账号 UID、token 或脱敏联系方式。 私有代理开发可通过 rewriteBrowserOrigin 显式将授权页和完成页映射到 platformOrigin。两者保留固定路径和完整查询字符串;仅放宽来源而不做映射会让浏览器离开配置的环境。发布配置要求浏览器地址同源。 diff --git a/packages/client/ui-settings-account/README.i18n.yaml b/packages/client/ui-settings-account/README.i18n.yaml index cb697284a7..67f94258b5 100644 --- a/packages/client/ui-settings-account/README.i18n.yaml +++ b/packages/client/ui-settings-account/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-settings-account/README.md -README.md: fdbbc4c391e7b4d6f6111de936b23f2fa101f3e3 -README.zh.md: 64acaa4b975c5b37213990bb866b268c9a689d1e +README.md: 30d41fb49262619fd34f1bcd1abfec49d1248438 +README.zh.md: 1916bb2bb37704e5ecc22589620add82ce74780f diff --git a/packages/client/ui-settings-account/README.md b/packages/client/ui-settings-account/README.md index fdbbc4c391..30d41fb492 100644 --- a/packages/client/ui-settings-account/README.md +++ b/packages/client/ui-settings-account/README.md @@ -28,7 +28,7 @@ Balances use Platform Web currency formatting: two decimal places and digit grou Desktop usage and top-up actions open an isolated native Platform view below a 48px return bar. Back destroys the view and preserves the Account settings page. Browser clients retain external links. Loading failures retain the return action and show a centered localized error with Retry. Retry reloads the same destination; renderer commands never receive the account token. -Contact us opens the Feishu questionnaire in the system browser on Desktop or a new browser tab on Web. It supplies the available Platform UID, build version, UI locale and physical screen resolution as prefill_* parameters, with hide_*=1 for every context field; tokens and contact details are excluded. Configure contactFormUrl on the ui-settings-account plugin to select another HTTPS form. contactSource defaults to empty until the questionnaire supports a Harness source option; OS and device fields remain unfilled, matching the Web implementation. +Contact us opens the Feishu questionnaire in the system browser on Desktop or a new browser tab on Web. It supplies the available build version, UI locale and physical screen resolution as prefill_* parameters, with hide_*=1 for every context field; the account UID, tokens and contact details are excluded. Configure contactFormUrl on the ui-settings-account plugin to select another HTTPS form. contactSource defaults to empty until the questionnaire supports a Harness source option; OS and device fields remain unfilled, matching the Web implementation. The sidebar account menu uses the shared Menu surface, backdrop blur, spacing, and row typography; feature styles only size its launcher. diff --git a/packages/client/ui-settings-account/README.zh.md b/packages/client/ui-settings-account/README.zh.md index 64acaa4b97..1916bb2bb3 100644 --- a/packages/client/ui-settings-account/README.zh.md +++ b/packages/client/ui-settings-account/README.zh.md @@ -28,7 +28,7 @@ kind: "package-reference" Desktop 的用量和充值操作在 48px 返回栏下方打开隔离的原生 Platform 视图。返回操作销毁视图并保留 Account 设置页。浏览器客户端继续使用外链。加载失败时保留返回操作,居中显示本地化错误提示和“重试”按钮。重试重新加载同一目标页面;渲染进程命令不接收账号 token。 -“联系我们”在 Desktop 的系统浏览器或 Web 的新标签页打开飞书问卷。链接通过 prefill_* 参数填写已有的 Platform UID、构建版本、界面语言和屏幕物理分辨率,并为所有上下文字段设置 hide_*=1;不传 token 或联系方式。可在 ui-settings-account 插件配置 contactFormUrl,切换到另一个 HTTPS 问卷。问卷支持 Harness 来源选项前,contactSource 默认为空;OS 和设备字段沿用 Web 实现,保持未填写。 +“联系我们”在 Desktop 的系统浏览器或 Web 的新标签页打开飞书问卷。链接通过 prefill_* 参数填写已有的构建版本、界面语言和屏幕物理分辨率,并为所有上下文字段设置 hide_*=1;不传账号 UID、token 或联系方式。可在 ui-settings-account 插件配置 contactFormUrl,切换到另一个 HTTPS 问卷。问卷支持 Harness 来源选项前,contactSource 默认为空;OS 和设备字段沿用 Web 实现,保持未填写。 侧边栏账号菜单使用公共 Menu 的表面、背景模糊、间距和菜单项排版;功能样式仅设置入口布局。 diff --git a/packages/client/ui-settings-account/src/client/contact-url.ts b/packages/client/ui-settings-account/src/client/contact-url.ts index f285260c64..5620f99d00 100644 --- a/packages/client/ui-settings-account/src/client/contact-url.ts +++ b/packages/client/ui-settings-account/src/client/contact-url.ts @@ -1,15 +1,13 @@ /** Feishu questionnaire context follows the Platform Web ticket fields. */ import type { Config } from '../contact-config.ts' -import type { AccountProfile } from '@deepseek-ai/dsh-deepseek-account/types' /** * Build an external questionnaire URL without authentication credentials. * @param config - questionnaire destination and supported source option. - * @param context - currently available account and browser environment. + * @param context - currently available build and browser environment. * @returns questionnaire URL with hidden, optionally prefilled context fields. */ export function contactUrl(config: Config, context: { - uid: AccountProfile['id'] version: string | undefined locale: string width: number @@ -21,7 +19,7 @@ export function contactUrl(config: Config, context: { const width = Math.round(context.width * ratio) const height = Math.round(context.height * ratio) const fields = { - uid: context.uid, source: config.contactSource, app_version: context.version, + source: config.contactSource, app_version: context.version, os_version: undefined, device_brand: undefined, device_model: undefined, app_locale: context.locale, screen_resolution: width > 0 && height > 0 ? `${width}x${height}` : undefined, } diff --git a/packages/client/ui-settings-account/src/client/index.ts b/packages/client/ui-settings-account/src/client/index.ts index 3226eab0e6..3cc65e4668 100644 --- a/packages/client/ui-settings-account/src/client/index.ts +++ b/packages/client/ui-settings-account/src/client/index.ts @@ -84,9 +84,7 @@ export function apply(ctx: Context): void { ...nativePlatform === undefined ? {} : { platform: nativePlatform }, refresh, contactUs() { - const profile = snapshot.details?.profile const url = contactUrl(config, { - uid: profile?.status === 'ready' ? profile.value.id : null, version: process.env.DSH_CLIENT_VERSION, locale: ctx.locale.getSnapshot().active === 'zh' ? 'zh-CN' : 'en', width: window.screen.width, height: window.screen.height, pixelRatio: window.devicePixelRatio, diff --git a/packages/client/ui-settings-account/src/contact-config.ts b/packages/client/ui-settings-account/src/contact-config.ts index 65d4bb06a0..ee9cc3f3b6 100644 --- a/packages/client/ui-settings-account/src/contact-config.ts +++ b/packages/client/ui-settings-account/src/contact-config.ts @@ -10,7 +10,7 @@ export interface Config { } /** Validate public questionnaire options. */ export const Config: z, Config> = z.object({ - contactFormUrl: z.string().pattern(/^https:\/\/[^/\s]+\//).default('https://trtgsjkv6r.feishu.cn/share/base/form/shrcnhcHE4A6lQaQ3v0raCXmBAg'), + contactFormUrl: z.string().pattern(/^https:\/\/[^/\s]+\//).default('https://trtgsjkv6r.feishu.cn/share/base/form/shrcnlCoGElW7MQznGy9r3YYXcg'), contactSource: z.string().default(''), }) /** Bootstrap key containing no account credentials. */ diff --git a/packages/client/ui-settings-account/tests/apply.client.spec.ts b/packages/client/ui-settings-account/tests/apply.client.spec.ts index e1bf83f08e..348924b9ca 100644 --- a/packages/client/ui-settings-account/tests/apply.client.spec.ts +++ b/packages/client/ui-settings-account/tests/apply.client.spec.ts @@ -38,7 +38,9 @@ it('shares account actions across seats, publishes dialog ownership, and opens c actions.showLogin(false) expect(listener).toHaveBeenCalledTimes(2) actions.contactUs() - expect(new URL(String(open.mock.calls.at(-1)![0])).searchParams.has('prefill_uid')).toBe(false) + const signedOut = new URL(String(open.mock.calls.at(-1)![0])) + expect(signedOut.searchParams.has('prefill_uid')).toBe(false) + expect(signedOut.searchParams.has('hide_uid')).toBe(false) c.mock.remote.account.getProfile.mockResolvedValue(ok(profile)) c.mock.streams.push('account/watch', stored) await vi.waitFor(() => { expect(actions.hooks.account.getSnapshot().details?.profile).toEqual(profile) }) @@ -48,7 +50,8 @@ it('shares account actions across seats, publishes dialog ownership, and opens c vi.spyOn(c.ctx.locale, 'getSnapshot').mockReturnValue({ ...c.ctx.locale.getSnapshot(), active: 'zh' }) actions.contactUs() const support = new URL(String(open.mock.calls.at(-1)![0])) - expect(support.searchParams.get('prefill_uid')).toBe('account-user') + expect(support.searchParams.has('prefill_uid')).toBe(false) + expect(support.searchParams.has('hide_uid')).toBe(false) expect(support.searchParams.get('prefill_app_locale')).toBe('zh-CN') await c.unload(SELF) expect(c.ctx.slots.entries('settings.launcher')).toHaveLength(0) diff --git a/packages/client/ui-settings-account/tests/contact-url.client.spec.ts b/packages/client/ui-settings-account/tests/contact-url.client.spec.ts index 57d049e559..943c75cfe8 100644 --- a/packages/client/ui-settings-account/tests/contact-url.client.spec.ts +++ b/packages/client/ui-settings-account/tests/contact-url.client.spec.ts @@ -1,38 +1,39 @@ import { expect, it } from 'vitest' -import type { AccountUserId } from '@deepseek-ai/dsh-deepseek-account/types' import { Config } from '../src/contact-config.ts' import { contactUrl } from '../src/client/contact-url.ts' it('prefills available support context and hides all context fields', () => { const config = Config({ contactSource: 'app_harness' }) const url = new URL(contactUrl(config, { - uid: 'user&123' as AccountUserId, version: '1.2.3', locale: 'zh-CN', - width: 1512, height: 982, pixelRatio: 2, + version: '1.2.3', locale: 'zh-CN', width: 1512, height: 982, pixelRatio: 2, })) expect(url.origin).toBe('https://trtgsjkv6r.feishu.cn') expect(Object.fromEntries(url.searchParams)).toEqual({ - hide_uid: '1', prefill_uid: 'user&123', hide_source: '1', prefill_source: 'app_harness', - hide_app_version: '1', prefill_app_version: '1.2.3', hide_os_version: '1', + hide_source: '1', prefill_source: 'app_harness', hide_app_version: '1', prefill_app_version: '1.2.3', + hide_os_version: '1', hide_device_brand: '1', hide_device_model: '1', hide_app_locale: '1', prefill_app_locale: 'zh-CN', hide_screen_resolution: '1', prefill_screen_resolution: '3024x1964', }) + expect(url.searchParams.has('prefill_uid')).toBe(false) + expect(url.searchParams.has('hide_uid')).toBe(false) }) -it('opens a configured form without stale account context when signed out', () => { - const url = new URL(contactUrl(Config({ contactFormUrl: 'https://example.test/form/?prefill_uid=old&prefill_source=old' }), { - uid: null, version: undefined, locale: 'en', width: 0, height: 0, pixelRatio: 1, +it('opens a configured form without stale context when unavailable', () => { + const url = new URL(contactUrl(Config({ contactFormUrl: 'https://example.test/form/?prefill_app_version=old&prefill_source=old' }), { + version: undefined, locale: 'en', width: 0, height: 0, pixelRatio: 1, })) expect(url.origin).toBe('https://example.test') - expect(url.searchParams.has('prefill_uid')).toBe(false) + expect(url.searchParams.has('prefill_app_version')).toBe(false) expect(url.searchParams.has('prefill_source')).toBe(false) expect(url.searchParams.has('prefill_screen_resolution')).toBe(false) - expect(url.searchParams.get('hide_uid')).toBe('1') + expect(url.searchParams.get('hide_source')).toBe('1') + expect(url.searchParams.get('hide_app_version')).toBe('1') expect(() => Config({ contactFormUrl: 'javascript:alert(1)' })).toThrow() }) it.each([NaN, Infinity])('uses CSS pixel dimensions when device pixel ratio is %s', (pixelRatio) => { const url = new URL(contactUrl(Config({}), { - uid: null, version: undefined, locale: 'en', width: 800, height: 600, pixelRatio, + version: undefined, locale: 'en', width: 800, height: 600, pixelRatio, })) expect(url.searchParams.get('prefill_screen_resolution')).toBe('800x600') }) From 817623750aac9578b4e8cfa381f3d7eb5004f8f7 Mon Sep 17 00:00:00 2001 From: lsdsjy <1356263+lsdsjy@users.noreply.github.com> Date: Tue, 22 Sep 2026 12:02:54 +0800 Subject: [PATCH 06/29] fix(desktop): match Platform login theme Opened and copied authorization links carried no palette, so the Platform login page rendered its own stored preference. Append the effective Desktop palette as theme=light or theme=dark, resolving system through the theme source the preload publishes. The theme source now reaches nativeTheme on Windows as well: the preload drops its macOS-only guard, since shouldUseDarkColors is read for every platform, and gates the DOMContentLoaded listener with once. --- apps/desktop/README.i18n.yaml | 4 +- apps/desktop/README.md | 2 +- apps/desktop/README.zh.md | 2 +- apps/desktop/src/main.ts | 18 +++++- apps/desktop/src/preload-theme.ts | 15 +++-- apps/desktop/tests/main-startup.spec.ts | 20 ++++++- .../tests/preload-theme.client.spec.ts | 58 +++++++++++++++++++ apps/desktop/tests/welcome-startup.spec.ts | 11 +++- 8 files changed, 112 insertions(+), 18 deletions(-) create mode 100644 apps/desktop/tests/preload-theme.client.spec.ts diff --git a/apps/desktop/README.i18n.yaml b/apps/desktop/README.i18n.yaml index d74baaa4b8..6e44ed8a7c 100644 --- a/apps/desktop/README.i18n.yaml +++ b/apps/desktop/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 apps/desktop/README.md -README.md: 711e65fb5feaea601800218801d138a0df9b3f97 -README.zh.md: 183d195a9af485c9ffe5a3e5bf65e3a459582b93 +README.md: 59f18ea269f303e267d5e9597d8748e2a8fed134 +README.zh.md: eb1594e032fea2da38f778e6b2217bd52587af91 diff --git a/apps/desktop/README.md b/apps/desktop/README.md index 711e65fb5f..59f18ea269 100644 --- a/apps/desktop/README.md +++ b/apps/desktop/README.md @@ -405,7 +405,7 @@ An unpackaged Electron process uses `.desktop-build/development/project` under i - Dependency lifecycle scripts follow pnpm’s build permissions; Desktop provides no separate approval dialog. - The desktop shell shares sessions, settings, credentials, workspaces, and storage under `$DSH_HOME` with CLI dsh, while executable packages, plugin activation, and lockfiles remain separate. -Sign in opens the configured platform page in the system browser. The Host owns PKCE and a temporary loopback callback, saves the credential before entering the workspace, and redirects the browser to the platform completion page. Cancel withdraws the local attempt even if the platform page later approves it. Settings offers Account sign-out; without a separate API key, sign-out returns to the welcome window. Packaged applications register dsh://open to show the window without passing credentials. On macOS, the development launcher prepares an ad-hoc-signed `Harness Dev.app` under `.desktop-build/development`, declares `dsh` in its Info.plist, and registers it with Launch Services. It loads the current workspace and records the selected development home, browser-data path, and debug settings for cold starts. Starting this bundle makes it the default `dsh://` handler; starting the packaged application registers the packaged handler again. The generated bundle does not contain account tokens and requires the workspace and prepared runtime to remain available. +Sign in opens the configured platform page in the system browser. The Host owns PKCE and a temporary loopback callback, saves the credential before entering the workspace, and redirects the browser to the platform completion page. Opened and copied authorization links carry the effective Desktop theme as `theme=light` or `theme=dark`; `system` resolves at the time of the action. Cancel withdraws the local attempt even if the platform page later approves it. Settings offers Account sign-out; without a separate API key, sign-out returns to the welcome window. Packaged applications register dsh://open to show the window without passing credentials. On macOS, the development launcher prepares an ad-hoc-signed `Harness Dev.app` under `.desktop-build/development`, declares `dsh` in its Info.plist, and registers it with Launch Services. It loads the current workspace and records the selected development home, browser-data path, and debug settings for cold starts. Starting this bundle makes it the default `dsh://` handler; starting the packaged application registers the packaged handler again. The generated bundle does not contain account tokens and requires the workspace and prepared runtime to remain available. An expired login displays a timeout heading with explicit Sign in again and Add API Key actions. Opening the API-key form dismisses the authorization view; late account-state notifications do not replace an in-progress key entry. diff --git a/apps/desktop/README.zh.md b/apps/desktop/README.zh.md index 183d195a9a..eb1594e032 100644 --- a/apps/desktop/README.zh.md +++ b/apps/desktop/README.zh.md @@ -405,7 +405,7 @@ node apps/desktop/node_modules/pnpm/bin/pnpm.mjs --dir apps/desktop run test:upd - 依赖的生命周期脚本遵循 pnpm 的构建权限;Desktop 不提供单独的审批对话框。 - 桌面壳与 CLI dsh 共享 `$DSH_HOME` 下的会话、设置、凭据、工作区和存储,但可执行包、插件激活和锁文件彼此隔离。 -登录会在系统浏览器中打开配置的平台页面。Host 负责 PKCE 和临时本机回调,在进入工作区前保存凭证,再将浏览器跳转到平台完成页。即使平台页面随后批准,取消仍会撤销本地尝试。设置中的账号页面提供退出;没有独立 API Key 时,退出后返回欢迎窗。打包应用注册 dsh://open,只显示窗口而不传递凭证。macOS 开发启动器在 `.desktop-build/development` 下准备经临时签名的 `Harness Dev.app`,在 Info.plist 中声明 `dsh` 并注册到 Launch Services。它加载当前工作区,并记录选定的开发 home、浏览器数据路径和调试设置,以供冷启动使用。启动此应用会将其设为 `dsh://` 默认处理程序;启动打包应用会重新注册打包版处理程序。生成的应用包不包含账号 token,依赖工作区和已准备的运行环境继续存在。 +登录会在系统浏览器中打开配置的平台页面。Host 负责 PKCE 和临时本机回调,在进入工作区前保存凭证,再将浏览器跳转到平台完成页。打开和复制的授权链接通过 `theme=light` 或 `theme=dark` 携带当前生效的 Desktop 主题;`system` 在执行操作时解析。即使平台页面随后批准,取消仍会撤销本地尝试。设置中的账号页面提供退出;没有独立 API Key 时,退出后返回欢迎窗。打包应用注册 dsh://open,只显示窗口而不传递凭证。macOS 开发启动器在 `.desktop-build/development` 下准备经临时签名的 `Harness Dev.app`,在 Info.plist 中声明 `dsh` 并注册到 Launch Services。它加载当前工作区,并记录选定的开发 home、浏览器数据路径和调试设置,以供冷启动使用。启动此应用会将其设为 `dsh://` 默认处理程序;启动打包应用会重新注册打包版处理程序。生成的应用包不包含账号 token,依赖工作区和已准备的运行环境继续存在。 登录超时后显示超时标题,并提供重新登录和添加 API Key 按钮。打开 API Key 表单会关闭授权视图;后续账号状态通知不会覆盖正在填写的密钥。 diff --git a/apps/desktop/src/main.ts b/apps/desktop/src/main.ts index 46ce1f45c1..9d5497101e 100644 --- a/apps/desktop/src/main.ts +++ b/apps/desktop/src/main.ts @@ -127,6 +127,20 @@ function chromeFallbackFill(): string { return nativeTheme.shouldUseDarkColors ? '#1b1b1c' : '#f9fafb' } +/** + * Add the effective Desktop palette to a Platform authorization URL so the + * login page opens in the application's theme. `system` resolves through + * `nativeTheme.shouldUseDarkColors`, which follows the theme source the + * application preload publishes. + * @param authorizeUrl - validated Platform authorization URL. + * @returns the authorization URL carrying `theme=light` or `theme=dark`. + */ +function platformLoginUrl(authorizeUrl: string): string { + const url = new URL(authorizeUrl) + url.searchParams.set('theme', nativeTheme.shouldUseDarkColors ? 'dark' : 'light') + return url.href +} + function createWindow(preload: string, show = false, primary = false): BrowserWindow { const window = new BrowserWindow({ width: 1280, @@ -333,7 +347,7 @@ async function main(): Promise { const attempt = state.attempt if (attempt?.phase === 'waiting-browser' && attempt.authorizeUrl !== undefined && openedAttempt !== attempt.id) { openedAttempt = attempt.id - void shell.openExternal(attempt.authorizeUrl).catch(() => undefined) + void shell.openExternal(platformLoginUrl(attempt.authorizeUrl)).catch(() => undefined) } if ((attempt?.phase === 'failed' || attempt?.phase === 'expired') && returnedAttempt !== attempt.id) { returnedAttempt = attempt.id @@ -892,7 +906,7 @@ async function main(): Promise { if (state?.attempt?.id !== id || state.attempt.phase !== 'waiting-browser' || state.attempt.authorizeUrl === undefined) { throw new Error('desktop welcome: login link is unavailable') } - await clipboard.writeText(state.attempt.authorizeUrl) + await clipboard.writeText(platformLoginUrl(state.attempt.authorizeUrl)) }, saveApiKey: async (apiKey) => { if (backend.host === undefined || welcomeBackend === undefined) return { ok: false } diff --git a/apps/desktop/src/preload-theme.ts b/apps/desktop/src/preload-theme.ts index cb1acb9699..1274e5b3c4 100644 --- a/apps/desktop/src/preload-theme.ts +++ b/apps/desktop/src/preload-theme.ts @@ -1,4 +1,4 @@ -/** Mirrors the Web UI's theme source into the macOS native theme so window vibrancy follows the app palette. */ +/** Mirrors the Web UI's theme source into Electron's native theme so native chrome and Platform login pages follow the app palette. */ import { ipcRenderer } from 'electron' import { DESKTOP_IPC } from './ipc.ts' @@ -7,14 +7,13 @@ import { DESKTOP_IPC } from './ipc.ts' const THEME_SOURCE_ATTRIBUTE = 'data-ds-theme-source' /** - * On macOS, watches `html[data-ds-theme-source]` and forwards each value to - * the main process, which sets `nativeTheme.themeSource` — the sidebar - * vibrancy material then follows the app's theme preference instead of the - * OS appearance, while `system` keeps following the OS. Other platforms - * never send. + * Watches `html[data-ds-theme-source]` and forwards each value to the main + * process, which sets `nativeTheme.themeSource`. The macOS sidebar vibrancy + * material then follows the app's theme preference instead of the OS + * appearance while `system` keeps following the OS, and the resolved + * `shouldUseDarkColors` palette travels with the Platform login link. */ export function syncNativeTheme(): void { - if (process.platform !== 'darwin') return let sent: string | undefined const send = (): void => { const value = document.documentElement.getAttribute(THEME_SOURCE_ATTRIBUTE) @@ -28,6 +27,6 @@ export function syncNativeTheme(): void { } // The preload runs before the document root exists; the theme bootstrap // script writes the attribute before DOMContentLoaded. - if (document.readyState === 'loading') window.addEventListener('DOMContentLoaded', observe) + if (document.readyState === 'loading') window.addEventListener('DOMContentLoaded', observe, { once: true }) else observe() } diff --git a/apps/desktop/tests/main-startup.spec.ts b/apps/desktop/tests/main-startup.spec.ts index 26c31d906c..00a79e9963 100644 --- a/apps/desktop/tests/main-startup.spec.ts +++ b/apps/desktop/tests/main-startup.spec.ts @@ -165,7 +165,7 @@ const harness = await vi.hoisted(async () => { get publishUpdate() { return publishUpdate! }, set publishUpdate(value: (state: DesktopUpdateState) => DesktopUpdateState) { publishUpdate = value }, dialog: { showOpenDialog: vi.fn(), showErrorBox: vi.fn(), showMessageBox: vi.fn() }, - openExternal: vi.fn(), + openExternal: vi.fn(async () => {}), protocolHandle: vi.fn<(scheme: string, handler: (request: Request) => Response | Promise) => void>(), applyRelease: vi.fn(() => { preparing.resolve(); return prepared.promise }), disableAllPlugins: vi.fn(async () => { @@ -1617,3 +1617,21 @@ it.each(['failed', 'expired'] as const)('focuses DSH once when browser authoriza harness.publishAccount(state) expect(window.focus).toHaveBeenCalledTimes(1) }) + +it.each([['light', false], ['dark', true]] as const)('opens Platform authorization in the effective %s palette', async (theme, shouldUseDarkColors) => { + await import('../src/main.ts') + await harness.preparing.promise + harness.prepared.resolve() + await harness.hostStarted.promise + harness.hosts[0]!.ready.resolve() + await Promise.resolve(invoke(DESKTOP_IPC.boot)) + harness.nativeTheme.shouldUseDarkColors = shouldUseDarkColors + const state: AccountView = { + status: 'signed-out', links: { usageUrl: 'https://platform.deepseek.com/usage', topUpUrl: 'https://platform.deepseek.com/top_up' }, + attempt: { id: 'test-theme-attempt' as NonNullable['id'], phase: 'waiting-browser', + authorizeUrl: 'https://platform.deepseek.com/dsh/authorize?state=state-1' }, + } + harness.publishAccount(state) + harness.publishAccount(state) + expect(harness.openExternal).toHaveBeenCalledExactlyOnceWith(`https://platform.deepseek.com/dsh/authorize?state=state-1&theme=${theme}`) +}) diff --git a/apps/desktop/tests/preload-theme.client.spec.ts b/apps/desktop/tests/preload-theme.client.spec.ts new file mode 100644 index 0000000000..90cd23eab0 --- /dev/null +++ b/apps/desktop/tests/preload-theme.client.spec.ts @@ -0,0 +1,58 @@ +// @vitest-environment jsdom +import { afterEach, expect, it, vi } from 'vitest' +import { DESKTOP_IPC } from '../src/ipc.ts' +import { syncNativeTheme } from '../src/preload-theme.ts' + +const send = vi.hoisted(() => vi.fn()) +vi.mock('electron', () => ({ ipcRenderer: { send } })) + +/** Observers created by the module under test; jsdom keeps one document per file. */ +const observers = new Set() +const NativeMutationObserver = MutationObserver + +/** Records every observer so teardown detaches it from the shared document. */ +class TrackedMutationObserver extends NativeMutationObserver { + constructor(callback: MutationCallback) { + super(callback) + observers.add(this) + } +} + +afterEach(() => { + for (const observer of observers) observer.disconnect() + observers.clear() + document.documentElement.removeAttribute('data-ds-theme-source') + vi.unstubAllGlobals() + vi.restoreAllMocks() + send.mockClear() +}) + +it.each(['darwin', 'win32'] as const)('mirrors the application theme source on %s', async (platform) => { + vi.stubGlobal('MutationObserver', TrackedMutationObserver) + vi.spyOn(process, 'platform', 'get').mockReturnValue(platform) + document.documentElement.setAttribute('data-ds-theme-source', 'dark') + syncNativeTheme() + expect(send).toHaveBeenCalledExactlyOnceWith(DESKTOP_IPC.nativeThemeSet, 'dark') + document.documentElement.setAttribute('data-ds-theme-source', 'system') + await vi.waitFor(() => { expect(send).toHaveBeenLastCalledWith(DESKTOP_IPC.nativeThemeSet, 'system') }) + expect(send).toHaveBeenCalledTimes(2) + for (const observer of observers) observer.disconnect() + send.mockClear() + document.documentElement.setAttribute('data-ds-theme-source', 'light') + await new Promise((resolve) => { queueMicrotask(resolve) }) + expect(send).not.toHaveBeenCalled() +}) + +it('waits for the document root and then stops listening for it', () => { + vi.stubGlobal('MutationObserver', TrackedMutationObserver) + vi.spyOn(process, 'platform', 'get').mockReturnValue('win32') + vi.spyOn(document, 'readyState', 'get').mockReturnValue('loading') + syncNativeTheme() + expect(send).not.toHaveBeenCalled() + document.documentElement.setAttribute('data-ds-theme-source', 'light') + window.dispatchEvent(new Event('DOMContentLoaded')) + expect(send).toHaveBeenCalledExactlyOnceWith(DESKTOP_IPC.nativeThemeSet, 'light') + document.documentElement.setAttribute('data-ds-theme-source', 'dark') + window.dispatchEvent(new Event('DOMContentLoaded')) + expect(send).toHaveBeenCalledOnce() +}) diff --git a/apps/desktop/tests/welcome-startup.spec.ts b/apps/desktop/tests/welcome-startup.spec.ts index db461e59e2..6dd4080692 100644 --- a/apps/desktop/tests/welcome-startup.spec.ts +++ b/apps/desktop/tests/welcome-startup.spec.ts @@ -31,6 +31,7 @@ const state = vi.hoisted(() => ({ windowOptions: undefined as BrowserWindowConstructorOptions | undefined, menu: vi.fn(), operations: undefined as WelcomeOperations | undefined, + nativeTheme: { themeSource: 'system', shouldUseDarkColors: false }, })) vi.mock('electron', () => ({ @@ -67,7 +68,7 @@ vi.mock('electron', () => ({ async loadURL(url: string) { state.contents = this.webContents; await state.loadWorkspace(url); this.ready?.() } }, net: { fetch: vi.fn() }, - nativeTheme: { themeSource: 'system' }, + nativeTheme: state.nativeTheme, session: { defaultSession: { setPermissionCheckHandler: vi.fn(), setPermissionRequestHandler: vi.fn(), webRequest: { onBeforeSendHeaders: vi.fn() }, } }, @@ -177,11 +178,15 @@ it('starts the Host for welcome onboarding and opens the workspace on skip witho attempt: { id: attemptId, phase: 'waiting-browser', authorizeUrl: 'https://example.test/login' } } state.accountState.mockResolvedValue(account) await state.operations!.copySignInLink(attemptId) - expect(state.copy).toHaveBeenCalledExactlyOnceWith('https://example.test/login') + expect(state.copy).toHaveBeenCalledExactlyOnceWith('https://example.test/login?theme=light') + state.nativeTheme.shouldUseDarkColors = true + await state.operations!.copySignInLink(attemptId) + expect(state.copy).toHaveBeenLastCalledWith('https://example.test/login?theme=dark') + state.nativeTheme.shouldUseDarkColors = false await expect(state.operations!.copySignInLink('stale' as typeof attemptId)).rejects.toThrow('login link is unavailable') state.accountState.mockResolvedValue({ ...account, attempt: { id: attemptId, phase: 'expired' } }) await expect(state.operations!.copySignInLink(attemptId)).rejects.toThrow('login link is unavailable') - expect(state.copy).toHaveBeenCalledOnce() + expect(state.copy).toHaveBeenCalledTimes(2) await state.operations!.skip() expect(state.loadWorkspace).not.toHaveBeenCalled() expect(state.showWorkspace).toHaveBeenCalledOnce() From ab62f09c22560e3649901e32f1a41fe51888ba75 Mon Sep 17 00:00:00 2001 From: winewill <324803222+winewill@users.noreply.github.com> Date: Tue, 22 Sep 2026 12:38:05 +0800 Subject: [PATCH 07/29] fix(desktop): report Windows extraction failures with 7-Zip evidence The installer showed "Failed to decompress files" and discarded 7-Zip's error output, so a failure such as security software quarantining an extracted file could not be told apart from a full disk or a broken download. - InstallerExtract returns negated Win32 errors for launch failures so they no longer collide with 7-Zip exit codes; 7-Zip writes UTF-8 errors. - window-frame.dll composes a report (result, archive, destination, Windows version, full 7-Zip output), saves it under the updater cache directory, and presents a task dialog with the first error line, a collapsible bounded excerpt, and a Copy error details button. Silent installs keep only the report; a missing task dialog falls back to a message box. - Unsigned Windows builds name their installer *-unsigned.exe so a shared file cannot pass for a release artifact; version discovery still counts them. - The directory smoke asserts the saved report on a broken archive and smoke-windows.ps1 accepts the prepared DLL. Refs #4893 --- apps/desktop/README.i18n.yaml | 4 +- apps/desktop/README.md | 6 +- apps/desktop/README.zh.md | 6 +- apps/desktop/electron-builder.config.d.mts | 1 + apps/desktop/installer/extract-report.h | 277 ++++++++++++++++++ apps/desktop/installer/extract.h | 42 +-- apps/desktop/installer/strings.nsh | 16 + apps/desktop/installer/window-frame.cpp | 25 ++ .../desktop-build-version-discovery.ts | 4 +- .../scripts/electron-builder-config.mjs | 3 +- .../desktop/scripts/installer-directories.nsh | 6 +- apps/desktop/scripts/installer.nsh | 33 +++ .../scripts/prepare-windows-installer.ps1 | 10 + .../scripts/smoke-installer-directories.ps1 | 20 +- apps/desktop/scripts/smoke-windows.ps1 | 8 +- .../desktop-build-version-discovery.spec.ts | 9 + .../fixtures/installer-directory-smoke.nsi | 3 + .../desktop/tests/installer-packaging.spec.ts | 13 + .../windows-installer-extract-report.cpp | 114 +++++++ .../tests/windows-update-publisher.spec.ts | 1 + 20 files changed, 570 insertions(+), 31 deletions(-) create mode 100644 apps/desktop/installer/extract-report.h create mode 100644 apps/desktop/tests/windows-installer-extract-report.cpp diff --git a/apps/desktop/README.i18n.yaml b/apps/desktop/README.i18n.yaml index 1281bcb68f..4765413cbe 100644 --- a/apps/desktop/README.i18n.yaml +++ b/apps/desktop/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 apps/desktop/README.md -README.md: 813813cf2292a6cfece78a273dcf6843093a95cf -README.zh.md: e63557e98c0a19ecd9bf9e6c9497ce074ce8b57b +README.md: c90e8162f785bb0aa8e25b755fa278725d1dd034 +README.zh.md: d78fc7ada24826f317877162ecf26cad21b519e3 diff --git a/apps/desktop/README.md b/apps/desktop/README.md index 813813cf22..c90e8162f7 100644 --- a/apps/desktop/README.md +++ b/apps/desktop/README.md @@ -190,14 +190,16 @@ The [Office conversion provider](../../packages/document/office-to-pdf/README.md The packaged application runs compiled JavaScript and pre-generated Typert metadata; it does not compile TypeScript plugins. Source-level debugger navigation and editor declarations remain available in development packages. [Copy-policy tests](tests/runtime-file-policy.spec.ts) cover exclusions and retained assets; The [payload smoke](tests/fixtures/runtime-payload-smoke.mjs) runs under Electron RunAsNode before the Host smoke and final inventory verification. The payload smoke resolves the search tool’s ripgrep executable and verifies text search and file enumeration. Signed Windows builds run these checks after dependency signing; other builds run them during `prepare:dsh`. The [Host smoke](scripts/smoke-runtime.ts) creates DOCX, XLSX, and PPTX inputs with bundled Python, converts each through the real Office provider, and checks PDF output. Every assembled application, including directory and unsigned Windows builds, repeats the payload and Host checks against ASAR. Archive integrity checks compare the complete archived descriptor with preparation, file bytes and membership in both archive and unpacked trees, recorded executable flags for archived files, and physical permissions for unpacked files. Conversion failures stop packaging before a release record is written; macOS DMG/ZIP builds run these checks before notarization. -Windows release qualification also runs [directory and replacement checks](scripts/smoke-windows.ps1) manually after the Desktop build. Set `$Makensis`, `$SevenZip`, and `$PluginDir` to the pinned builder’s NSIS compiler, 7-Zip executable, and x86-unicode NSIS plugin directory. From the repository root, run the command below. It verifies directory replacement and rollback, and both locked-file replacement modes; it is not part of the unit-test lane. +Windows release qualification also runs [directory and replacement checks](scripts/smoke-windows.ps1) manually after the Desktop build. Set `$Makensis`, `$SevenZip`, and `$PluginDir` to the pinned builder’s NSIS compiler, 7-Zip executable, and x86-unicode NSIS plugin directory; pass the prepared `window-frame.dll` as `-FrameLibrary` to exercise the native extraction path and its failure report as well. From the repository root, run the command below. It verifies directory replacement and rollback, and both locked-file replacement modes; it is not part of the unit-test lane. ```powershell -pwsh -NoProfile -File apps/desktop/scripts/smoke-windows.ps1 -Makensis $Makensis -SevenZip $SevenZip -PluginDir $PluginDir +pwsh -NoProfile -File apps/desktop/scripts/smoke-windows.ps1 -Makensis $Makensis -SevenZip $SevenZip -PluginDir $PluginDir -FrameLibrary apps/desktop/.desktop-build/targets/win-x64/installer-ui/window-frame.dll ``` The Windows installer extracts the new version beside the installation directory, stops the old application, and replaces directories through same-volume renames. Same-path upgrades preserve the old directory until promotion succeeds; extraction failure leaves it intact, and promotion failure attempts to restore it. The installer removes the old backup before launch. Forced termination or power loss can leave `.new-*` or `.old-*` directories; installation-location and scope migrations retain electron-builder's old-uninstaller flow. +When extraction fails, the installer writes a report with the 7-Zip result and its complete error output to `%LOCALAPPDATA%\deepseek harness-updater\installer-logs\extract-failure-.log` and shows the first error line with a **Copy error details** button; silent installs write only the report. Unsigned Windows builds (`DSH_DESKTOP_UNSIGNED=1`) name their installer `deepseek-harness--win-x64-unsigned.exe` so they cannot be mistaken for release artifacts. + ### Upload updates diff --git a/apps/desktop/README.zh.md b/apps/desktop/README.zh.md index e63557e98c..d78fc7ada2 100644 --- a/apps/desktop/README.zh.md +++ b/apps/desktop/README.zh.md @@ -190,14 +190,16 @@ Desktop 在本地打包工作区包,并通过目标捆绑的 Node 和 pnpm 安 打包应用运行编译后的 JavaScript 和预生成的 Typert 元数据,不编译 TypeScript 插件。源码级调试导航和编辑器声明仍可从开发包中获取。[复制规则测试](tests/runtime-file-policy.spec.ts)覆盖排除项和保留资源;[产物 smoke](tests/fixtures/runtime-payload-smoke.mjs) 在 Host smoke 和最终清单验证之前,使用 Electron RunAsNode 执行。产物 smoke 解析搜索工具使用的 ripgrep 可执行文件,并验证文本搜索和文件枚举。Windows 签名构建在依赖签名后运行这些检查;其他构建在 `prepare:dsh` 中运行。[Host smoke](scripts/smoke-runtime.ts) 使用捆绑的 Python 创建 DOCX、XLSX 和 PPTX 输入,通过真实 Office 提供方逐一转换并检查 PDF 输出。每个组装后的应用(包括目录包和 Windows 未签名构建)都会针对 ASAR 重复产物和 Host 检查。归档完整性检查将归档内完整描述符与准备结果比对,并核对归档和解包目录中的文件内容与清单、归档内文件记录的执行标志,以及解包文件的物理权限。转换失败会在写入发布记录前终止打包;macOS DMG/ZIP 构建在公证前执行这些检查。 -Windows 发布验收还需在 Desktop 构建后手动运行[目录和替换检查](scripts/smoke-windows.ps1)。将 `$Makensis`、`$SevenZip` 和 `$PluginDir` 分别设为锁定版本构建器的 NSIS 编译器、7-Zip 可执行文件和 x86-unicode NSIS 插件目录。从仓库根目录运行以下命令。它验证 目录替换与回滚和两种文件占用替换方式;不属于单元测试通道。 +Windows 发布验收还需在 Desktop 构建后手动运行[目录和替换检查](scripts/smoke-windows.ps1)。将 `$Makensis`、`$SevenZip` 和 `$PluginDir` 分别设为锁定版本构建器的 NSIS 编译器、7-Zip 可执行文件和 x86-unicode NSIS 插件目录;通过 `-FrameLibrary` 传入已准备好的 `window-frame.dll`,即可同时覆盖原生解压路径及其失败报告。从仓库根目录运行以下命令。它验证 目录替换与回滚和两种文件占用替换方式;不属于单元测试通道。 ```powershell -pwsh -NoProfile -File apps/desktop/scripts/smoke-windows.ps1 -Makensis $Makensis -SevenZip $SevenZip -PluginDir $PluginDir +pwsh -NoProfile -File apps/desktop/scripts/smoke-windows.ps1 -Makensis $Makensis -SevenZip $SevenZip -PluginDir $PluginDir -FrameLibrary apps/desktop/.desktop-build/targets/win-x64/installer-ui/window-frame.dll ``` Windows 安装器先将新版本解压到安装目录旁边,再退出旧应用并通过同卷目录改名完成替换。同路径升级在替换成功前保留旧目录;解压失败时旧版不变,替换失败时尝试恢复旧目录。安装器在启动前清理旧版备份。强制结束安装器或断电可能留下 `.new-*` 或 `.old-*` 目录;不同安装位置或安装范围迁移仍使用 electron-builder 的旧卸载器流程。 +解压失败时,安装器会把 7-Zip 的结果和完整错误输出写入 `%LOCALAPPDATA%\deepseek harness-updater\installer-logs\extract-failure-<时间戳>.log`,并在弹窗中显示首条错误行和 **复制错误信息** 按钮;静默安装只写入报告。未签名的 Windows 构建(`DSH_DESKTOP_UNSIGNED=1`)会将安装包命名为 `deepseek-harness-<版本>-win-x64-unsigned.exe`,以免被误当作发布产物。 + ### 上传更新 diff --git a/apps/desktop/electron-builder.config.d.mts b/apps/desktop/electron-builder.config.d.mts index c35e702674..d1cae61b6a 100644 --- a/apps/desktop/electron-builder.config.d.mts +++ b/apps/desktop/electron-builder.config.d.mts @@ -3,6 +3,7 @@ import type { AfterPackContext, BeforePackContext } from 'app-builder-lib' /** Electron-builder fields asserted by the Desktop release tests. */ export interface DesktopElectronBuilderConfig { readonly appId: string + readonly artifactName: string readonly protocols: readonly [{ readonly name: 'DeepSeek Harness'; readonly schemes: readonly ['dsh'] }] readonly directories: { readonly output: string diff --git a/apps/desktop/installer/extract-report.h b/apps/desktop/installer/extract-report.h new file mode 100644 index 0000000000..eb83f431a5 --- /dev/null +++ b/apps/desktop/installer/extract-report.h @@ -0,0 +1,277 @@ +// 7-Zip's error output is the primary evidence for an extraction failure; the report preserves it verbatim +// on disk and in the clipboard while the dialog shows only a headline and a bounded excerpt. +#pragma once +#include +#include +#include +#include +#include +#include + +namespace extract_report { + +constexpr size_t kOutputLimit = 256 * 1024; +constexpr size_t kHeadlineLimit = 160; +constexpr size_t kExcerptLineLimit = 120; +constexpr size_t kExcerptLines = 10; +constexpr size_t kExcerptChars = 1000; + +// Exit codes documented by 7-Zip; the installer treats every non-zero value as fatal. +inline const wchar_t* SevenZipMeaning(int code) { + switch (code) { + case 1: return L"warning: some files were not extracted"; + case 2: return L"fatal error"; + case 7: return L"command line error"; + case 8: return L"not enough memory"; + case 255: return L"stopped before completion"; + default: return L"unexpected exit code"; + } +} + +inline std::wstring Trim(const std::wstring& text) { + const auto begin = text.find_first_not_of(L" \t\r\n"); + if (begin == std::wstring::npos) return L""; + const auto end = text.find_last_not_of(L" \t\r\n"); + return text.substr(begin, end - begin + 1); +} + +inline std::vector Lines(const std::wstring& text) { + std::vector lines; + size_t start = 0; + while (start <= text.size()) { + const auto end = text.find(L'\n', start); + std::wstring line = text.substr(start, end == std::wstring::npos ? std::wstring::npos : end - start); + if (!line.empty() && line.back() == L'\r') line.pop_back(); + lines.push_back(line); + if (end == std::wstring::npos) break; + start = end + 1; + } + return lines; +} + +constexpr wchar_t kEllipsis = 0x2026; + +inline std::wstring Truncate(const std::wstring& text, size_t limit) { + if (text.size() <= limit) return text; + return text.substr(0, limit - 1) + kEllipsis; +} + +inline std::wstring Win32Message(DWORD error) { + LPWSTR buffer = nullptr; + const DWORD length = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + nullptr, error, 0, reinterpret_cast(&buffer), 0, nullptr); + std::wstring message = length && buffer ? Trim(std::wstring(buffer, length)) : L""; + if (buffer) LocalFree(buffer); + return message; +} + +// Positive results are 7-Zip exit codes; negative results are negated Win32 errors from launching or supervising it. +inline std::wstring DescribeResult(int code) { + if (code >= 0) return L"7-Zip exit code " + std::to_wstring(code) + L" (" + SevenZipMeaning(code) + L")"; + const DWORD error = static_cast(-static_cast(code)); + std::wstring message = Win32Message(error); + return L"Windows error " + std::to_wstring(error) + L" while running 7-Zip" + (message.empty() ? L"" : L" (" + message + L")"); +} + +// 7-Zip prefixes the failing operation and path with "ERROR:"; the bare archive name it prints first says nothing. +inline std::wstring Headline(int code, const std::wstring& output) { + std::wstring fallback; + for (const std::wstring& raw : Lines(output)) { + const std::wstring line = Trim(raw); + const auto marker = line.find(L"ERROR"); + if (marker == std::wstring::npos) continue; + const std::wstring detail = Trim(line.substr(line.find(L':', marker) == std::wstring::npos ? line.size() : line.find(L':', marker) + 1)); + if (detail.empty()) continue; + if (detail.find(L" : ") != std::wstring::npos || detail.find(L' ') != std::wstring::npos) return Truncate(line, kHeadlineLimit); + if (fallback.empty()) fallback = line; + } + if (!fallback.empty()) return Truncate(fallback, kHeadlineLimit); + return DescribeResult(code); +} + +inline std::wstring Compose(int code, const std::wstring& archive, const std::wstring& destination, const std::wstring& output, + const std::wstring& timestamp, const std::wstring& windowsVersion) { + std::wstring report = L"DeepSeek Harness installer: extraction failed\r\n"; + report += L"Time: " + timestamp + L"\r\n"; + report += L"Result: " + DescribeResult(code) + L"\r\n"; + report += L"Archive: " + archive + L"\r\n"; + report += L"Destination: " + destination + L"\r\n"; + report += L"Windows: " + windowsVersion + L"\r\n"; + report += L"\r\n7-Zip output:\r\n"; + const std::wstring trimmed = Trim(output); + if (trimmed.empty()) { + report += L"(none)\r\n"; + } else { + for (const std::wstring& line : Lines(trimmed)) report += line + L"\r\n"; + } + return report; +} + +// The dialog stays compact: long lines are cut and a trailing note counts what the report still holds. +inline std::wstring Excerpt(const std::wstring& report, size_t maxLines = kExcerptLines, size_t maxChars = kExcerptChars) { + const std::vector lines = Lines(Trim(report)); + std::wstring excerpt; + size_t shown = 0; + for (const std::wstring& line : lines) { + const std::wstring cut = Truncate(line, kExcerptLineLimit); + if (shown == maxLines || excerpt.size() + cut.size() + 2 > maxChars) break; + excerpt += (shown ? L"\r\n" : L"") + cut; + ++shown; + } + if (shown < lines.size()) { + excerpt += L"\r\n" + std::wstring(1, kEllipsis) + L" (" + std::to_wstring(lines.size() - shown) + L" more lines in the saved report)"; + } + return excerpt; +} + +inline std::wstring Decode(const std::string& bytes) { + if (bytes.empty()) return L""; + for (UINT codePage : {static_cast(CP_UTF8), static_cast(CP_ACP)}) { + const DWORD flags = codePage == CP_UTF8 ? MB_ERR_INVALID_CHARS : 0; + const int length = MultiByteToWideChar(codePage, flags, bytes.data(), static_cast(bytes.size()), nullptr, 0); + if (length <= 0) continue; + std::wstring text(static_cast(length), L'\0'); + MultiByteToWideChar(codePage, flags, bytes.data(), static_cast(bytes.size()), &text[0], length); + return text; + } + return L"(undecodable 7-Zip output)"; +} + +inline std::wstring ReadOutput(LPCWSTR path) { + HANDLE file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); + if (file == INVALID_HANDLE_VALUE) return L""; + std::string bytes; + char buffer[8192]; + DWORD count = 0; + while (bytes.size() < kOutputLimit && ReadFile(file, buffer, sizeof(buffer), &count, nullptr) && count) { + bytes.append(buffer, std::min(count, kOutputLimit - bytes.size())); + } + CloseHandle(file); + return Decode(bytes); +} + +inline std::wstring Timestamp() { + SYSTEMTIME now; + GetLocalTime(&now); + WCHAR text[32]; + wsprintfW(text, L"%04u-%02u-%02u %02u:%02u:%02u", now.wYear, now.wMonth, now.wDay, now.wHour, now.wMinute, now.wSecond); + return text; +} + +inline std::wstring WindowsVersion() { + typedef LONG(WINAPI * RtlGetVersionFn)(PRTL_OSVERSIONINFOW); + HMODULE ntdll = GetModuleHandleW(L"ntdll.dll"); + auto getVersion = ntdll ? reinterpret_cast(GetProcAddress(ntdll, "RtlGetVersion")) : nullptr; + RTL_OSVERSIONINFOW info = {}; + info.dwOSVersionInfoSize = sizeof(info); + if (!getVersion || getVersion(&info) != 0) return L"unknown"; + WCHAR text[64]; + wsprintfW(text, L"%u.%u.%u", info.dwMajorVersion, info.dwMinorVersion, info.dwBuildNumber); + return text; +} + +inline bool WriteUtf8(LPCWSTR path, const std::wstring& text) { + std::wstring directory(path); + const auto separator = directory.find_last_of(L"\\/"); + if (separator != std::wstring::npos) { + directory.resize(separator); + const int created = SHCreateDirectoryExW(nullptr, directory.c_str(), nullptr); + if (created != ERROR_SUCCESS && created != ERROR_ALREADY_EXISTS && created != ERROR_FILE_EXISTS) return false; + } + const int length = WideCharToMultiByte(CP_UTF8, 0, text.data(), static_cast(text.size()), nullptr, 0, nullptr, nullptr); + if (length <= 0) return false; + std::string bytes("\xEF\xBB\xBF", 3); + bytes.resize(3 + static_cast(length)); + WideCharToMultiByte(CP_UTF8, 0, text.data(), static_cast(text.size()), &bytes[3], length, nullptr, nullptr); + HANDLE file = CreateFileW(path, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); + if (file == INVALID_HANDLE_VALUE) return false; + DWORD written = 0; + const bool complete = WriteFile(file, bytes.data(), static_cast(bytes.size()), &written, nullptr) && written == bytes.size(); + CloseHandle(file); + return complete; +} + +inline bool CopyToClipboard(HWND owner, const std::wstring& text) { + const size_t bytes = (text.size() + 1) * sizeof(wchar_t); + HGLOBAL memory = GlobalAlloc(GMEM_MOVEABLE, bytes); + if (!memory) return false; + void* target = GlobalLock(memory); + if (!target) { GlobalFree(memory); return false; } + memcpy(target, text.c_str(), bytes); + GlobalUnlock(memory); + bool copied = false; + for (int attempt = 0; attempt < 5 && !copied; ++attempt) { + if (attempt) Sleep(50); + if (!OpenClipboard(owner)) continue; + copied = EmptyClipboard() && SetClipboardData(CF_UNICODETEXT, memory) != nullptr; + CloseClipboard(); + } + if (!copied) GlobalFree(memory); + return copied; +} + +struct DialogStrings { + LPCWSTR title; + LPCWSTR heading; + LPCWSTR copy; + LPCWSTR expand; + LPCWSTR collapse; + LPCWSTR footer; + LPCWSTR copied; +}; + +struct DialogState { + const std::wstring* report; + const DialogStrings* strings; +}; + +constexpr int kCopyButton = 1001; + +inline HRESULT CALLBACK DialogCallback(HWND dialog, UINT notification, WPARAM wparam, LPARAM, LONG_PTR data) { + auto* state = reinterpret_cast(data); + if (notification == TDN_BUTTON_CLICKED && static_cast(wparam) == kCopyButton && state) { + if (CopyToClipboard(dialog, *state->report)) { + SendMessageW(dialog, TDM_SET_ELEMENT_TEXT, TDE_FOOTER, reinterpret_cast(state->strings->copied)); + } + return S_FALSE; + } + return S_OK; +} + +// The task dialog comes from the comctl32 v6 the installer already loads; without it a message box carries the headline. +inline void Show(HWND parent, const std::wstring& headline, const std::wstring& excerpt, const std::wstring& report, const DialogStrings& strings) { + typedef HRESULT(WINAPI * TaskDialogIndirectFn)(const TASKDIALOGCONFIG*, int*, int*, BOOL*); + HMODULE comctl = GetModuleHandleW(L"comctl32.dll"); + if (!comctl) comctl = LoadLibraryW(L"comctl32.dll"); + auto taskDialog = comctl ? reinterpret_cast(GetProcAddress(comctl, "TaskDialogIndirect")) : nullptr; + if (taskDialog) { + DialogState state{&report, &strings}; + TASKDIALOG_BUTTON buttons[] = {{kCopyButton, strings.copy}}; + TASKDIALOGCONFIG config = {}; + config.cbSize = sizeof(config); + config.hwndParent = parent; + config.dwFlags = TDF_ALLOW_DIALOG_CANCELLATION | TDF_POSITION_RELATIVE_TO_WINDOW; + config.dwCommonButtons = TDCBF_OK_BUTTON; + config.pszWindowTitle = strings.title; + config.pszMainIcon = TD_WARNING_ICON; + config.pszMainInstruction = strings.heading; + config.pszContent = headline.c_str(); + config.cButtons = 1; + config.pButtons = buttons; + config.nDefaultButton = IDOK; + config.pszExpandedInformation = excerpt.c_str(); + config.pszExpandedControlText = strings.collapse; + config.pszCollapsedControlText = strings.expand; + config.pszFooterIcon = TD_INFORMATION_ICON; + config.pszFooter = strings.footer; + config.pfCallback = DialogCallback; + config.lpCallbackData = reinterpret_cast(&state); + config.cxWidth = 320; + int pressed = 0; + if (SUCCEEDED(taskDialog(&config, &pressed, nullptr, nullptr))) return; + } + const std::wstring text = std::wstring(strings.heading) + L"\r\n\r\n" + headline + L"\r\n\r\n" + strings.footer; + MessageBoxW(parent, text.c_str(), strings.title, MB_OK | MB_ICONEXCLAMATION | MB_SETFOREGROUND); +} + +} // namespace extract_report diff --git a/apps/desktop/installer/extract.h b/apps/desktop/installer/extract.h index 86c5161824..af30077912 100644 --- a/apps/desktop/installer/extract.h +++ b/apps/desktop/installer/extract.h @@ -1,5 +1,6 @@ // The pinned 7-Zip executable owns extraction; this pipe reader publishes its work percentage. #pragma once +#include #include #include #include "extract-progress.h" @@ -32,25 +33,30 @@ struct InstallerAttributes { } }; -static DWORD ExtractApplication(HWND parent, LPCWSTR tool, LPCWSTR archive, LPCWSTR destination, LPCWSTR log) { +// Win32 failures around the 7-Zip process return negated error codes so they never collide with 7-Zip's exit codes. +static int LaunchFailure(DWORD error) { + return -static_cast(error ? error : ERROR_GEN_FAILURE); +} + +static int ExtractApplication(HWND parent, LPCWSTR tool, LPCWSTR archive, LPCWSTR destination, LPCWSTR log) { SECURITY_ATTRIBUTES security = {sizeof(security), nullptr, TRUE}; InstallerHandle input, output; - if (!CreatePipe(&input.value, &output.value, &security, 0)) return GetLastError(); - if (!SetHandleInformation(input.value, HANDLE_FLAG_INHERIT, 0)) return GetLastError(); + if (!CreatePipe(&input.value, &output.value, &security, 0)) return LaunchFailure(GetLastError()); + if (!SetHandleInformation(input.value, HANDLE_FLAG_INHERIT, 0)) return LaunchFailure(GetLastError()); InstallerHandle errors(CreateFileW(log, GENERIC_WRITE, FILE_SHARE_READ, &security, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr)); - if (errors.value == INVALID_HANDLE_VALUE) return GetLastError(); + if (errors.value == INVALID_HANDLE_VALUE) return LaunchFailure(GetLastError()); InstallerHandle nullInput(CreateFileW(L"NUL", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, &security, OPEN_EXISTING, 0, nullptr)); - if (nullInput.value == INVALID_HANDLE_VALUE) return GetLastError(); + if (nullInput.value == INVALID_HANDLE_VALUE) return LaunchFailure(GetLastError()); InstallerHandle job(CreateJobObjectW(nullptr, nullptr)); - if (!job.value) return GetLastError(); + if (!job.value) return LaunchFailure(GetLastError()); JOBOBJECT_EXTENDED_LIMIT_INFORMATION limits = {}; limits.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; - if (!SetInformationJobObject(job.value, JobObjectExtendedLimitInformation, &limits, sizeof(limits))) return GetLastError(); + if (!SetInformationJobObject(job.value, JobObjectExtendedLimitInformation, &limits, sizeof(limits))) return LaunchFailure(GetLastError()); InstallerAttributes attributes; - if (!attributes.Initialize()) return GetLastError(); + if (!attributes.Initialize()) return LaunchFailure(GetLastError()); HANDLE inherited[] = {nullInput.value, output.value, errors.value}; if (!UpdateProcThreadAttribute(attributes.list, 0, PROC_THREAD_ATTRIBUTE_HANDLE_LIST, inherited, sizeof(inherited), nullptr, nullptr) || - !UpdateProcThreadAttribute(attributes.list, 0, PROC_THREAD_ATTRIBUTE_JOB_LIST, &job.value, sizeof(job.value), nullptr, nullptr)) return GetLastError(); + !UpdateProcThreadAttribute(attributes.list, 0, PROC_THREAD_ATTRIBUTE_JOB_LIST, &job.value, sizeof(job.value), nullptr, nullptr)) return LaunchFailure(GetLastError()); STARTUPINFOEXW startup = {}; startup.StartupInfo.cb = sizeof(startup); startup.StartupInfo.dwFlags = STARTF_USESTDHANDLES; @@ -59,10 +65,11 @@ static DWORD ExtractApplication(HWND parent, LPCWSTR tool, LPCWSTR archive, LPCW startup.StartupInfo.hStdError = errors.value; startup.lpAttributeList = attributes.list; // A final dot prevents a destination's trailing backslash from escaping its closing quote. - std::wstring command = L"\"" + std::wstring(tool) + L"\" x -y -bso0 -bse2 -bsp1 -bb0 \"-o" + destination + L"\\.\" \"" + archive + L"\""; + // Error output is UTF-8 so the failure report can quote paths from any code page. + std::wstring command = L"\"" + std::wstring(tool) + L"\" x -y -bso0 -bse2 -bsp1 -bb0 -sccUTF-8 \"-o" + destination + L"\\.\" \"" + archive + L"\""; PROCESS_INFORMATION child = {}; if (!CreateProcessW(tool, &command[0], nullptr, nullptr, TRUE, - EXTENDED_STARTUPINFO_PRESENT | CREATE_NO_WINDOW, nullptr, nullptr, &startup.StartupInfo, &child)) return GetLastError(); + EXTENDED_STARTUPINFO_PRESENT | CREATE_NO_WINDOW, nullptr, nullptr, &startup.StartupInfo, &child)) return LaunchFailure(GetLastError()); InstallerHandle process(child.hProcess), thread(child.hThread); output.Close(); errors.Close(); @@ -79,17 +86,18 @@ static DWORD ExtractApplication(HWND parent, LPCWSTR tool, LPCWSTR archive, LPCW if (readError != ERROR_BROKEN_PIPE && readError != ERROR_SUCCESS) { TerminateJobObject(job.value, readError); WaitForSingleObject(process.value, INFINITE); - return readError; + return LaunchFailure(readError); } - if (WaitForSingleObject(process.value, INFINITE) != WAIT_OBJECT_0) return GetLastError(); + if (WaitForSingleObject(process.value, INFINITE) != WAIT_OBJECT_0) return LaunchFailure(GetLastError()); DWORD result; - if (!GetExitCodeProcess(process.value, &result)) return GetLastError(); + if (!GetExitCodeProcess(process.value, &result)) return LaunchFailure(GetLastError()); if (result == 0 && parent) SetPropW(parent, L"HarnessInstaller.ExtractProgress", reinterpret_cast(100)); - return result; + return result > INT_MAX ? INT_MAX : static_cast(result); } // Runs on the NSIS worker; only an exit code of zero permits directory promotion. -extern "C" __declspec(dllexport) DWORD __cdecl InstallerExtract(HWND parent, LPCWSTR tool, LPCWSTR archive, LPCWSTR destination, LPCWSTR log) { +// Positive results are 7-Zip exit codes; negative results are negated Win32 errors from launching or supervising it. +extern "C" __declspec(dllexport) int __cdecl InstallerExtract(HWND parent, LPCWSTR tool, LPCWSTR archive, LPCWSTR destination, LPCWSTR log) { try { return ExtractApplication(parent, tool, archive, destination, log); } - catch (const std::bad_alloc&) { return ERROR_NOT_ENOUGH_MEMORY; } + catch (const std::bad_alloc&) { return LaunchFailure(ERROR_NOT_ENOUGH_MEMORY); } } diff --git a/apps/desktop/installer/strings.nsh b/apps/desktop/installer/strings.nsh index bea3ac97d9..f2f2b08191 100644 --- a/apps/desktop/installer/strings.nsh +++ b/apps/desktop/installer/strings.nsh @@ -39,3 +39,19 @@ LangString INSTALLER_DISK_SPACE ${LANG_ENGLISH} "There is not enough free disk s LangString INSTALLER_DISK_SPACE ${LANG_SIMPCHINESE} "此磁盘的可用空间不足,请选择其他位置。" LangString INSTALLER_PER_USER ${LANG_ENGLISH} "This installer supports the current user only. Uninstall the existing all-users installation first." LangString INSTALLER_PER_USER ${LANG_SIMPCHINESE} "此安装程序仅支持当前用户。请先卸载已有的所有用户安装版本。" +LangString INSTALLER_EXTRACT_FAILED ${LANG_ENGLISH} "The application files could not be extracted." +LangString INSTALLER_EXTRACT_FAILED ${LANG_SIMPCHINESE} "无法解压应用程序文件。" +LangString INSTALLER_EXTRACT_HINT ${LANG_ENGLISH} "Security software may have blocked a file, or the disk may be full. Close this installer and try again. If it keeps failing, send us the error details below." +LangString INSTALLER_EXTRACT_HINT ${LANG_SIMPCHINESE} "可能是安全软件拦截了文件,或磁盘空间不足。请关闭安装程序后重试;如仍然失败,请将下方错误信息发送给我们。" +LangString INSTALLER_EXTRACT_COPY ${LANG_ENGLISH} "Copy error details" +LangString INSTALLER_EXTRACT_COPY ${LANG_SIMPCHINESE} "复制错误信息" +LangString INSTALLER_EXTRACT_EXPAND ${LANG_ENGLISH} "Show details" +LangString INSTALLER_EXTRACT_EXPAND ${LANG_SIMPCHINESE} "显示详情" +LangString INSTALLER_EXTRACT_COLLAPSE ${LANG_ENGLISH} "Hide details" +LangString INSTALLER_EXTRACT_COLLAPSE ${LANG_SIMPCHINESE} "隐藏详情" +LangString INSTALLER_EXTRACT_SAVED ${LANG_ENGLISH} "The full report was saved to %s" +LangString INSTALLER_EXTRACT_SAVED ${LANG_SIMPCHINESE} "完整错误报告已保存到 %s" +LangString INSTALLER_EXTRACT_UNSAVED ${LANG_ENGLISH} "The full report could not be saved. Use Copy error details to keep it." +LangString INSTALLER_EXTRACT_UNSAVED ${LANG_SIMPCHINESE} "无法保存完整错误报告,请使用“复制错误信息”保留。" +LangString INSTALLER_EXTRACT_COPIED ${LANG_ENGLISH} "Error details were copied to the clipboard." +LangString INSTALLER_EXTRACT_COPIED ${LANG_SIMPCHINESE} "错误信息已复制到剪贴板。" diff --git a/apps/desktop/installer/window-frame.cpp b/apps/desktop/installer/window-frame.cpp index 7f47563e81..0a81fae33e 100644 --- a/apps/desktop/installer/window-frame.cpp +++ b/apps/desktop/installer/window-frame.cpp @@ -12,10 +12,35 @@ #include #include "progress.h" #include "extract.h" +#include "extract-report.h" #include "uninstall-data.h" using namespace Gdiplus; +// Saves the extraction failure report and, unless silent, presents its headline with a copy action. +// Returns 1 when the report file was written and 0 otherwise; the dialog outcome never fails the caller. +extern "C" __declspec(dllexport) int __cdecl InstallerReportExtractFailure( + HWND parent, int code, LPCWSTR archive, LPCWSTR destination, LPCWSTR log, LPCWSTR reportPath, int show, + LPCWSTR title, LPCWSTR heading, LPCWSTR hint, LPCWSTR copy, LPCWSTR expand, LPCWSTR collapse, LPCWSTR savedFormat, LPCWSTR unsaved, LPCWSTR copied) { + try { + const std::wstring output = extract_report::ReadOutput(log); + const std::wstring report = extract_report::Compose(code, archive, destination, output, + extract_report::Timestamp(), extract_report::WindowsVersion()); + const bool saved = extract_report::WriteUtf8(reportPath, report); + if (show) { + std::wstring footer = saved ? savedFormat : unsaved; + const auto placeholder = footer.find(L"%s"); + if (saved && placeholder != std::wstring::npos) footer.replace(placeholder, 2, reportPath); + const extract_report::DialogStrings strings{title, heading, copy, expand, collapse, footer.c_str(), copied}; + const std::wstring content = extract_report::Headline(code, output) + L"\r\n\r\n" + hint; + extract_report::Show(parent, content, extract_report::Excerpt(report), report, strings); + } + return saved ? 1 : 0; + } catch (const std::bad_alloc&) { + return 0; + } +} + // Returns a Win32 error code; no cleanup request may traverse a linked root or touch the protected root. extern "C" __declspec(dllexport) DWORD __cdecl UninstallRemoveData(LPCWSTR path, LPCWSTR installation, LPCWSTR protectedRoot) { return uninstall_data::Remove(path, installation, protectedRoot); diff --git a/apps/desktop/scripts/desktop-build-version-discovery.ts b/apps/desktop/scripts/desktop-build-version-discovery.ts index 32ed5a37b2..6bb7a1b045 100644 --- a/apps/desktop/scripts/desktop-build-version-discovery.ts +++ b/apps/desktop/scripts/desktop-build-version-discovery.ts @@ -30,8 +30,8 @@ const LISTING_DEADLINE_MS = 8_000 /** Objects one listing page may return. */ const LISTING_PAGE_SIZE = 1000 -/** Artifact name electron-builder writes for one build, on either platform. */ -const ARTIFACT = /(?:^|\/)deepseek-harness-(?.+)-(?:mac|win)-(?:arm64|x64)\.(?:exe|dmg|zip)$/u +/** Artifact name electron-builder writes for one build, on either platform; unsigned Windows builds add a suffix. */ +const ARTIFACT = /(?:^|\/)deepseek-harness-(?.+)-(?:mac|win)-(?:arm64|x64)(?:-unsigned)?\.(?:exe|dmg|zip)$/u /** Inputs that decide which versions are already taken. */ export interface DesktopBuildVersionSuggestionOptions { diff --git a/apps/desktop/scripts/electron-builder-config.mjs b/apps/desktop/scripts/electron-builder-config.mjs index e3873de35f..2cee72d23d 100644 --- a/apps/desktop/scripts/electron-builder-config.mjs +++ b/apps/desktop/scripts/electron-builder-config.mjs @@ -106,7 +106,8 @@ export function createElectronBuilderConfig( ...packaged === undefined ? {} : { dshBuildCommit: packaged.commit, dshBuildDirty: packaged.dirty }, }, productName: 'DeepSeek Harness', - artifactName: 'deepseek-harness-${version}-${os}-${arch}.${ext}', + // Unsigned builds carry their own suffix so a shared file can never pass for a release artifact. + artifactName: `deepseek-harness-\${version}-\${os}-\${arch}${unsigned ? '-unsigned' : ''}.\${ext}`, directories: { output: unsigned ? buildPaths.unsignedArtifacts : buildPaths.artifacts }, asar: true, electronDist: buildPaths.electron, diff --git a/apps/desktop/scripts/installer-directories.nsh b/apps/desktop/scripts/installer-directories.nsh index 881bdc8b20..49d4a2fb82 100644 --- a/apps/desktop/scripts/installer-directories.nsh +++ b/apps/desktop/scripts/installer-directories.nsh @@ -17,7 +17,11 @@ Var dshNewMoved ${If} $R0 != 0 DetailPrint $R1 Call dshRollbackDirectories - MessageBox MB_OK|MB_ICONEXCLAMATION "$(decompressionFailed)" /SD IDOK + !ifmacrodef customInstallerExtractFailed + !insertmacro customInstallerExtractFailed "${FILE}" + !else + MessageBox MB_OK|MB_ICONEXCLAMATION "$(decompressionFailed)" /SD IDOK + !endif SetErrorLevel 2 Quit ${EndIf} diff --git a/apps/desktop/scripts/installer.nsh b/apps/desktop/scripts/installer.nsh index 8d0378ebc0..7ddda5aa85 100644 --- a/apps/desktop/scripts/installer.nsh +++ b/apps/desktop/scripts/installer.nsh @@ -1,4 +1,5 @@ !include "LogicLib.nsh" +!include "FileFunc.nsh" !define INSTALLER_SOURCE_DIR "${__FILEDIR__}\..\installer" !define /ifndef INSTALLER_BUILD_DIR "${__FILEDIR__}\..\.desktop-build\targets\win-x64\installer-ui" @@ -132,6 +133,38 @@ ManifestDPIAware true ${EndIf} !macroend +; The report outlives $PLUGINSDIR so a user can send it; silent installs keep only the file. +!ifndef DSH_INSTALLER_LOG_DIR + !define DSH_INSTALLER_LOG_DIR "$LOCALAPPDATA\${DSH_UPDATER_CACHE_NAME}\installer-logs" +!endif + +!macro customInstallerExtractFailed Archive + Push $0 + Push $1 + Push $2 + Push $3 + Push $4 + Push $5 + Push $6 + ${GetTime} "" "L" $0 $1 $2 $3 $4 $5 $6 + StrCpy $0 "${DSH_INSTALLER_LOG_DIR}\extract-failure-$2$1$0-$4$5$6.log" + StrCpy $1 1 + ${If} ${Silent} + StrCpy $1 0 + ${EndIf} + System::Call '$PLUGINSDIR\window-frame.dll::InstallerReportExtractFailure(p $HWNDPARENT, i R0, w "${Archive}", w "$dshNewDirectory", w "$PLUGINSDIR\extract.log", w r0, i r1, w "$(^SetupCaption)", w "$(INSTALLER_EXTRACT_FAILED)", w "$(INSTALLER_EXTRACT_HINT)", w "$(INSTALLER_EXTRACT_COPY)", w "$(INSTALLER_EXTRACT_EXPAND)", w "$(INSTALLER_EXTRACT_COLLAPSE)", w "$(INSTALLER_EXTRACT_SAVED)", w "$(INSTALLER_EXTRACT_UNSAVED)", w "$(INSTALLER_EXTRACT_COPIED)") i.r2 ?c' + ${If} $2 == 1 + DetailPrint $0 + ${EndIf} + Pop $6 + Pop $5 + Pop $4 + Pop $3 + Pop $2 + Pop $1 + Pop $0 +!macroend + !macro customCheckAppRunning !ifdef BUILD_UNINSTALLER InitPluginsDir diff --git a/apps/desktop/scripts/prepare-windows-installer.ps1 b/apps/desktop/scripts/prepare-windows-installer.ps1 index 0209e74d78..98e02cf9a6 100644 --- a/apps/desktop/scripts/prepare-windows-installer.ps1 +++ b/apps/desktop/scripts/prepare-windows-installer.ps1 @@ -50,6 +50,16 @@ if ($TestProgress -or $CompileProgressOnly) { & $presentationExecutable if ($LASTEXITCODE -ne 0) { throw 'Installer presentation regression failed.' } } + $reportSource = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../tests/windows-installer-extract-report.cpp')) + $reportExecutable = Join-Path $output 'extract-report-test.exe' + $reportScript = Join-Path $output 'compile-extract-report-test.cmd' + [IO.File]::WriteAllLines($reportScript, @('@echo off', ('call "{0}" >nul' -f $vcvars), 'if errorlevel 1 exit /b %errorlevel%', ('cl /nologo /MT /W4 /WX /EHsc "{0}" /Fo"{1}" /Fe"{2}" /link "{3}" user32.lib shell32.lib' -f $reportSource, (Join-Path $output 'extract-report-test.obj'), $reportExecutable, (Join-Path $output 'window-frame.lib'))), [Text.Encoding]::Default) + & $env:ComSpec /d /c $reportScript + if ($LASTEXITCODE -ne 0) { throw 'Extraction report test compilation failed.' } + if ($TestProgress) { + & $reportExecutable + if ($LASTEXITCODE -ne 0) { throw 'Extraction report regression failed.' } + } } Add-Type -AssemblyName System.Drawing foreach ($asset in @('brand', 'brand-2x', 'brand-dark', 'brand-dark-2x', 'uninstaller-sidebar')) { diff --git a/apps/desktop/scripts/smoke-installer-directories.ps1 b/apps/desktop/scripts/smoke-installer-directories.ps1 index 2fa8eabfb5..283f168016 100644 --- a/apps/desktop/scripts/smoke-installer-directories.ps1 +++ b/apps/desktop/scripts/smoke-installer-directories.ps1 @@ -42,8 +42,9 @@ try { } $probe = Join-Path $caseRoot 'probe.exe' $caseArchive = if ($mode -eq 'broken') { $brokenArchive } else { $archive } + $reportDir = Join-Path $caseRoot 'installer-logs' $compileArgs = @('/V2', "/DOUTPUT_FILE=$probe", "/DPAYLOAD_FILE=$caseArchive", "/DTARGET_DIR=$target", "/DDSH_SEVENZIP_PATH=$SevenZip") - if ($FrameLibrary) { $compileArgs += "/DSOURCE_DLL=$FrameLibrary" } + if ($FrameLibrary) { $compileArgs += @("/DSOURCE_DLL=$FrameLibrary", "/DREPORT_DIR=$reportDir") } if ($mode -eq 'missing-stage') { $compileArgs += '/DMISSING_STAGE' } if ($mode -eq 'cancelled') { $compileArgs += '/DCANCELLED' } Invoke-Checked $Makensis ($compileArgs + $fixture) @@ -76,9 +77,24 @@ try { if ((Test-Path -LiteralPath (Join-Path $target 'obsolete.txt')) -ne $expectObsolete) { throw "Directory smoke $mode did not preserve the expected old-only file state" } - if (@(Get-ChildItem -LiteralPath $caseRoot -Directory | Where-Object Name -ne 'Application').Count -ne 0) { + if (@(Get-ChildItem -LiteralPath $caseRoot -Directory | Where-Object Name -notin @('Application', 'installer-logs')).Count -ne 0) { throw "Directory smoke $mode left transaction directories behind" } + if ($FrameLibrary) { + # Only an extraction failure writes a report; it must quote 7-Zip's verdict so support can read the cause. + $reports = @(if (Test-Path -LiteralPath $reportDir) { Get-ChildItem -LiteralPath $reportDir -File }) + if ($mode -eq 'broken') { + if ($reports.Count -ne 1 -or $reports[0].Name -notmatch '^extract-failure-\d{8}-\d{6}\.log$') { + throw "Directory smoke $mode did not save exactly one extraction report" + } + $report = Get-Content -LiteralPath $reports[0].FullName -Raw -Encoding UTF8 + foreach ($expected in @('Result: 7-Zip exit code 2 (fatal error)', "Archive: $caseArchive", 'Cannot open the file as [7z] archive')) { + if (-not $report.Contains($expected)) { throw "Directory smoke $mode report lacks '$expected'" } + } + } elseif ($reports.Count -ne 0) { + throw "Directory smoke $mode saved an unexpected extraction report" + } + } Write-Output "Directory replacement smoke passed: $mode" } } finally { diff --git a/apps/desktop/scripts/smoke-windows.ps1 b/apps/desktop/scripts/smoke-windows.ps1 index 5f3c0372e8..8ae29ad614 100644 --- a/apps/desktop/scripts/smoke-windows.ps1 +++ b/apps/desktop/scripts/smoke-windows.ps1 @@ -2,7 +2,8 @@ param( [Parameter(Mandatory)][string]$Makensis, [Parameter(Mandatory)][string]$SevenZip, - [Parameter(Mandatory)][string]$PluginDir + [Parameter(Mandatory)][string]$PluginDir, + [string]$FrameLibrary ) $ErrorActionPreference = 'Stop' $desktopRoot = Split-Path $PSScriptRoot -Parent @@ -15,7 +16,10 @@ function Invoke-Checked([string]$Executable, [string[]]$Arguments) { } try { - & (Join-Path $PSScriptRoot 'smoke-installer-directories.ps1') -Makensis $Makensis -SevenZip $SevenZip + # The prepared window-frame.dll adds the native extraction path and its failure report to the directory checks. + $directoryArguments = @{ Makensis = $Makensis; SevenZip = $SevenZip } + if ($FrameLibrary) { $directoryArguments.FrameLibrary = $FrameLibrary } + & (Join-Path $PSScriptRoot 'smoke-installer-directories.ps1') @directoryArguments $payload = Join-Path $scratch 'payload' New-Item -ItemType Directory -Path $payload | Out-Null [System.IO.File]::WriteAllText((Join-Path $payload 'locked.txt'), 'new runtime') diff --git a/apps/desktop/tests/desktop-build-version-discovery.spec.ts b/apps/desktop/tests/desktop-build-version-discovery.spec.ts index 490227416e..8438e076ad 100644 --- a/apps/desktop/tests/desktop-build-version-discovery.spec.ts +++ b/apps/desktop/tests/desktop-build-version-discovery.spec.ts @@ -70,4 +70,13 @@ describe('desktop build version discovery', () => { await expect(suggestDesktopBuildVersion({ productVersion: PRERELEASE, target: 'mac-arm64', environment: {}, date: DATE, artifactsRoot })) .resolves.toBe(`${PRERELEASE}.${DATE}.4`) }) + + it('counts unsigned Windows artifacts written under their own suffix', async () => { + const artifactsRoot = await artifactsWith([ + `deepseek-harness-${PRERELEASE}.${DATE}.2-win-x64-unsigned.exe`, + `deepseek-harness-${PRERELEASE}.${DATE}.5-win-x64-unsigned.exe.blockmap`, + ]) + await expect(suggestDesktopBuildVersion({ productVersion: PRERELEASE, target: 'win-x64', environment: {}, date: DATE, artifactsRoot })) + .resolves.toBe(`${PRERELEASE}.${DATE}.3`) + }) }) diff --git a/apps/desktop/tests/fixtures/installer-directory-smoke.nsi b/apps/desktop/tests/fixtures/installer-directory-smoke.nsi index 2269a06d38..3afd73a433 100644 --- a/apps/desktop/tests/fixtures/installer-directory-smoke.nsi +++ b/apps/desktop/tests/fixtures/installer-directory-smoke.nsi @@ -11,6 +11,9 @@ LangString decompressionFailed ${LANG_ENGLISH} "Payload extraction failed" !insertmacro dshExtractPayload "${PAYLOAD_FILE}" !macroend !ifdef SOURCE_DLL + LoadLanguageFile "${NSISDIR}\Contrib\Language files\SimpChinese.nlf" + !include "..\..\installer\strings.nsh" + !define DSH_INSTALLER_LOG_DIR "${REPORT_DIR}" !include "..\..\scripts\installer.nsh" !else !include "..\..\scripts\installer-directories.nsh" diff --git a/apps/desktop/tests/installer-packaging.spec.ts b/apps/desktop/tests/installer-packaging.spec.ts index ef8d377e92..3e42ed5a63 100644 --- a/apps/desktop/tests/installer-packaging.spec.ts +++ b/apps/desktop/tests/installer-packaging.spec.ts @@ -57,6 +57,19 @@ describe('installer preparation preserves application dependencies', () => { } }) + it('names unsigned Windows artifacts so they cannot pass for release builds', async () => { + const { createElectronBuilderConfig } = await import('../scripts/electron-builder-config.mjs') + const config = createElectronBuilderConfig({ + DSH_DESKTOP_APP_ID: 'com.example.installer', + DSH_DESKTOP_MANDATORY_UPDATE_TEST_ORIGIN: 'https://policy.example.com', + DSH_DESKTOP_MANDATORY_UPDATE_CONFIG: JSON.stringify({ allowedAuthOrigins: ['https://login.example.com'] }), + DSH_DESKTOP_TARGET_PLATFORM: 'win32', + DSH_DESKTOP_TARGET_ARCH: 'x64', + DSH_DESKTOP_UNSIGNED: '1', + }, 'win32', 'x64') + expect(config.artifactName).toBe('deepseek-harness-${version}-${os}-${arch}-unsigned.${ext}') + }) + it('packages every preload entry point the shell loads', async () => { const { readdirSync, readFileSync } = await import('node:fs') const sourceDirectory = new URL('../src/', import.meta.url) diff --git a/apps/desktop/tests/windows-installer-extract-report.cpp b/apps/desktop/tests/windows-installer-extract-report.cpp new file mode 100644 index 0000000000..ea73fd2fd1 --- /dev/null +++ b/apps/desktop/tests/windows-installer-extract-report.cpp @@ -0,0 +1,114 @@ +// Extraction failure reports keep 7-Zip's evidence intact while the dialog headline and excerpt stay bounded. +#define WIN32_LEAN_AND_MEAN +#define UNICODE +#include +#include +#include +#include "../installer/extract-report.h" + +extern "C" __declspec(dllimport) int __cdecl InstallerReportExtractFailure( + HWND parent, int code, LPCWSTR archive, LPCWSTR destination, LPCWSTR log, LPCWSTR reportPath, int show, + LPCWSTR title, LPCWSTR heading, LPCWSTR hint, LPCWSTR copy, LPCWSTR expand, LPCWSTR collapse, LPCWSTR savedFormat, LPCWSTR unsaved, LPCWSTR copied); + +static bool Contains(const std::wstring& text, const std::wstring& needle) { return text.find(needle) != std::wstring::npos; } + +static std::string ReadBytes(const std::wstring& path) { + HANDLE file = CreateFileW(path.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr); + assert(file != INVALID_HANDLE_VALUE); + std::string bytes(1 << 16, '\0'); + DWORD count = 0; + const BOOL read = ReadFile(file, &bytes[0], static_cast(bytes.size()), &count, nullptr); + assert(read); + CloseHandle(file); + bytes.resize(count); + return bytes; +} + +static void WriteBytes(const std::wstring& path, const std::string& bytes) { + HANDLE file = CreateFileW(path.c_str(), GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, 0, nullptr); + assert(file != INVALID_HANDLE_VALUE); + DWORD written = 0; + const BOOL wrote = WriteFile(file, bytes.data(), static_cast(bytes.size()), &written, nullptr); + assert(wrote); + CloseHandle(file); +} + +int wmain() { + using namespace extract_report; + + // Result codes distinguish 7-Zip's own exit codes from Win32 failures around its process. + assert(DescribeResult(2) == L"7-Zip exit code 2 (fatal error)"); + assert(DescribeResult(9) == L"7-Zip exit code 9 (unexpected exit code)"); + assert(DescribeResult(-5).rfind(L"Windows error 5 while running 7-Zip", 0) == 0); + assert(Contains(DescribeResult(-ERROR_FILE_NOT_FOUND), L"Windows error 2")); + + // The headline prefers the line naming the failing operation over the archive name 7-Zip prints first. + const std::wstring broken = L"ERROR: broken.7z\r\nbroken.7z\r\nOpen ERROR: Cannot open the file as [7z] archive\r\n\r\n\r\nERRORS:\r\nIs not archive\r\n"; + assert(Headline(2, broken) == L"Open ERROR: Cannot open the file as [7z] archive"); + const std::wstring locked = L"ERROR: Cannot delete output file : The process cannot access the file. : C:\\Apps\\Harness.new-1\\resources\\app.node\r\n"; + assert(Headline(2, locked) == Trim(locked)); + assert(Headline(-ERROR_ACCESS_DENIED, L"") == DescribeResult(-ERROR_ACCESS_DENIED)); + assert(Headline(1, L"ERROR: only-a-path\r\n") == L"ERROR: only-a-path"); + const std::wstring longLine = L"ERROR: Cannot open output file : " + std::wstring(400, L'x'); + const std::wstring headline = Headline(2, longLine); + assert(headline.size() == kHeadlineLimit && headline.back() == kEllipsis); + + // The report carries the result, both paths, and 7-Zip's output verbatim. + const std::wstring report = Compose(2, L"C:\\Temp\\app-64.7z", L"C:\\Apps\\Harness.new-1", locked, L"2026-09-22 10:59:49", L"10.0.26100"); + assert(Contains(report, L"Result: 7-Zip exit code 2 (fatal error)\r\n")); + assert(Contains(report, L"Archive: C:\\Temp\\app-64.7z\r\n")); + assert(Contains(report, L"Destination: C:\\Apps\\Harness.new-1\r\n")); + assert(Contains(report, L"Windows: 10.0.26100\r\n")); + assert(Contains(report, L"\r\n7-Zip output:\r\n" + Trim(locked) + L"\r\n")); + assert(Contains(Compose(2, L"a", L"b", L" \r\n", L"t", L"w"), L"7-Zip output:\r\n(none)\r\n")); + + // The excerpt is bounded by lines and characters and tells how much the saved report still holds. + std::wstring manyErrors; + for (int i = 0; i < 40; ++i) manyErrors += L"ERROR: Cannot open output file : Access is denied. : C:\\Apps\\file" + std::to_wstring(i) + L".dll\r\n"; + const std::wstring excerpt = Excerpt(Compose(2, L"a", L"b", manyErrors, L"t", L"w")); + assert(Lines(excerpt).size() == kExcerptLines + 1); + assert(excerpt.size() <= kExcerptChars + 64); + assert(Contains(excerpt, L" (" + std::to_wstring(48 - kExcerptLines) + L" more lines in the saved report)")); + assert(Excerpt(L"one\r\ntwo") == L"one\r\ntwo"); + assert(Excerpt(std::wstring(2000, L'x') + L"\r\nnext").size() < kExcerptLineLimit + 64); + + // 7-Zip output arrives as UTF-8; anything else falls back to the system code page instead of vanishing. + assert(Decode("Access denied: \xE6\x96\x87\xE4\xBB\xB6") == L"Access denied: \x6587\x4EF6"); + assert(!Decode("\xC1\xED\xD2\xBB : file").empty()); + assert(Decode("") == L""); + + // The exported entry point writes the report beside a missing directory and survives a missing log file. + WCHAR temp[MAX_PATH]; + const DWORD tempLength = GetTempPathW(MAX_PATH, temp); + assert(tempLength); + const std::wstring root = std::wstring(temp) + L"dsh-extract-report-" + std::to_wstring(GetCurrentProcessId()); + const BOOL created = CreateDirectoryW(root.c_str(), nullptr); + assert(created); + const std::wstring log = root + L"\\extract.log"; + WriteBytes(log, "ERROR: Cannot open output file : Access is denied. : C:\\Apps\\Harness.new-1\\\xE6\x96\x87\xE4\xBB\xB6.dll\r\n"); + const std::wstring reportPath = root + L"\\nested\\logs\\extract-failure.log"; + const int written = InstallerReportExtractFailure(nullptr, 2, L"C:\\Temp\\app-64.7z", L"C:\\Apps\\Harness.new-1", log.c_str(), reportPath.c_str(), 0, + L"title", L"heading", L"hint", L"copy", L"expand", L"collapse", L"saved %s", L"unsaved", L"copied"); + assert(written == 1); + const std::string saved = ReadBytes(reportPath); + assert(saved.rfind("\xEF\xBB\xBF", 0) == 0); + assert(saved.find("Result: 7-Zip exit code 2 (fatal error)") != std::string::npos); + assert(saved.find("Access is denied. : C:\\Apps\\Harness.new-1\\\xE6\x96\x87\xE4\xBB\xB6.dll") != std::string::npos); + const std::wstring missingLogReport = root + L"\\missing.log.txt"; + const int withoutLog = InstallerReportExtractFailure(nullptr, -ERROR_ACCESS_DENIED, L"a", L"b", (root + L"\\absent.log").c_str(), missingLogReport.c_str(), 0, + L"title", L"heading", L"hint", L"copy", L"expand", L"collapse", L"saved %s", L"unsaved", L"copied"); + assert(withoutLog == 1); + assert(ReadBytes(missingLogReport).find("Windows error 5 while running 7-Zip") != std::string::npos); + assert(ReadBytes(missingLogReport).find("7-Zip output:\r\n(none)") != std::string::npos); + // An unwritable report location reports failure without throwing. + const int unwritable = InstallerReportExtractFailure(nullptr, 2, L"a", L"b", log.c_str(), (log + L"\\impossible.txt").c_str(), 0, + L"title", L"heading", L"hint", L"copy", L"expand", L"collapse", L"saved %s", L"unsaved", L"copied"); + assert(unwritable == 0); + + for (const std::wstring& file : {reportPath, missingLogReport, log}) DeleteFileW(file.c_str()); + RemoveDirectoryW((root + L"\\nested\\logs").c_str()); + RemoveDirectoryW((root + L"\\nested").c_str()); + const BOOL removed = RemoveDirectoryW(root.c_str()); + assert(removed); + return 0; +} diff --git a/apps/desktop/tests/windows-update-publisher.spec.ts b/apps/desktop/tests/windows-update-publisher.spec.ts index 2c27e600a1..a1af8d5416 100644 --- a/apps/desktop/tests/windows-update-publisher.spec.ts +++ b/apps/desktop/tests/windows-update-publisher.spec.ts @@ -90,6 +90,7 @@ describe('Windows update publisher', () => { DSH_DESKTOP_AUTO_UPDATE_ENV: 'production', }, 'win32', 'x64') expect(config.win.forceCodeSigning).toBe(true) + expect(config.artifactName).toBe('deepseek-harness-${version}-${os}-${arch}.${ext}') expect(typeof config.win.signtoolOptions.sign).toBe('function') const manager = new WindowsSignToolManager({ platformSpecificBuildOptions: config.win, getCscLink: () => undefined }) expect(await manager.computedPublisherName.value).toEqual(['CN=Publisher,O=Company,C=CN']) From 943af81a185ea4d70eda2b36598938857b1f851b Mon Sep 17 00:00:00 2001 From: imccyu Date: Tue, 22 Sep 2026 13:07:34 +0800 Subject: [PATCH 08/29] fix(release): pin vendor dependencies for dsh 0.1.5 --- apps/cli/package.json | 12 +- apps/desktop-host/package.json | 4 +- apps/web/package.json | 2 +- benchmarks/package.json | 4 +- packages/acp/acp/package.json | 6 +- packages/api/gateway/package.json | 6 +- packages/api/remotes/package.json | 4 +- packages/api/session-controller/package.json | 6 +- packages/api/settings-controller/package.json | 6 +- .../api/workspace-controller/package.json | 4 +- packages/api/workspace-files/package.json | 6 +- .../attachment/attachment-local/package.json | 6 +- packages/attachment/attachment/package.json | 4 +- packages/boot/app-boot/package.json | 22 +- packages/boot/cmdline/package.json | 10 +- packages/bundle/acp-app/package.json | 6 +- packages/bundle/base/package.json | 8 +- packages/bundle/headless/package.json | 10 +- packages/bundle/sdk-app/package.json | 8 +- packages/bundle/sdk-minimal/package.json | 6 +- packages/bundle/web-app/package.json | 10 +- packages/client/connection/package.json | 6 +- packages/client/file-upload/package.json | 4 +- packages/client/hmr/package.json | 8 +- packages/client/locale/package.json | 6 +- packages/client/modules/package.json | 6 +- packages/client/resources/package.json | 4 +- packages/client/store/package.json | 4 +- packages/client/ui-agent-preset/package.json | 4 +- packages/client/ui-approval/package.json | 4 +- packages/client/ui-attachment/package.json | 4 +- .../client/ui-brand-official/package.json | 4 +- packages/client/ui-chat/package.json | 6 +- packages/client/ui-commands/package.json | 4 +- packages/client/ui-conversation/package.json | 6 +- packages/client/ui-deliverables/package.json | 4 +- .../ui-directory-picker-browse/package.json | 4 +- .../ui-directory-picker-native/package.json | 4 +- packages/client/ui-dockkit/package.json | 4 +- packages/client/ui-goal/package.json | 4 +- packages/client/ui-input-trigger/package.json | 4 +- packages/client/ui-jobs/package.json | 4 +- packages/client/ui-layout/package.json | 4 +- .../client/ui-message-feedback/package.json | 4 +- .../client/ui-model-selection/package.json | 4 +- packages/client/ui-open-in-app/package.json | 4 +- .../client/ui-permission-presets/package.json | 4 +- packages/client/ui-plan/package.json | 4 +- packages/client/ui-primitives/package.json | 4 +- packages/client/ui-reference/package.json | 4 +- packages/client/ui-renderer/package.json | 4 +- packages/client/ui-schedule/package.json | 4 +- packages/client/ui-session/package.json | 4 +- .../client/ui-settings-general/package.json | 6 +- .../client/ui-settings-models/package.json | 4 +- .../ui-settings-plugin-inventory/package.json | 4 +- .../client/ui-settings-plugins/package.json | 4 +- packages/client/ui-settings/package.json | 6 +- .../ui-sidebar-documentpreview/package.json | 4 +- packages/client/ui-sidebar-files/package.json | 4 +- packages/client/ui-sidebar-right/package.json | 4 +- packages/client/ui-sidebar/package.json | 4 +- packages/client/ui-skill/package.json | 4 +- packages/client/ui-slots/package.json | 4 +- packages/client/ui-subagent/package.json | 4 +- packages/client/ui-theme/package.json | 6 +- packages/client/ui-tool/package.json | 4 +- packages/client/ui-trajectory/package.json | 4 +- .../client/ui-user-questions/package.json | 4 +- packages/client/ui-workflow-run/package.json | 4 +- packages/client/ui-workspace/package.json | 4 +- packages/client/web/package.json | 6 +- .../code-runtime-worker-thread/package.json | 6 +- .../code-runtime/code-runtime/package.json | 4 +- .../compaction/command-compact/package.json | 8 +- .../compaction/compaction-basic/package.json | 10 +- .../package.json | 10 +- packages/compaction/compaction/package.json | 4 +- .../context/agent-instructions/package.json | 8 +- .../context/file-reference-local/package.json | 6 +- packages/context/file-reference/package.json | 4 +- .../context/session-reference/package.json | 10 +- packages/context/time-context/package.json | 6 +- packages/context/tmux-context/package.json | 6 +- .../core/agent-default-model/package.json | 6 +- packages/core/agent-loop/package.json | 6 +- .../core/agent-tool-presentation/package.json | 6 +- packages/core/agent/package.json | 4 +- packages/core/scope/package.json | 4 +- packages/core/session/package.json | 4 +- packages/core/system-prompt/package.json | 6 +- packages/core/tools/package.json | 6 +- .../credentials/authorization/package.json | 4 +- .../credentials-local/package.json | 6 +- packages/credentials/credentials/package.json | 4 +- packages/e2b/e2b/package.json | 6 +- packages/e2b/fs-e2b/package.json | 4 +- packages/e2b/subprocess-e2b/package.json | 6 +- .../agent-team-profile/package.json | 6 +- .../agent-team-web-profile/package.json | 6 +- packages/experimental/agent-team/package.json | 6 +- .../client-ui-agent-team/package.json | 4 +- .../code-runtime-python/package.json | 6 +- packages/experimental/inspector/package.json | 12 +- .../experimental/tool-agent-team/package.json | 6 +- .../webworker-packer/package.json | 6 +- .../webworker-runtime/package.json | 8 +- .../cordis-client-runner/package.json | 6 +- .../cordis-host-runner/package.json | 8 +- packages/extensions/tool-cordis/package.json | 6 +- packages/extensions/ui-cordis/package.json | 4 +- .../feedback/command-feedback/package.json | 8 +- .../feedback/message-feedback/package.json | 10 +- packages/fs/fs-local/package.json | 6 +- .../fs/fs-observation-policy/package.json | 4 +- packages/fs/fs-sandbox/package.json | 4 +- packages/fs/fs/package.json | 4 +- packages/fs/tool-fs-search/package.json | 6 +- packages/fs/tool-fs/package.json | 6 +- packages/fs/tool-present/package.json | 6 +- .../fs/tool-str-replace-editor/package.json | 6 +- packages/goal/command-goal/package.json | 6 +- packages/goal/goal-round-driver/package.json | 4 +- packages/goal/goal/package.json | 6 +- packages/goal/tool-goal/package.json | 8 +- .../guard/repeat-tool-reminder/package.json | 6 +- packages/guard/timeout-policy/package.json | 4 +- packages/hooks/hook-protocol/package.json | 4 +- packages/hooks/hooks-claude-code/package.json | 6 +- packages/hooks/hooks-codex/package.json | 6 +- .../host/directory-picker-auto/package.json | 10 +- .../host/directory-picker-browse/package.json | 6 +- .../host/directory-picker-native/package.json | 4 +- packages/host/directory-picker/package.json | 4 +- packages/host/frontend-static/package.json | 8 +- packages/host/open-in-app/package.json | 8 +- packages/host/plugin-inventory/package.json | 8 +- packages/host/webserver/package.json | 6 +- .../identity/anonymous-user-id/package.json | 4 +- packages/interaction/commands/package.json | 4 +- .../permission-presets/package.json | 6 +- .../interaction/tool-ask-user/package.json | 4 +- .../interaction/user-approval/package.json | 6 +- .../interaction/user-questions/package.json | 4 +- packages/jobs/jobs-local/package.json | 10 +- packages/jobs/jobs/package.json | 4 +- packages/jobs/tool-jobs/package.json | 6 +- .../deepseek-llm-api-extensions/package.json | 4 +- packages/llm/llm-deepseek/package.json | 6 +- packages/llm/llm-pi-ai/package.json | 6 +- packages/llm/llm-retry/package.json | 10 +- packages/llm/llm/package.json | 6 +- .../package.json | 12 +- packages/llm/token-meter/package.json | 6 +- packages/lsp/lsp-stdio/package.json | 6 +- packages/lsp/lsp/package.json | 4 +- packages/lsp/tool-lsp/package.json | 6 +- packages/mcp/mcp-client/package.json | 6 +- packages/plan/plan-mode/package.json | 4 +- packages/preset/agent-presets/package.json | 16 +- packages/preset/persona/package.json | 6 +- .../invariants/package.json | 6 +- packages/sandbox/sandbox-local/package.json | 6 +- packages/sandbox/sandbox-policy/package.json | 6 +- .../sandbox/sandbox-windows-acl/package.json | 4 +- packages/sandbox/sandbox/package.json | 4 +- packages/schedule/schedule/package.json | 6 +- packages/sdk/client/package.json | 4 +- packages/sdk/protocol/package.json | 4 +- packages/sdk/server/package.json | 8 +- .../session-log-export/package.json | 8 +- .../session-query-sqlite/package.json | 8 +- .../session-query/session-query/package.json | 4 +- .../tool-session-query/package.json | 6 +- .../session-checkpoint-policy/package.json | 6 +- .../session-format-catalog/package.json | 4 +- .../session-format-v0-to-v1/package.json | 4 +- .../session-format-v1-to-v2/package.json | 4 +- .../session-format-v2-to-v3/package.json | 4 +- packages/session/session-format/package.json | 4 +- .../session/session-log-deepseek/package.json | 10 +- .../session-persistence-jsonl/package.json | 6 +- .../session/session-persistence/package.json | 4 +- .../session-projection-cache/package.json | 6 +- .../session/session-projection/package.json | 4 +- packages/session/session-stats/package.json | 8 +- .../session-telemetry-otel/package.json | 10 +- .../session/session-telemetry/package.json | 4 +- .../package.json | 6 +- .../package.json | 10 +- .../session/session-title-llm/package.json | 6 +- packages/session/session-title/package.json | 6 +- .../session/session-turn-outline/package.json | 8 +- packages/settings/settings-file/package.json | 6 +- packages/settings/settings/package.json | 8 +- packages/shell/bash-local/package.json | 6 +- packages/shell/bash-sandbox/package.json | 4 +- packages/shell/pwsh-local/package.json | 6 +- packages/shell/pwsh-sandbox/package.json | 4 +- packages/shell/shell-env/package.json | 6 +- packages/shell/shell/package.json | 4 +- .../shell/tool-bash-persistent/package.json | 10 +- packages/shell/tool-bash/package.json | 6 +- .../shell/tool-pwsh-persistent/package.json | 10 +- packages/shell/tool-pwsh/package.json | 6 +- packages/skill/skill-badge/package.json | 4 +- packages/skill/skill-filesystem/package.json | 6 +- packages/skill/skill/package.json | 6 +- packages/skill/tool-skill/package.json | 6 +- packages/spill/spill-local/package.json | 10 +- packages/spill/spill-policy/package.json | 6 +- packages/spill/spill/package.json | 4 +- packages/storage/storage-domain/package.json | 6 +- packages/storage/storage-json/package.json | 6 +- packages/storage/storage-sqlite/package.json | 6 +- packages/storage/storage/package.json | 4 +- packages/subagent/subagent-acp/package.json | 8 +- .../subagent-claude-code/package.json | 6 +- packages/subagent/subagent-codex/package.json | 8 +- .../subagent/subagent-dsh-sdk/package.json | 8 +- .../subagent-fork-in-process/package.json | 8 +- .../subagent-in-process-driver/package.json | 8 +- .../subagent-spawn-in-process/package.json | 8 +- packages/subagent/subagent/package.json | 4 +- .../tool-subagent-control/package.json | 4 +- packages/subagent/tool-subagent/package.json | 8 +- .../subprocess/subprocess-local/package.json | 4 +- packages/subprocess/subprocess/package.json | 4 +- .../subprocess/win32-process/package.json | 4 +- packages/terminal/terminal-bash/package.json | 6 +- packages/terminal/terminal/package.json | 4 +- packages/terminal/tool-terminal/package.json | 10 +- .../agent-loop-testkit/package.json | 4 +- .../test-support/client-runtime/package.json | 4 +- .../test-support/llm-mock-server/package.json | 4 +- packages/test-support/llm-replay/package.json | 4 +- .../test-support/loader-smoke/package.json | 4 +- .../session-snapshot/package.json | 4 +- packages/todo/tool-todo/package.json | 10 +- packages/typert/generator/package.json | 4 +- packages/typert/loader/package.json | 10 +- packages/typert/protocol/package.json | 4 +- packages/typert/registry/package.json | 4 +- packages/util/atomic-write/package.json | 4 +- packages/util/brand/package.json | 4 +- packages/util/chunked-list/package.json | 4 +- packages/util/crypto/package.json | 4 +- packages/util/deque/package.json | 4 +- packages/util/home-paths/package.json | 4 +- packages/util/http-proxy/package.json | 4 +- packages/util/launch-environment/package.json | 4 +- packages/util/native-command/package.json | 4 +- packages/util/output-retention/package.json | 4 +- packages/util/package-manifest/package.json | 4 +- packages/util/time/package.json | 4 +- packages/util/timeout/package.json | 4 +- packages/util/values/package.json | 4 +- packages/util/workspace-path/package.json | 4 +- packages/web/tool-web/package.json | 6 +- packages/web/web-fetch-http/package.json | 6 +- packages/web/web-search-deepseek/package.json | 6 +- packages/web/web-search-exa/package.json | 6 +- .../web/web-search-perplexity/package.json | 6 +- packages/web/web/package.json | 6 +- packages/webhook/webhook-github/package.json | 10 +- packages/webhook/webhook/package.json | 8 +- packages/workflow/tool-ralph/package.json | 8 +- packages/workflow/tool-workflow/package.json | 6 +- .../workflow-worker-thread/package.json | 6 +- packages/workflow/workflow/package.json | 4 +- packages/workspace/workspace/package.json | 4 +- pnpm-lock.yaml | 750 +++++++++--------- python/sdk-runtime/package.json | 14 +- scripts/verify-package-dependencies.spec.ts | 33 +- scripts/verify-package-dependencies.ts | 34 +- 275 files changed, 1212 insertions(+), 1171 deletions(-) diff --git a/apps/cli/package.json b/apps/cli/package.json index 97881b4cfa..b265db2e3e 100644 --- a/apps/cli/package.json +++ b/apps/cli/package.json @@ -28,11 +28,11 @@ }, "license": "MIT", "dependencies": { - "@deepseek-ai/cordis": "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/cordis": "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-acp-app": "workspace:^", "@deepseek-ai/dsh-agent-instructions": "workspace:^", "@deepseek-ai/dsh-agent-tool-presentation": "workspace:^", @@ -95,7 +95,7 @@ "@deepseek-ai/dsh-webhook": "workspace:^", "@deepseek-ai/dsh-webhook-github": "workspace:^", "@deepseek-ai/dsh-workflow-worker-thread": "workspace:^", - "@deepseek-ai/schemastery": "workspace:^", + "@deepseek-ai/schemastery": "workspace:*", "commander": "^15.0.0", "js-yaml": "^4.2.0", "node-addon-require-builtin": "^0.1.4", diff --git a/apps/desktop-host/package.json b/apps/desktop-host/package.json index 83b1ed2a5b..99eb2b4904 100644 --- a/apps/desktop-host/package.json +++ b/apps/desktop-host/package.json @@ -11,8 +11,8 @@ "config/desktop.cordis.patch.yml" ], "dependencies": { - "@deepseek-ai/cordis": "workspace:^", - "@deepseek-ai/cordis-plugin-include": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", + "@deepseek-ai/cordis-plugin-include": "workspace:*", "@deepseek-ai/dsh": "workspace:^", "@deepseek-ai/dsh-api-gateway": "workspace:^", "@deepseek-ai/dsh-app-boot": "workspace:^", diff --git a/apps/web/package.json b/apps/web/package.json index cc504af02b..50e6e88070 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -30,7 +30,7 @@ }, "license": "MIT", "devDependencies": { - "@deepseek-ai/cordis-plugin-group": "workspace:^", + "@deepseek-ai/cordis-plugin-group": "workspace:*", "@deepseek-ai/dsh-client-modules": "workspace:^", "@deepseek-ai/dsh-client-store": "workspace:^", "@deepseek-ai/dsh-client-ui-dockkit": "workspace:^", diff --git a/benchmarks/package.json b/benchmarks/package.json index cc8c60cf71..4fd9edcd60 100644 --- a/benchmarks/package.json +++ b/benchmarks/package.json @@ -7,7 +7,7 @@ "devDependencies": { "playwright": "^1.49.0", "@deepseek-ai/dsh-llm-replay": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-agent-loop": "workspace:^", "@deepseek-ai/dsh-agent-loop-testkit": "workspace:^", @@ -32,6 +32,6 @@ "@deepseek-ai/dsh-typert-protocol": "workspace:^" }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/acp/acp/package.json b/packages/acp/acp/package.json index 1e18f54543..3bf01229ec 100644 --- a/packages/acp/acp/package.json +++ b/packages/acp/acp/package.json @@ -29,10 +29,10 @@ "dependencies": { "@agentclientprotocol/sdk": "1.4.0", "@deepseek-ai/dsh-brand": "workspace:^", - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-attachment": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", @@ -48,7 +48,7 @@ } }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-agent-loop": "workspace:^", "@deepseek-ai/dsh-agent-loop-testkit": "workspace:^", diff --git a/packages/api/gateway/package.json b/packages/api/gateway/package.json index 985db89e9e..03dbbc8245 100644 --- a/packages/api/gateway/package.json +++ b/packages/api/gateway/package.json @@ -53,12 +53,12 @@ "dependencies": { "@deepseek-ai/dsh-deque": "workspace:^", "@deepseek-ai/dsh-timeout": "workspace:^", - "@deepseek-ai/schemastery": "workspace:^", + "@deepseek-ai/schemastery": "workspace:*", "ws": "^8.21.0", "@deepseek-ai/dsh-typert-protocol": "workspace:^" }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-brand": "workspace:^", @@ -67,7 +67,7 @@ "@deepseek-ai/dsh-typert-registry": "workspace:^", "@deepseek-ai/dsh-util-crypto": "workspace:^", "@types/ws": "^8.18.1", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "zod": "^4.4.3" } } diff --git a/packages/api/remotes/package.json b/packages/api/remotes/package.json index 73f4bbdd13..1415ffdc5f 100644 --- a/packages/api/remotes/package.json +++ b/packages/api/remotes/package.json @@ -55,11 +55,11 @@ "@deepseek-ai/dsh-util-values": "workspace:^" }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-scope": "workspace:^" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-agent-presets": "workspace:^", "@deepseek-ai/dsh-api-gateway": "workspace:^", diff --git a/packages/api/session-controller/package.json b/packages/api/session-controller/package.json index e07392fe5c..f8378d4010 100644 --- a/packages/api/session-controller/package.json +++ b/packages/api/session-controller/package.json @@ -70,12 +70,12 @@ "dependencies": { "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-deque": "workspace:^", - "@deepseek-ai/schemastery": "workspace:^", + "@deepseek-ai/schemastery": "workspace:*", "mime-types": "^3.0.2", "zod": "^4.4.3" }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-agent-default-model": "workspace:^", "@deepseek-ai/dsh-agent-presets": "workspace:^", @@ -117,7 +117,7 @@ } }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-agent-default-model": "workspace:^", "@deepseek-ai/dsh-agent-loop": "workspace:^", diff --git a/packages/api/settings-controller/package.json b/packages/api/settings-controller/package.json index c9bcbf578a..28caa71fed 100644 --- a/packages/api/settings-controller/package.json +++ b/packages/api/settings-controller/package.json @@ -44,11 +44,11 @@ ], "license": "MIT", "dependencies": { - "@deepseek-ai/schemastery": "workspace:^", + "@deepseek-ai/schemastery": "workspace:*", "zod": "^4.4.3" }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-agent-presets": "workspace:^", "@deepseek-ai/dsh-credentials": "workspace:^", "@deepseek-ai/dsh-native-command": "workspace:^", @@ -57,7 +57,7 @@ "@deepseek-ai/dsh-typert-protocol": "workspace:^" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-agent-presets": "workspace:^", "@deepseek-ai/dsh-credentials": "workspace:^", "@deepseek-ai/dsh-native-command": "workspace:^", diff --git a/packages/api/workspace-controller/package.json b/packages/api/workspace-controller/package.json index e73fe14586..dc6691b4f9 100644 --- a/packages/api/workspace-controller/package.json +++ b/packages/api/workspace-controller/package.json @@ -69,7 +69,7 @@ "zod": "^4.4.3" }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-api-gateway": "workspace:^", "@deepseek-ai/dsh-client-connection": "workspace:^", "@deepseek-ai/dsh-host-directory-picker": "workspace:^", @@ -79,7 +79,7 @@ "@deepseek-ai/dsh-workspace": "workspace:^" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-api-gateway": "workspace:^", "@deepseek-ai/dsh-client-connection": "workspace:^", "@deepseek-ai/dsh-client-store": "workspace:^", diff --git a/packages/api/workspace-files/package.json b/packages/api/workspace-files/package.json index c5130dbe89..9592cc40be 100644 --- a/packages/api/workspace-files/package.json +++ b/packages/api/workspace-files/package.json @@ -54,14 +54,14 @@ "dependencies": { "@deepseek-ai/dsh-deque": "workspace:^", "@deepseek-ai/dsh-typert-protocol": "workspace:^", - "@deepseek-ai/schemastery": "workspace:^", + "@deepseek-ai/schemastery": "workspace:*", "zod": "^4.4.3" }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-api-gateway": "workspace:^", "@deepseek-ai/dsh-client-resources": "workspace:^", "@deepseek-ai/dsh-client-ui-slots": "workspace:^", diff --git a/packages/attachment/attachment-local/package.json b/packages/attachment/attachment-local/package.json index 1d2a37a9e4..8e4f2850b4 100644 --- a/packages/attachment/attachment-local/package.json +++ b/packages/attachment/attachment-local/package.json @@ -23,15 +23,15 @@ "peerDependencies": { "@deepseek-ai/dsh-attachment": "workspace:^", "@deepseek-ai/dsh-home-paths": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "dependencies": { - "@deepseek-ai/schemastery": "workspace:^", + "@deepseek-ai/schemastery": "workspace:*", "sharp": "^0.35.3" }, "devDependencies": { "@deepseek-ai/dsh-attachment": "workspace:^", "@deepseek-ai/dsh-home-paths": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/attachment/attachment/package.json b/packages/attachment/attachment/package.json index e030ce0e71..8bfc20cb06 100644 --- a/packages/attachment/attachment/package.json +++ b/packages/attachment/attachment/package.json @@ -23,10 +23,10 @@ "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-brand": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-brand": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/boot/app-boot/package.json b/packages/boot/app-boot/package.json index 9b51435015..c4b1a011e7 100644 --- a/packages/boot/app-boot/package.json +++ b/packages/boot/app-boot/package.json @@ -33,14 +33,14 @@ "resolve.exports": "^2.0.3" }, "peerDependencies": { - "@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/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-launch-environment": "workspace:^", "@deepseek-ai/dsh-home-paths": "workspace:^", "@deepseek-ai/dsh-system-prompt": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "peerDependenciesMeta": { "@deepseek-ai/cordis-plugin-hmr": { @@ -48,16 +48,16 @@ } }, "devDependencies": { - "@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/cordis-plugin-timer": "workspace:^", + "@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/cordis-plugin-timer": "workspace:*", "@deepseek-ai/dsh-launch-environment": "workspace:^", "@deepseek-ai/dsh-home-paths": "workspace:^", "@deepseek-ai/dsh-system-prompt": "workspace:^", "@types/js-yaml": "^4.0.9", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "chokidar": "4.0.3" } } diff --git a/packages/boot/cmdline/package.json b/packages/boot/cmdline/package.json index bb453aaa94..57c18c4452 100644 --- a/packages/boot/cmdline/package.json +++ b/packages/boot/cmdline/package.json @@ -27,13 +27,13 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis-plugin-loader": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis-plugin-loader": "workspace:*", + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis-plugin-include": "workspace:^", - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis-plugin-include": "workspace:*", + "@deepseek-ai/cordis-plugin-loader": "workspace:*", "commander": "^15.0.0", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/bundle/acp-app/package.json b/packages/bundle/acp-app/package.json index f9aca81482..01b4862970 100644 --- a/packages/bundle/acp-app/package.json +++ b/packages/bundle/acp-app/package.json @@ -39,10 +39,10 @@ "commander": "^15.0.0" }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis-plugin-include": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis-plugin-include": "workspace:*", + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/bundle/base/package.json b/packages/bundle/base/package.json index abe58f9588..5a6e059e55 100644 --- a/packages/bundle/base/package.json +++ b/packages/bundle/base/package.json @@ -34,8 +34,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:^", @@ -120,9 +120,9 @@ "@deepseek-ai/dsh-agent-instructions": "workspace:^" }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/bundle/headless/package.json b/packages/bundle/headless/package.json index 5d7042c166..46b1f112f4 100644 --- a/packages/bundle/headless/package.json +++ b/packages/bundle/headless/package.json @@ -43,20 +43,20 @@ "@deepseek-ai/dsh-cmdline": "workspace:^", "@deepseek-ai/dsh-code-runtime-worker-thread": "workspace:^", "@deepseek-ai/dsh-util-values": "workspace:^", - "@deepseek-ai/schemastery": "workspace:^", + "@deepseek-ai/schemastery": "workspace:*", "commander": "^15.0.0" }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", + "@deepseek-ai/cordis-plugin-loader": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-agent-default-model": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", + "@deepseek-ai/cordis-plugin-loader": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-agent-default-model": "workspace:^", "@deepseek-ai/dsh-agent-loop": "workspace:^", diff --git a/packages/bundle/sdk-app/package.json b/packages/bundle/sdk-app/package.json index 974b60623a..20f002c9a4 100644 --- a/packages/bundle/sdk-app/package.json +++ b/packages/bundle/sdk-app/package.json @@ -36,14 +36,14 @@ "dependencies": { "@deepseek-ai/dsh-cmdline": "workspace:^", "@deepseek-ai/dsh-sdk-jsonrpc-server": "workspace:^", - "@deepseek-ai/schemastery": "workspace:^", + "@deepseek-ai/schemastery": "workspace:*", "commander": "^15.0.0" }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis-plugin-include": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis-plugin-include": "workspace:*", + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/bundle/sdk-minimal/package.json b/packages/bundle/sdk-minimal/package.json index bd32a131f0..5208226eac 100644 --- a/packages/bundle/sdk-minimal/package.json +++ b/packages/bundle/sdk-minimal/package.json @@ -34,7 +34,7 @@ } }, "dependencies": { - "@deepseek-ai/cordis-plugin-timer": "workspace:^", + "@deepseek-ai/cordis-plugin-timer": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-agent-loop": "workspace:^", "@deepseek-ai/dsh-deepseek-llm-api-extensions": "workspace:^", @@ -63,9 +63,9 @@ "@deepseek-ai/dsh-tools": "workspace:^" }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/bundle/web-app/package.json b/packages/bundle/web-app/package.json index 3498cb6761..2392881d50 100644 --- a/packages/bundle/web-app/package.json +++ b/packages/bundle/web-app/package.json @@ -116,19 +116,19 @@ "@deepseek-ai/dsh-tool-subagent": "workspace:^", "@deepseek-ai/dsh-web-frontend": "workspace:^", "@deepseek-ai/dsh-workspace": "workspace:^", - "@deepseek-ai/schemastery": "workspace:^", + "@deepseek-ai/schemastery": "workspace:*", "commander": "^15.0.0", "open": "^11.0.0" }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", + "@deepseek-ai/cordis-plugin-loader": "workspace:*", "@deepseek-ai/dsh-shell-env": "workspace:^", "@deepseek-ai/dsh-system-prompt": "workspace:^" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", + "@deepseek-ai/cordis-plugin-loader": "workspace:*", "@deepseek-ai/dsh-shell-env": "workspace:^", "@deepseek-ai/dsh-system-prompt": "workspace:^" } diff --git a/packages/client/connection/package.json b/packages/client/connection/package.json index 4732dcdd71..dab23d2d88 100644 --- a/packages/client/connection/package.json +++ b/packages/client/connection/package.json @@ -35,7 +35,7 @@ "license": "MIT", "dependencies": { "@deepseek-ai/dsh-credentials": "workspace:^", - "@deepseek-ai/schemastery": "workspace:^", + "@deepseek-ai/schemastery": "workspace:*", "zod": "^4.4.3" }, "files": [ @@ -44,10 +44,10 @@ "lib/types/**/*.d.ts" ], "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-api-session-controller": "workspace:^", "@deepseek-ai/dsh-attachment": "workspace:^", "@deepseek-ai/dsh-brand": "workspace:^", diff --git a/packages/client/file-upload/package.json b/packages/client/file-upload/package.json index 5c606edbc5..0b3f35d369 100644 --- a/packages/client/file-upload/package.json +++ b/packages/client/file-upload/package.json @@ -67,11 +67,11 @@ "@deepseek-ai/dsh-brand": "workspace:^" }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-scope": "workspace:^" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-client-connection": "workspace:^", "@deepseek-ai/dsh-commands": "workspace:^", diff --git a/packages/client/hmr/package.json b/packages/client/hmr/package.json index 3c5f0a3cbd..05ab26abea 100644 --- a/packages/client/hmr/package.json +++ b/packages/client/hmr/package.json @@ -38,17 +38,17 @@ }, "license": "MIT", "dependencies": { - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@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:^" + "@deepseek-ai/cordis": "workspace:*" }, "files": [ "lib/index.js", diff --git a/packages/client/locale/package.json b/packages/client/locale/package.json index 4245200191..bf980b6fb9 100644 --- a/packages/client/locale/package.json +++ b/packages/client/locale/package.json @@ -39,10 +39,10 @@ }, "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-api-remotes": "workspace:^", "@deepseek-ai/dsh-client-store": "workspace:^", "@deepseek-ai/dsh-client-test-runtime": "workspace:^", @@ -56,7 +56,7 @@ "@deepseek-ai/dsh-settings": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "files": [ "lib/index.js", diff --git a/packages/client/modules/package.json b/packages/client/modules/package.json index 06ee59bb3e..ed5f826661 100644 --- a/packages/client/modules/package.json +++ b/packages/client/modules/package.json @@ -42,10 +42,10 @@ }, "license": "MIT", "devDependencies": { - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis-plugin-loader": "workspace:*", "@deepseek-ai/dsh-host-webserver": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-package-manifest": "workspace:^" }, "files": [ @@ -55,6 +55,6 @@ "lib/types/**/*.d.ts" ], "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/client/resources/package.json b/packages/client/resources/package.json index dd6b9baa2f..689f352ede 100644 --- a/packages/client/resources/package.json +++ b/packages/client/resources/package.json @@ -39,10 +39,10 @@ }, "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-client-store": "workspace:^", "@deepseek-ai/dsh-client-test-runtime": "workspace:^", "@deepseek-ai/dsh-client-ui-renderer": "workspace:^", diff --git a/packages/client/store/package.json b/packages/client/store/package.json index 59325a1517..00bc212768 100644 --- a/packages/client/store/package.json +++ b/packages/client/store/package.json @@ -23,10 +23,10 @@ }, "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "zustand": "~4.4.7", "immer": "^10.1.1" }, diff --git a/packages/client/ui-agent-preset/package.json b/packages/client/ui-agent-preset/package.json index 2dce990410..6d072209e3 100644 --- a/packages/client/ui-agent-preset/package.json +++ b/packages/client/ui-agent-preset/package.json @@ -46,7 +46,7 @@ }, "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-api-remotes": "workspace:^", @@ -62,7 +62,7 @@ "@deepseek-ai/dsh-client-ui-slots": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@types/react": "~18.3.1", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "react": "^18.2.0", "@deepseek-ai/dsh-client-ui-renderer": "workspace:^", "@deepseek-ai/dsh-client-ui-session": "workspace:^", diff --git a/packages/client/ui-approval/package.json b/packages/client/ui-approval/package.json index 765176239f..86ecffb2ff 100644 --- a/packages/client/ui-approval/package.json +++ b/packages/client/ui-approval/package.json @@ -44,10 +44,10 @@ }, "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-api-remotes": "workspace:^", "@deepseek-ai/dsh-api-session-controller": "workspace:^", "@deepseek-ai/dsh-client-locale": "workspace:^", diff --git a/packages/client/ui-attachment/package.json b/packages/client/ui-attachment/package.json index f994246609..6e19205536 100644 --- a/packages/client/ui-attachment/package.json +++ b/packages/client/ui-attachment/package.json @@ -43,7 +43,7 @@ }, "license": "MIT", "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@types/react": "~18.3.1", "@types/react-dom": "~18.3.0", "@deepseek-ai/dsh-client-ui-chat": "workspace:^", @@ -64,6 +64,6 @@ "lib/types/**/*.d.ts" ], "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/client/ui-brand-official/package.json b/packages/client/ui-brand-official/package.json index 1113b8a013..6a1af745e0 100644 --- a/packages/client/ui-brand-official/package.json +++ b/packages/client/ui-brand-official/package.json @@ -40,13 +40,13 @@ }, "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-client-ui-primitives": "workspace:^", "@deepseek-ai/dsh-client-ui-renderer": "workspace:^", "@deepseek-ai/dsh-client-ui-sidebar": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@testing-library/react": "^16.1.0", "@types/react": "~18.3.1", "react": "^18.2.0", diff --git a/packages/client/ui-chat/package.json b/packages/client/ui-chat/package.json index 4fc9f35f4d..f62bf82962 100644 --- a/packages/client/ui-chat/package.json +++ b/packages/client/ui-chat/package.json @@ -48,10 +48,10 @@ }, "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-api-remotes": "workspace:^", "@deepseek-ai/dsh-api-session-controller": "workspace:^", @@ -88,7 +88,7 @@ "react-dom": "^18.2.0" }, "dependencies": { - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "files": [ "lib/index.js", diff --git a/packages/client/ui-commands/package.json b/packages/client/ui-commands/package.json index f3313850a3..a058e1b14f 100644 --- a/packages/client/ui-commands/package.json +++ b/packages/client/ui-commands/package.json @@ -42,7 +42,7 @@ }, "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-api-remotes": "workspace:^", @@ -55,7 +55,7 @@ "@deepseek-ai/dsh-client-ui-slots": "workspace:^", "@deepseek-ai/dsh-commands": "workspace:^", "@types/react": "~18.3.1", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "react": "^18.2.0", "@deepseek-ai/dsh-api-session-controller": "workspace:^", "@deepseek-ai/dsh-client-store": "workspace:^", diff --git a/packages/client/ui-conversation/package.json b/packages/client/ui-conversation/package.json index 060d2a0611..8628f0b603 100644 --- a/packages/client/ui-conversation/package.json +++ b/packages/client/ui-conversation/package.json @@ -46,13 +46,13 @@ }, "license": "MIT", "dependencies": { - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-api-remotes": "workspace:^", "@deepseek-ai/dsh-api-session-controller": "workspace:^", "@deepseek-ai/dsh-api-workspace-controller": "workspace:^", diff --git a/packages/client/ui-deliverables/package.json b/packages/client/ui-deliverables/package.json index 676e3569fd..f9160c942e 100644 --- a/packages/client/ui-deliverables/package.json +++ b/packages/client/ui-deliverables/package.json @@ -45,7 +45,7 @@ }, "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-api-remotes": "workspace:^", @@ -58,7 +58,7 @@ "@deepseek-ai/dsh-client-ui-renderer": "workspace:^", "@deepseek-ai/dsh-client-ui-slots": "workspace:^", "@types/react": "~18.3.1", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "react": "^18.2.0", "@deepseek-ai/dsh-client-ui-primitives": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", diff --git a/packages/client/ui-directory-picker-browse/package.json b/packages/client/ui-directory-picker-browse/package.json index 019e02f3fe..24cfcb3575 100644 --- a/packages/client/ui-directory-picker-browse/package.json +++ b/packages/client/ui-directory-picker-browse/package.json @@ -42,7 +42,7 @@ }, "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-api-remotes": "workspace:^", @@ -54,7 +54,7 @@ "@deepseek-ai/dsh-client-ui-workspace": "workspace:^", "@testing-library/react": "^16.1.0", "@types/react": "~18.3.1", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "react": "^18.2.0", "react-dom": "^18.2.0", "clsx": "^2.0.0" diff --git a/packages/client/ui-directory-picker-native/package.json b/packages/client/ui-directory-picker-native/package.json index e984a73db2..7ed364f0ce 100644 --- a/packages/client/ui-directory-picker-native/package.json +++ b/packages/client/ui-directory-picker-native/package.json @@ -40,14 +40,14 @@ }, "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-client-ui-renderer": "workspace:^", "@deepseek-ai/dsh-client-ui-workspace": "workspace:^", "@testing-library/react": "^16.1.0", "@types/react": "~18.3.1", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "react": "^18.2.0", "react-dom": "^18.2.0" }, diff --git a/packages/client/ui-dockkit/package.json b/packages/client/ui-dockkit/package.json index 570cdebef4..d64cb583b8 100644 --- a/packages/client/ui-dockkit/package.json +++ b/packages/client/ui-dockkit/package.json @@ -23,7 +23,7 @@ }, "license": "MIT", "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-client-ui-primitives": "workspace:^", "@testing-library/react": "^16.1.0", @@ -39,6 +39,6 @@ "lib/types/**/*.d.ts" ], "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/client/ui-goal/package.json b/packages/client/ui-goal/package.json index b59be8fb9a..371fc27b12 100644 --- a/packages/client/ui-goal/package.json +++ b/packages/client/ui-goal/package.json @@ -45,7 +45,7 @@ }, "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-api-remotes": "workspace:^", @@ -62,7 +62,7 @@ "@deepseek-ai/dsh-goal": "workspace:^", "@testing-library/react": "^16.1.0", "@types/react": "~18.3.1", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "react": "^18.2.0", "react-dom": "^18.2.0", "@deepseek-ai/dsh-session": "workspace:^", diff --git a/packages/client/ui-input-trigger/package.json b/packages/client/ui-input-trigger/package.json index 4cf4959203..4af96ec488 100644 --- a/packages/client/ui-input-trigger/package.json +++ b/packages/client/ui-input-trigger/package.json @@ -42,7 +42,7 @@ }, "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-client-locale": "workspace:^", @@ -52,7 +52,7 @@ "@deepseek-ai/dsh-client-ui-primitives": "workspace:^", "@deepseek-ai/dsh-client-ui-slots": "workspace:^", "@types/react": "~18.3.1", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "react": "^18.2.0", "@deepseek-ai/dsh-file-reference": "workspace:^", "@deepseek-ai/dsh-api-session-controller": "workspace:^", diff --git a/packages/client/ui-jobs/package.json b/packages/client/ui-jobs/package.json index d36767585b..e6668f556c 100644 --- a/packages/client/ui-jobs/package.json +++ b/packages/client/ui-jobs/package.json @@ -41,7 +41,7 @@ "access": "public" }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-client-locale": "workspace:^", @@ -50,7 +50,7 @@ "@deepseek-ai/dsh-client-ui-primitives": "workspace:^", "@deepseek-ai/dsh-client-ui-slots": "workspace:^", "@types/react": "~18.3.1", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "react": "^18.2.0", "@deepseek-ai/dsh-api-session-controller": "workspace:^", "@deepseek-ai/dsh-client-ui-renderer": "workspace:^", diff --git a/packages/client/ui-layout/package.json b/packages/client/ui-layout/package.json index 5c56f8dfe9..7ab0b24dcf 100644 --- a/packages/client/ui-layout/package.json +++ b/packages/client/ui-layout/package.json @@ -42,7 +42,7 @@ }, "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-brand": "workspace:^", @@ -53,7 +53,7 @@ "@deepseek-ai/dsh-client-ui-slots": "workspace:^", "@deepseek-ai/dsh-client-ui-theme": "workspace:^", "@types/react": "~18.3.1", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "react": "^18.2.0" }, "files": [ diff --git a/packages/client/ui-message-feedback/package.json b/packages/client/ui-message-feedback/package.json index 051353d43f..c589cd4c23 100644 --- a/packages/client/ui-message-feedback/package.json +++ b/packages/client/ui-message-feedback/package.json @@ -43,7 +43,7 @@ }, "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-api-remotes": "workspace:^", @@ -57,7 +57,7 @@ "@deepseek-ai/dsh-message-feedback": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-typert-protocol": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@testing-library/react": "^16.1.0", "@types/react": "~18.3.1", "@types/react-dom": "~18.3.0", diff --git a/packages/client/ui-model-selection/package.json b/packages/client/ui-model-selection/package.json index bf37cfed12..463be8cc2d 100644 --- a/packages/client/ui-model-selection/package.json +++ b/packages/client/ui-model-selection/package.json @@ -42,7 +42,7 @@ }, "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-api-remotes": "workspace:^", @@ -56,7 +56,7 @@ "@deepseek-ai/dsh-client-ui-slots": "workspace:^", "@deepseek-ai/dsh-typert-protocol": "workspace:^", "@types/react": "~18.3.1", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "react": "^18.2.0", "react-dom": "^18.2.0", "@types/react-dom": "~18.3.0", diff --git a/packages/client/ui-open-in-app/package.json b/packages/client/ui-open-in-app/package.json index 923abdf40e..0c726ef252 100644 --- a/packages/client/ui-open-in-app/package.json +++ b/packages/client/ui-open-in-app/package.json @@ -47,10 +47,10 @@ } }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-api-session-controller": "workspace:^", "@deepseek-ai/dsh-client-locale": "workspace:^", "@deepseek-ai/dsh-client-store": "workspace:^", diff --git a/packages/client/ui-permission-presets/package.json b/packages/client/ui-permission-presets/package.json index d96960bb15..21aaaba411 100644 --- a/packages/client/ui-permission-presets/package.json +++ b/packages/client/ui-permission-presets/package.json @@ -43,10 +43,10 @@ }, "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-api-remotes": "workspace:^", "@deepseek-ai/dsh-api-session-controller": "workspace:^", "@deepseek-ai/dsh-client-locale": "workspace:^", diff --git a/packages/client/ui-plan/package.json b/packages/client/ui-plan/package.json index 49d6f41358..596adb6ee0 100644 --- a/packages/client/ui-plan/package.json +++ b/packages/client/ui-plan/package.json @@ -41,7 +41,7 @@ }, "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-api-remotes": "workspace:^", @@ -52,7 +52,7 @@ "@deepseek-ai/dsh-client-ui-slots": "workspace:^", "@deepseek-ai/dsh-plan-mode": "workspace:^", "@types/react": "~18.3.1", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "react": "^18.2.0", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-client-ui-renderer": "workspace:^", diff --git a/packages/client/ui-primitives/package.json b/packages/client/ui-primitives/package.json index 4c02a1ced6..70f7fba6cb 100644 --- a/packages/client/ui-primitives/package.json +++ b/packages/client/ui-primitives/package.json @@ -25,7 +25,7 @@ "devDependencies": { "@types/react": "~18.3.1", "@types/react-dom": "~18.3.0", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "react": "^18.2.0", "clsx": "^2.0.0", "react-dom": "^18.2.0", @@ -53,6 +53,6 @@ "lib/types/**/*.d.ts" ], "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/client/ui-reference/package.json b/packages/client/ui-reference/package.json index 84dd09e631..4c00e9d339 100644 --- a/packages/client/ui-reference/package.json +++ b/packages/client/ui-reference/package.json @@ -43,7 +43,7 @@ }, "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-api-remotes": "workspace:^", @@ -58,7 +58,7 @@ "@deepseek-ai/dsh-session-reference": "workspace:^", "@deepseek-ai/dsh-typert-protocol": "workspace:^", "@deepseek-ai/dsh-util-workspace-path": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "files": [ "lib/index.js", diff --git a/packages/client/ui-renderer/package.json b/packages/client/ui-renderer/package.json index 17edf34172..99272ba2ea 100644 --- a/packages/client/ui-renderer/package.json +++ b/packages/client/ui-renderer/package.json @@ -41,10 +41,10 @@ }, "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-client-test-runtime": "workspace:^", "@deepseek-ai/dsh-client-ui-slots": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/client/ui-schedule/package.json b/packages/client/ui-schedule/package.json index b4717e39a2..a0f43a1da0 100644 --- a/packages/client/ui-schedule/package.json +++ b/packages/client/ui-schedule/package.json @@ -41,7 +41,7 @@ "access": "public" }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-api-session-controller": "workspace:^", @@ -57,7 +57,7 @@ "@testing-library/react": "^16.1.0", "@types/react": "~18.3.1", "@types/react-dom": "~18.3.0", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "react": "^18.2.0", "react-dom": "^18.2.0" }, diff --git a/packages/client/ui-session/package.json b/packages/client/ui-session/package.json index e7943cbdbf..c4430b80df 100644 --- a/packages/client/ui-session/package.json +++ b/packages/client/ui-session/package.json @@ -40,10 +40,10 @@ }, "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-api-session-controller": "workspace:^", "@deepseek-ai/dsh-client-store": "workspace:^", "@deepseek-ai/dsh-client-ui-renderer": "workspace:^", diff --git a/packages/client/ui-settings-general/package.json b/packages/client/ui-settings-general/package.json index 62ea8b087d..2c4ce21271 100644 --- a/packages/client/ui-settings-general/package.json +++ b/packages/client/ui-settings-general/package.json @@ -43,10 +43,10 @@ }, "license": "MIT", "dependencies": { - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-api-remotes": "workspace:^", @@ -58,7 +58,7 @@ "@deepseek-ai/dsh-client-ui-settings": "workspace:^", "@deepseek-ai/dsh-client-ui-sidebar": "workspace:^", "@deepseek-ai/dsh-client-ui-slots": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@types/react": "~18.3.1", "react": "^18.2.0", "@deepseek-ai/dsh-client-ui-renderer": "workspace:^", diff --git a/packages/client/ui-settings-models/package.json b/packages/client/ui-settings-models/package.json index a44acf6333..b8195de272 100644 --- a/packages/client/ui-settings-models/package.json +++ b/packages/client/ui-settings-models/package.json @@ -41,7 +41,7 @@ }, "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-api-remotes": "workspace:^", @@ -52,7 +52,7 @@ "@deepseek-ai/dsh-client-ui-settings": "workspace:^", "@deepseek-ai/dsh-client-ui-slots": "workspace:^", "@types/react": "~18.3.1", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "react": "^18.2.0", "@deepseek-ai/dsh-client-ui-renderer": "workspace:^", "@deepseek-ai/dsh-util-values": "workspace:^" diff --git a/packages/client/ui-settings-plugin-inventory/package.json b/packages/client/ui-settings-plugin-inventory/package.json index a0e43dbaa4..f7b778f8ab 100644 --- a/packages/client/ui-settings-plugin-inventory/package.json +++ b/packages/client/ui-settings-plugin-inventory/package.json @@ -42,7 +42,7 @@ }, "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-api-remotes": "workspace:^", @@ -54,7 +54,7 @@ "@deepseek-ai/dsh-client-ui-slots": "workspace:^", "@testing-library/react": "^16.1.0", "@types/react": "~18.3.1", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "react": "^18.2.0", "react-dom": "^18.2.0", "@deepseek-ai/dsh-client-ui-renderer": "workspace:^", diff --git a/packages/client/ui-settings-plugins/package.json b/packages/client/ui-settings-plugins/package.json index a9ee3769c3..c442b85e1d 100644 --- a/packages/client/ui-settings-plugins/package.json +++ b/packages/client/ui-settings-plugins/package.json @@ -41,10 +41,10 @@ }, "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-api-remotes": "workspace:^", "@deepseek-ai/dsh-client-locale": "workspace:^", "@deepseek-ai/dsh-client-store": "workspace:^", diff --git a/packages/client/ui-settings/package.json b/packages/client/ui-settings/package.json index d8c8fd594a..77e3121444 100644 --- a/packages/client/ui-settings/package.json +++ b/packages/client/ui-settings/package.json @@ -39,10 +39,10 @@ }, "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-api-remotes": "workspace:^", "@deepseek-ai/dsh-client-store": "workspace:^", "@deepseek-ai/dsh-client-test-runtime": "workspace:^", @@ -50,7 +50,7 @@ "@deepseek-ai/dsh-settings": "workspace:^", "@types/react": "~18.3.1", "react": "^18.2.0", - "@deepseek-ai/schemastery": "workspace:^", + "@deepseek-ai/schemastery": "workspace:*", "@deepseek-ai/dsh-util-values": "workspace:^" }, "files": [ diff --git a/packages/client/ui-sidebar-documentpreview/package.json b/packages/client/ui-sidebar-documentpreview/package.json index c84f696313..6dff631937 100644 --- a/packages/client/ui-sidebar-documentpreview/package.json +++ b/packages/client/ui-sidebar-documentpreview/package.json @@ -43,10 +43,10 @@ }, "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-api-gateway": "workspace:^", "@deepseek-ai/dsh-api-remotes": "workspace:^", "@deepseek-ai/dsh-api-workspace-files": "workspace:^", diff --git a/packages/client/ui-sidebar-files/package.json b/packages/client/ui-sidebar-files/package.json index c9b0f30663..2da4742959 100644 --- a/packages/client/ui-sidebar-files/package.json +++ b/packages/client/ui-sidebar-files/package.json @@ -42,10 +42,10 @@ }, "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-api-remotes": "workspace:^", "@deepseek-ai/dsh-api-workspace-files": "workspace:^", "@deepseek-ai/dsh-client-locale": "workspace:^", diff --git a/packages/client/ui-sidebar-right/package.json b/packages/client/ui-sidebar-right/package.json index 05c813fcc2..ab8a79d601 100644 --- a/packages/client/ui-sidebar-right/package.json +++ b/packages/client/ui-sidebar-right/package.json @@ -43,10 +43,10 @@ }, "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-api-session-controller": "workspace:^", "@deepseek-ai/dsh-client-locale": "workspace:^", "@deepseek-ai/dsh-client-resources": "workspace:^", diff --git a/packages/client/ui-sidebar/package.json b/packages/client/ui-sidebar/package.json index e3329d2ad5..c15eb7aa15 100644 --- a/packages/client/ui-sidebar/package.json +++ b/packages/client/ui-sidebar/package.json @@ -44,7 +44,7 @@ }, "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-api-workspace-controller": "workspace:^", @@ -58,7 +58,7 @@ "@deepseek-ai/dsh-client-ui-session": "workspace:^", "@deepseek-ai/dsh-client-ui-workspace": "workspace:^", "@types/react": "~18.3.1", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "react": "^18.2.0", "clsx": "^2.0.0" }, diff --git a/packages/client/ui-skill/package.json b/packages/client/ui-skill/package.json index 312000f453..faad887629 100644 --- a/packages/client/ui-skill/package.json +++ b/packages/client/ui-skill/package.json @@ -44,7 +44,7 @@ }, "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-api-remotes": "workspace:^", @@ -60,7 +60,7 @@ "@deepseek-ai/dsh-session": "workspace:^", "@testing-library/react": "^16.1.0", "@types/react": "~18.3.1", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "react": "^18.2.0", "react-dom": "^18.2.0" }, diff --git a/packages/client/ui-slots/package.json b/packages/client/ui-slots/package.json index aa3ea2b5db..c4e442da26 100644 --- a/packages/client/ui-slots/package.json +++ b/packages/client/ui-slots/package.json @@ -25,13 +25,13 @@ "devDependencies": { "@deepseek-ai/dsh-client-store": "workspace:^", "@types/react": "~18.3.1", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "files": [ "lib/index.js", "lib/types/**/*.d.ts" ], "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/client/ui-subagent/package.json b/packages/client/ui-subagent/package.json index 013105cce6..a25900dea8 100644 --- a/packages/client/ui-subagent/package.json +++ b/packages/client/ui-subagent/package.json @@ -43,7 +43,7 @@ }, "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-client-locale": "workspace:^", @@ -56,7 +56,7 @@ "@deepseek-ai/dsh-token-meter": "workspace:^", "@types/react": "~18.3.1", "@types/react-dom": "~18.3.0", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "react": "^18.2.0", "react-dom": "^18.2.0", "@deepseek-ai/dsh-api-session-controller": "workspace:^", diff --git a/packages/client/ui-theme/package.json b/packages/client/ui-theme/package.json index 5a7a7fb249..eca96065c0 100644 --- a/packages/client/ui-theme/package.json +++ b/packages/client/ui-theme/package.json @@ -40,10 +40,10 @@ }, "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-api-remotes": "workspace:^", "@deepseek-ai/dsh-client-connection": "workspace:^", "@deepseek-ai/dsh-client-locale": "workspace:^", @@ -70,6 +70,6 @@ "watch": "tsdown --watch" }, "dependencies": { - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" } } diff --git a/packages/client/ui-tool/package.json b/packages/client/ui-tool/package.json index 8e2770e323..11ddae1f81 100644 --- a/packages/client/ui-tool/package.json +++ b/packages/client/ui-tool/package.json @@ -42,7 +42,7 @@ }, "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-spill-policy": "workspace:^", @@ -53,7 +53,7 @@ "@deepseek-ai/dsh-tools": "workspace:^", "@deepseek-ai/dsh-spill": "workspace:^", "@deepseek-ai/dsh-code-runtime-worker-thread": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-api-remotes": "workspace:^", "@deepseek-ai/dsh-client-connection": "workspace:^", "@deepseek-ai/dsh-client-locale": "workspace:^", diff --git a/packages/client/ui-trajectory/package.json b/packages/client/ui-trajectory/package.json index 6eb6fc741f..32e664d600 100644 --- a/packages/client/ui-trajectory/package.json +++ b/packages/client/ui-trajectory/package.json @@ -43,7 +43,7 @@ }, "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -56,7 +56,7 @@ "@deepseek-ai/dsh-tools": "workspace:^", "@types/react": "~18.3.1", "@types/react-dom": "~18.3.0", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "react": "^18.2.0", "react-dom": "^18.2.0", "@deepseek-ai/dsh-client-store": "workspace:^", diff --git a/packages/client/ui-user-questions/package.json b/packages/client/ui-user-questions/package.json index 43a56f951a..2c8e881b99 100644 --- a/packages/client/ui-user-questions/package.json +++ b/packages/client/ui-user-questions/package.json @@ -44,10 +44,10 @@ }, "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-api-remotes": "workspace:^", "@deepseek-ai/dsh-api-session-controller": "workspace:^", diff --git a/packages/client/ui-workflow-run/package.json b/packages/client/ui-workflow-run/package.json index ac5afa61bf..98a545b350 100644 --- a/packages/client/ui-workflow-run/package.json +++ b/packages/client/ui-workflow-run/package.json @@ -49,7 +49,7 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-api-session-controller": "workspace:^", @@ -66,7 +66,7 @@ "@deepseek-ai/dsh-tool-workflow": "workspace:^", "@deepseek-ai/dsh-workflow": "workspace:^", "@types/react": "~18.3.1", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "react": "^18.2.0" } } diff --git a/packages/client/ui-workspace/package.json b/packages/client/ui-workspace/package.json index 086992fd19..96f844a25b 100644 --- a/packages/client/ui-workspace/package.json +++ b/packages/client/ui-workspace/package.json @@ -48,7 +48,7 @@ }, "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-api-remotes": "workspace:^", @@ -70,7 +70,7 @@ "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-util-workspace-path": "workspace:^", "@types/react": "~18.3.1", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "react": "^18.2.0", "clsx": "^2.0.0" }, diff --git a/packages/client/web/package.json b/packages/client/web/package.json index 4b84e01cf3..07f0783d0f 100644 --- a/packages/client/web/package.json +++ b/packages/client/web/package.json @@ -23,7 +23,7 @@ }, "license": "MIT", "devDependencies": { - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis-plugin-loader": "workspace:*", "@deepseek-ai/dsh-client-modules": "workspace:^", "@deepseek-ai/dsh-client-store": "workspace:^", "@deepseek-ai/dsh-client-ui-dockkit": "workspace:^", @@ -32,13 +32,13 @@ "@deepseek-ai/dsh-client-ui-slots": "workspace:^", "@types/react": "~18.3.1", "@types/react-dom": "~18.3.0", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "react": "^18.2.0", "react-dom": "^18.2.0", "typescript": "^6.0.3" }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "files": [ "lib/index.js", diff --git a/packages/code-runtime/code-runtime-worker-thread/package.json b/packages/code-runtime/code-runtime-worker-thread/package.json index 5f18cafa8b..9491b8e996 100644 --- a/packages/code-runtime/code-runtime-worker-thread/package.json +++ b/packages/code-runtime/code-runtime-worker-thread/package.json @@ -31,17 +31,17 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-code-runtime": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-timeout": "workspace:^" }, "dependencies": { "@deepseek-ai/dsh-util-values": "workspace:^", - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-code-runtime": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-timeout": "workspace:^" diff --git a/packages/code-runtime/code-runtime/package.json b/packages/code-runtime/code-runtime/package.json index 7e31f4998e..070c598183 100644 --- a/packages/code-runtime/code-runtime/package.json +++ b/packages/code-runtime/code-runtime/package.json @@ -27,9 +27,9 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/compaction/command-compact/package.json b/packages/compaction/command-compact/package.json index ac4c49b3b6..de807314c1 100644 --- a/packages/compaction/command-compact/package.json +++ b/packages/compaction/command-compact/package.json @@ -29,16 +29,16 @@ "peerDependencies": { "@deepseek-ai/dsh-commands": "workspace:^", "@deepseek-ai/dsh-compaction": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis-plugin-include": "workspace:^", - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis-plugin-include": "workspace:*", + "@deepseek-ai/cordis-plugin-loader": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-commands": "workspace:^", "@deepseek-ai/dsh-compaction": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/compaction/compaction-basic/package.json b/packages/compaction/compaction-basic/package.json index 82f980e727..60eac2756d 100644 --- a/packages/compaction/compaction-basic/package.json +++ b/packages/compaction/compaction-basic/package.json @@ -27,7 +27,7 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-commands": "workspace:^", "@deepseek-ai/dsh-compaction": "workspace:^", @@ -43,12 +43,12 @@ }, "dependencies": { "@deepseek-ai/dsh-util-values": "workspace:^", - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", - "@deepseek-ai/cordis-plugin-include": "workspace:^", - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", + "@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:^", diff --git a/packages/compaction/compaction-tool-result-pruner/package.json b/packages/compaction/compaction-tool-result-pruner/package.json index 93eedeba7f..d163cc7f2b 100644 --- a/packages/compaction/compaction-tool-result-pruner/package.json +++ b/packages/compaction/compaction-tool-result-pruner/package.json @@ -27,7 +27,7 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-compaction": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", @@ -35,12 +35,12 @@ }, "dependencies": { "@deepseek-ai/dsh-util-values": "workspace:^", - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", - "@deepseek-ai/cordis-plugin-include": "workspace:^", - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", + "@deepseek-ai/cordis-plugin-include": "workspace:*", + "@deepseek-ai/cordis-plugin-loader": "workspace:*", "@deepseek-ai/dsh-compaction": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", diff --git a/packages/compaction/compaction/package.json b/packages/compaction/compaction/package.json index 4382613ca4..8d21374edb 100644 --- a/packages/compaction/compaction/package.json +++ b/packages/compaction/compaction/package.json @@ -46,7 +46,7 @@ "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", - "@deepseek-ai/cordis": "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": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/context/agent-instructions/package.json b/packages/context/agent-instructions/package.json index 7fa0bba69e..1531f9a2b3 100644 --- a/packages/context/agent-instructions/package.json +++ b/packages/context/agent-instructions/package.json @@ -27,7 +27,7 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-fs": "workspace:^", "@deepseek-ai/dsh-home-paths": "workspace:^", @@ -38,11 +38,11 @@ }, "dependencies": { "@deepseek-ai/dsh-util-values": "workspace:^", - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis": "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:^", diff --git a/packages/context/file-reference-local/package.json b/packages/context/file-reference-local/package.json index 998c6e2e52..90b4656d9f 100644 --- a/packages/context/file-reference-local/package.json +++ b/packages/context/file-reference-local/package.json @@ -32,20 +32,20 @@ ], "license": "MIT", "dependencies": { - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "peerDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-file-reference": "workspace:^", "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-file-reference": "workspace:^", "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/context/file-reference/package.json b/packages/context/file-reference/package.json index abc2a1cc2a..f0334f1da6 100644 --- a/packages/context/file-reference/package.json +++ b/packages/context/file-reference/package.json @@ -37,10 +37,10 @@ "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/context/session-reference/package.json b/packages/context/session-reference/package.json index e4e17c536b..3b89b9786e 100644 --- a/packages/context/session-reference/package.json +++ b/packages/context/session-reference/package.json @@ -46,11 +46,11 @@ "dependencies": { "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-util-values": "workspace:^", - "@deepseek-ai/schemastery": "workspace:^", + "@deepseek-ai/schemastery": "workspace:*", "zod": "^4.4.3" }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-compaction": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", @@ -73,9 +73,9 @@ } }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", - "@deepseek-ai/cordis-plugin-include": "workspace:^", - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", + "@deepseek-ai/cordis-plugin-include": "workspace:*", + "@deepseek-ai/cordis-plugin-loader": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-compaction": "workspace:^", "@deepseek-ai/dsh-fs-local": "workspace:^", diff --git a/packages/context/time-context/package.json b/packages/context/time-context/package.json index 94023206a8..fcbdda6b7b 100644 --- a/packages/context/time-context/package.json +++ b/packages/context/time-context/package.json @@ -33,11 +33,11 @@ "license": "MIT", "dependencies": { "@deepseek-ai/dsh-util-values": "workspace:^", - "@deepseek-ai/schemastery": "workspace:^", + "@deepseek-ai/schemastery": "workspace:*", "zod": "^4.4.3" }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", @@ -45,7 +45,7 @@ "@deepseek-ai/dsh-session-projection": "workspace:^" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-agent-loop": "workspace:^", "@deepseek-ai/dsh-agent-loop-testkit": "workspace:^", diff --git a/packages/context/tmux-context/package.json b/packages/context/tmux-context/package.json index 95a04c31b9..b1021c6215 100644 --- a/packages/context/tmux-context/package.json +++ b/packages/context/tmux-context/package.json @@ -27,14 +27,14 @@ ], "license": "MIT", "dependencies": { - "@deepseek-ai/schemastery": "workspace:^", + "@deepseek-ai/schemastery": "workspace:*", "zod": "^4.4.3" }, "peerDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-shell": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-session-projection": "workspace:^" }, "devDependencies": { @@ -44,7 +44,7 @@ "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-system-prompt": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-session-projection": "workspace:^" } } diff --git a/packages/core/agent-default-model/package.json b/packages/core/agent-default-model/package.json index 109ae3394d..ade673f6d5 100644 --- a/packages/core/agent-default-model/package.json +++ b/packages/core/agent-default-model/package.json @@ -27,18 +27,18 @@ ], "license": "MIT", "dependencies": { - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "peerDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-settings": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-settings": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/core/agent-loop/package.json b/packages/core/agent-loop/package.json index 708c7c514a..5091fddbdd 100644 --- a/packages/core/agent-loop/package.json +++ b/packages/core/agent-loop/package.json @@ -31,7 +31,7 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", @@ -46,11 +46,11 @@ "dependencies": { "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-util-values": "workspace:^", - "@deepseek-ai/schemastery": "workspace:^", + "@deepseek-ai/schemastery": "workspace:*", "zod": "^4.4.3" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-llm-pi-ai": "workspace:^", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/core/agent-tool-presentation/package.json b/packages/core/agent-tool-presentation/package.json index 10109f5ef1..5bc00141ab 100644 --- a/packages/core/agent-tool-presentation/package.json +++ b/packages/core/agent-tool-presentation/package.json @@ -27,11 +27,11 @@ ], "license": "MIT", "dependencies": { - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "peerDependencies": { "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -40,6 +40,6 @@ "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/core/agent/package.json b/packages/core/agent/package.json index b34895cb88..f85e083ab8 100644 --- a/packages/core/agent/package.json +++ b/packages/core/agent/package.json @@ -45,7 +45,7 @@ "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-typert-protocol": "workspace:^", "@deepseek-ai/dsh-util-values": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", @@ -57,6 +57,6 @@ "@deepseek-ai/dsh-typert-protocol": "workspace:^", "@deepseek-ai/dsh-typert-registry": "workspace:^", "@deepseek-ai/dsh-util-values": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/core/scope/package.json b/packages/core/scope/package.json index 3ac55af4cb..268e0fdbe9 100644 --- a/packages/core/scope/package.json +++ b/packages/core/scope/package.json @@ -33,10 +33,10 @@ "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/core/session/package.json b/packages/core/session/package.json index 4f43ac08dd..4215779d0c 100644 --- a/packages/core/session/package.json +++ b/packages/core/session/package.json @@ -42,14 +42,14 @@ "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-scope": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-scope": "workspace:^", "@deepseek-ai/dsh-typert-protocol": "workspace:^", "@deepseek-ai/dsh-typert-registry": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "dependencies": { "@deepseek-ai/dsh-llm": "workspace:^", diff --git a/packages/core/system-prompt/package.json b/packages/core/system-prompt/package.json index 0df2d6de53..8ec4194a77 100644 --- a/packages/core/system-prompt/package.json +++ b/packages/core/system-prompt/package.json @@ -35,15 +35,15 @@ "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-scope": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "dependencies": { - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-scope": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/core/tools/package.json b/packages/core/tools/package.json index e3d6cdc3b8..0e37581818 100644 --- a/packages/core/tools/package.json +++ b/packages/core/tools/package.json @@ -41,7 +41,7 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-code-runtime": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", @@ -54,10 +54,10 @@ "dependencies": { "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-util-values": "workspace:^", - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-code-runtime": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/credentials/authorization/package.json b/packages/credentials/authorization/package.json index 830bdf51fe..76e5b79cef 100644 --- a/packages/credentials/authorization/package.json +++ b/packages/credentials/authorization/package.json @@ -40,12 +40,12 @@ "@deepseek-ai/dsh-credentials": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-credentials": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/credentials/credentials-local/package.json b/packages/credentials/credentials-local/package.json index c33473e37f..c7d7d2128a 100644 --- a/packages/credentials/credentials-local/package.json +++ b/packages/credentials/credentials-local/package.json @@ -31,11 +31,11 @@ "@deepseek-ai/dsh-credentials": "workspace:^", "@deepseek-ai/dsh-launch-environment": "workspace:^", "@deepseek-ai/dsh-home-paths": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "dependencies": { "chokidar": "^4.0.3", - "@deepseek-ai/schemastery": "workspace:^", + "@deepseek-ai/schemastery": "workspace:*", "yaml": "^2.9.0" }, "devDependencies": { @@ -43,6 +43,6 @@ "@deepseek-ai/dsh-credentials": "workspace:^", "@deepseek-ai/dsh-launch-environment": "workspace:^", "@deepseek-ai/dsh-home-paths": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/credentials/credentials/package.json b/packages/credentials/credentials/package.json index 2b442b47c8..bc5c80beb8 100644 --- a/packages/credentials/credentials/package.json +++ b/packages/credentials/credentials/package.json @@ -37,11 +37,11 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-invariants": "workspace:^" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-invariants": "workspace:^" }, "dependencies": { diff --git a/packages/e2b/e2b/package.json b/packages/e2b/e2b/package.json index 9a2bd625fc..602ed51b2c 100644 --- a/packages/e2b/e2b/package.json +++ b/packages/e2b/e2b/package.json @@ -27,15 +27,15 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-http-proxy": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "workspace:^", + "@deepseek-ai/schemastery": "workspace:*", "e2b": "2.29.1" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-agent-loop-testkit": "workspace:^", "@deepseek-ai/dsh-app-boot": "workspace:^", diff --git a/packages/e2b/fs-e2b/package.json b/packages/e2b/fs-e2b/package.json index 4381fe7e86..6f989f2b8a 100644 --- a/packages/e2b/fs-e2b/package.json +++ b/packages/e2b/fs-e2b/package.json @@ -29,11 +29,11 @@ "peerDependencies": { "@deepseek-ai/dsh-e2b": "workspace:^", "@deepseek-ai/dsh-fs": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-e2b": "workspace:^", "@deepseek-ai/dsh-fs": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/e2b/subprocess-e2b/package.json b/packages/e2b/subprocess-e2b/package.json index f5824b362c..c6a7342657 100644 --- a/packages/e2b/subprocess-e2b/package.json +++ b/packages/e2b/subprocess-e2b/package.json @@ -30,15 +30,15 @@ "@deepseek-ai/dsh-e2b": "workspace:^", "@deepseek-ai/dsh-subprocess": "workspace:^", "@deepseek-ai/dsh-timeout": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "dependencies": { - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-e2b": "workspace:^", "@deepseek-ai/dsh-subprocess": "workspace:^", "@deepseek-ai/dsh-timeout": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/experimental/agent-team-profile/package.json b/packages/experimental/agent-team-profile/package.json index 51fefe782d..1414ef126c 100644 --- a/packages/experimental/agent-team-profile/package.json +++ b/packages/experimental/agent-team-profile/package.json @@ -38,11 +38,11 @@ "@deepseek-ai/dsh-experimental-tool-agent-team": "workspace:^" }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis-plugin-include": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis-plugin-include": "workspace:*", + "@deepseek-ai/cordis": "workspace:*", "js-yaml": "^4.2.0" } } diff --git a/packages/experimental/agent-team-web-profile/package.json b/packages/experimental/agent-team-web-profile/package.json index e4df1779f9..1bd3692f3e 100644 --- a/packages/experimental/agent-team-web-profile/package.json +++ b/packages/experimental/agent-team-web-profile/package.json @@ -37,11 +37,11 @@ "@deepseek-ai/dsh-experimental-client-ui-agent-team": "workspace:^" }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis-plugin-include": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis-plugin-include": "workspace:*", + "@deepseek-ai/cordis": "workspace:*", "js-yaml": "^4.2.0" } } diff --git a/packages/experimental/agent-team/package.json b/packages/experimental/agent-team/package.json index b61057e3aa..c15441b1a7 100644 --- a/packages/experimental/agent-team/package.json +++ b/packages/experimental/agent-team/package.json @@ -54,11 +54,11 @@ "license": "MIT", "dependencies": { "@deepseek-ai/dsh-brand": "workspace:^", - "@deepseek-ai/schemastery": "workspace:^", + "@deepseek-ai/schemastery": "workspace:*", "zod": "^4.4.3" }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", @@ -69,7 +69,7 @@ "@deepseek-ai/dsh-typert-protocol": "workspace:^" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-agent-loop": "workspace:^", "@deepseek-ai/dsh-agent-loop-testkit": "workspace:^", diff --git a/packages/experimental/client-ui-agent-team/package.json b/packages/experimental/client-ui-agent-team/package.json index 4932c980ba..563a2c7a75 100644 --- a/packages/experimental/client-ui-agent-team/package.json +++ b/packages/experimental/client-ui-agent-team/package.json @@ -57,7 +57,7 @@ "@deepseek-ai/dsh-experimental-agent-team": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-typert-protocol": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-api-remotes": "workspace:^", @@ -74,7 +74,7 @@ "@deepseek-ai/dsh-typert-protocol": "workspace:^", "@testing-library/react": "^16.1.0", "@types/react": "~18.3.1", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "react-dom": "^18.2.0" }, "files": [ diff --git a/packages/experimental/code-runtime-python/package.json b/packages/experimental/code-runtime-python/package.json index 2fb430b5a8..ceaa310bdf 100644 --- a/packages/experimental/code-runtime-python/package.json +++ b/packages/experimental/code-runtime-python/package.json @@ -26,17 +26,17 @@ "peerDependencies": { "@deepseek-ai/dsh-code-runtime": "workspace:^", "@deepseek-ai/dsh-timeout": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-util-values": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-code-runtime": "workspace:^", "@deepseek-ai/dsh-timeout": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-util-values": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "private": true } diff --git a/packages/experimental/inspector/package.json b/packages/experimental/inspector/package.json index b7983de638..fe46f14acc 100644 --- a/packages/experimental/inspector/package.json +++ b/packages/experimental/inspector/package.json @@ -39,19 +39,19 @@ "dependencies": { "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-util-crypto": "workspace:^", - "@deepseek-ai/schemastery": "workspace:^", + "@deepseek-ai/schemastery": "workspace:*", "ws": "^8.21.0" }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", + "@deepseek-ai/cordis-plugin-loader": "workspace:*", "@deepseek-ai/dsh-client-modules": "workspace:^", "@deepseek-ai/dsh-host-webserver": "workspace:^" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", - "@deepseek-ai/cordis-plugin-include": "workspace:^", - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", + "@deepseek-ai/cordis-plugin-include": "workspace:*", + "@deepseek-ai/cordis-plugin-loader": "workspace:*", "@deepseek-ai/dsh-host-webserver": "workspace:^", "@types/ws": "^8.18.1", "playwright": "^1.49.0", diff --git a/packages/experimental/tool-agent-team/package.json b/packages/experimental/tool-agent-team/package.json index be33c259a2..7f08e60b07 100644 --- a/packages/experimental/tool-agent-team/package.json +++ b/packages/experimental/tool-agent-team/package.json @@ -27,7 +27,7 @@ ], "license": "MIT", "dependencies": { - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "peerDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -35,7 +35,7 @@ "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-experimental-agent-team": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -53,6 +53,6 @@ "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-experimental-agent-team": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/experimental/webworker-packer/package.json b/packages/experimental/webworker-packer/package.json index ca79afecb6..a98d0e2064 100644 --- a/packages/experimental/webworker-packer/package.json +++ b/packages/experimental/webworker-packer/package.json @@ -31,19 +31,19 @@ ], "license": "MIT", "dependencies": { - "@deepseek-ai/cordis-plugin-include": "workspace:^", + "@deepseek-ai/cordis-plugin-include": "workspace:*", "@deepseek-ai/dsh-experimental-webworker-runtime": "workspace:^", "@deepseek-ai/dsh-home-paths": "workspace:^", "js-yaml": "^4.2.0", "picomatch": "^4.0.4" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@types/js-yaml": "^4.0.9", "@types/picomatch": "^3.0.2", "@deepseek-ai/dsh-package-manifest": "workspace:^" }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/experimental/webworker-runtime/package.json b/packages/experimental/webworker-runtime/package.json index ec646a9b60..ac04c0d104 100644 --- a/packages/experimental/webworker-runtime/package.json +++ b/packages/experimental/webworker-runtime/package.json @@ -35,15 +35,15 @@ "readable-stream": "^4.7.0" }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", + "@deepseek-ai/cordis-plugin-loader": "workspace:*", "@deepseek-ai/dsh-client-connection": "workspace:^", "@deepseek-ai/dsh-client-modules": "workspace:^", "@deepseek-ai/dsh-host-webserver": "workspace:^" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", + "@deepseek-ai/cordis-plugin-loader": "workspace:*", "@deepseek-ai/dsh-api-gateway": "workspace:^", "@deepseek-ai/dsh-bash-sandbox": "workspace:^", "@deepseek-ai/dsh-client-connection": "workspace:^", diff --git a/packages/extensions/cordis-client-runner/package.json b/packages/extensions/cordis-client-runner/package.json index 4b96b17335..ceb94aeaed 100644 --- a/packages/extensions/cordis-client-runner/package.json +++ b/packages/extensions/cordis-client-runner/package.json @@ -42,16 +42,16 @@ }, "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis-plugin-loader": "workspace:*", "@deepseek-ai/dsh-api-remotes": "workspace:^", "@deepseek-ai/dsh-client-modules": "workspace:^", "@deepseek-ai/dsh-client-ui-renderer": "workspace:^", "@deepseek-ai/dsh-client-ui-theme": "workspace:^", "@types/react": "~18.3.1", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "react": "^18.2.0", "@deepseek-ai/dsh-util-values": "workspace:^" }, diff --git a/packages/extensions/cordis-host-runner/package.json b/packages/extensions/cordis-host-runner/package.json index a4578ed8c6..d8ebc413e8 100644 --- a/packages/extensions/cordis-host-runner/package.json +++ b/packages/extensions/cordis-host-runner/package.json @@ -45,11 +45,11 @@ "license": "MIT", "dependencies": { "@deepseek-ai/dsh-util-values": "workspace:^", - "@deepseek-ai/schemastery": "workspace:^", + "@deepseek-ai/schemastery": "workspace:*", "zod": "^4.4.3" }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", @@ -59,8 +59,8 @@ "@deepseek-ai/dsh-typert-protocol": "workspace:^" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", - "@deepseek-ai/cordis-plugin-timer": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", + "@deepseek-ai/cordis-plugin-timer": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", diff --git a/packages/extensions/tool-cordis/package.json b/packages/extensions/tool-cordis/package.json index 77e0883e7b..d19d0fb5ef 100644 --- a/packages/extensions/tool-cordis/package.json +++ b/packages/extensions/tool-cordis/package.json @@ -34,10 +34,10 @@ "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis-plugin-loader": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-cordis-host-runner": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", @@ -45,6 +45,6 @@ "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/extensions/ui-cordis/package.json b/packages/extensions/ui-cordis/package.json index 4bad5de8e9..32b78e9ed7 100644 --- a/packages/extensions/ui-cordis/package.json +++ b/packages/extensions/ui-cordis/package.json @@ -47,7 +47,7 @@ }, "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-api-remotes": "workspace:^", @@ -63,7 +63,7 @@ "@deepseek-ai/dsh-client-ui-slots": "workspace:^", "@deepseek-ai/dsh-client-ui-tool": "workspace:^", "@types/react": "~18.3.1", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "react": "^18.2.0" }, "files": [ diff --git a/packages/feedback/command-feedback/package.json b/packages/feedback/command-feedback/package.json index 3b0414d813..77fb5b7fc7 100644 --- a/packages/feedback/command-feedback/package.json +++ b/packages/feedback/command-feedback/package.json @@ -47,22 +47,22 @@ "@deepseek-ai/dsh-commands": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-anonymous-user-id": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-typert-protocol": "workspace:^" }, "dependencies": { "zod": "^4.4.3" }, "devDependencies": { - "@deepseek-ai/cordis-plugin-include": "workspace:^", - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis-plugin-include": "workspace:*", + "@deepseek-ai/cordis-plugin-loader": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-agent-loop-testkit": "workspace:^", "@deepseek-ai/dsh-commands": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-anonymous-user-id": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-typert-protocol": "workspace:^" } } diff --git a/packages/feedback/message-feedback/package.json b/packages/feedback/message-feedback/package.json index 90134101c3..abfa697159 100644 --- a/packages/feedback/message-feedback/package.json +++ b/packages/feedback/message-feedback/package.json @@ -49,23 +49,23 @@ "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-session-persistence": "workspace:^", "@deepseek-ai/dsh-typert-protocol": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-command-feedback": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "workspace:^", + "@deepseek-ai/schemastery": "workspace:*", "zod": "^4.4.3" }, "devDependencies": { - "@deepseek-ai/cordis-plugin-include": "workspace:^", - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis-plugin-include": "workspace:*", + "@deepseek-ai/cordis-plugin-loader": "workspace:*", "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-session-persistence": "workspace:^", "@deepseek-ai/dsh-session-persistence-jsonl": "workspace:^", "@deepseek-ai/dsh-typert-protocol": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-command-feedback": "workspace:^" } } diff --git a/packages/fs/fs-local/package.json b/packages/fs/fs-local/package.json index 2a70ac51a7..56a9da2f6a 100644 --- a/packages/fs/fs-local/package.json +++ b/packages/fs/fs-local/package.json @@ -28,15 +28,15 @@ "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-fs": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "dependencies": { "koffi": "^3.1.0", - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-fs": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/fs/fs-observation-policy/package.json b/packages/fs/fs-observation-policy/package.json index 978f3d0ae7..59ad5acad9 100644 --- a/packages/fs/fs-observation-policy/package.json +++ b/packages/fs/fs-observation-policy/package.json @@ -28,11 +28,11 @@ "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-fs": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-fs": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/fs/fs-sandbox/package.json b/packages/fs/fs-sandbox/package.json index e1261a7f14..dc2bb684d9 100644 --- a/packages/fs/fs-sandbox/package.json +++ b/packages/fs/fs-sandbox/package.json @@ -31,14 +31,14 @@ "@deepseek-ai/dsh-fs-local": "workspace:^", "@deepseek-ai/dsh-sandbox": "workspace:^", "@deepseek-ai/dsh-sandbox-policy": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-fs": "workspace:^", "@deepseek-ai/dsh-fs-local": "workspace:^", "@deepseek-ai/dsh-sandbox": "workspace:^", "@deepseek-ai/dsh-sandbox-policy": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-session-projection": "workspace:^" } } diff --git a/packages/fs/fs/package.json b/packages/fs/fs/package.json index 800220fbbb..a46cf65967 100644 --- a/packages/fs/fs/package.json +++ b/packages/fs/fs/package.json @@ -36,13 +36,13 @@ "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-sandbox": "workspace:^", - "@deepseek-ai/cordis": "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": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/fs/tool-fs-search/package.json b/packages/fs/tool-fs-search/package.json index b4bab8a8c4..20ecda599d 100644 --- a/packages/fs/tool-fs-search/package.json +++ b/packages/fs/tool-fs-search/package.json @@ -28,7 +28,7 @@ "license": "MIT", "dependencies": { "@vscode/ripgrep": "^1.18.0", - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "peerDependencies": { "@deepseek-ai/dsh-llm": "workspace:^", @@ -39,7 +39,7 @@ "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-timeout": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -52,7 +52,7 @@ "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-timeout": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-scope": "workspace:^" } } diff --git a/packages/fs/tool-fs/package.json b/packages/fs/tool-fs/package.json index 3486c30fd1..03f16c0632 100644 --- a/packages/fs/tool-fs/package.json +++ b/packages/fs/tool-fs/package.json @@ -28,7 +28,7 @@ "license": "MIT", "dependencies": { "diff": "^9.0.0", - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "peerDependencies": { "@deepseek-ai/dsh-attachment": "workspace:^", @@ -40,7 +40,7 @@ "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", "@deepseek-ai/dsh-user-approval": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -58,7 +58,7 @@ "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", "@deepseek-ai/dsh-user-approval": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-session-projection": "workspace:^", "@deepseek-ai/dsh-scope": "workspace:^", "@deepseek-ai/dsh-code-runtime": "workspace:^" diff --git a/packages/fs/tool-present/package.json b/packages/fs/tool-present/package.json index 18e5bb3d4a..659cea88a0 100644 --- a/packages/fs/tool-present/package.json +++ b/packages/fs/tool-present/package.json @@ -32,10 +32,10 @@ "lib/types/**/*.d.ts" ], "dependencies": { - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-fs": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", @@ -44,7 +44,7 @@ "@deepseek-ai/dsh-tools": "workspace:^" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-fs": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", diff --git a/packages/fs/tool-str-replace-editor/package.json b/packages/fs/tool-str-replace-editor/package.json index 92b0be3892..e1e35a2a86 100644 --- a/packages/fs/tool-str-replace-editor/package.json +++ b/packages/fs/tool-str-replace-editor/package.json @@ -30,10 +30,10 @@ "@deepseek-ai/dsh-sandbox": "workspace:^", "@deepseek-ai/dsh-sandbox-policy": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "dependencies": { - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -48,7 +48,7 @@ "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-session-projection": "workspace:^" } } diff --git a/packages/goal/command-goal/package.json b/packages/goal/command-goal/package.json index 1b0dfe53d3..96d36bc0ad 100644 --- a/packages/goal/command-goal/package.json +++ b/packages/goal/command-goal/package.json @@ -30,10 +30,10 @@ "@deepseek-ai/dsh-commands": "workspace:^", "@deepseek-ai/dsh-goal": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis-plugin-loader": "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:^", @@ -41,7 +41,7 @@ "@deepseek-ai/dsh-goal": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-session-projection": "workspace:^" } } diff --git a/packages/goal/goal-round-driver/package.json b/packages/goal/goal-round-driver/package.json index 6a43469b1d..9f3b170dee 100644 --- a/packages/goal/goal-round-driver/package.json +++ b/packages/goal/goal-round-driver/package.json @@ -37,7 +37,7 @@ "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -49,7 +49,7 @@ "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-session-projection": "workspace:^" } } diff --git a/packages/goal/goal/package.json b/packages/goal/goal/package.json index e4664dffef..07496de265 100644 --- a/packages/goal/goal/package.json +++ b/packages/goal/goal/package.json @@ -61,10 +61,10 @@ "@deepseek-ai/dsh-scope": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-typert-protocol": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "dependencies": { - "@deepseek-ai/schemastery": "workspace:^", + "@deepseek-ai/schemastery": "workspace:*", "zod": "^4.4.3" }, "devDependencies": { @@ -83,6 +83,6 @@ "@deepseek-ai/dsh-session-persistence-jsonl": "workspace:^", "@deepseek-ai/dsh-subprocess-local": "workspace:^", "@deepseek-ai/dsh-typert-protocol": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/goal/tool-goal/package.json b/packages/goal/tool-goal/package.json index 69f3285384..51bd83f6fd 100644 --- a/packages/goal/tool-goal/package.json +++ b/packages/goal/tool-goal/package.json @@ -33,14 +33,14 @@ "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-session-projection": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis-plugin-loader": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-agent-loop-testkit": "workspace:^", "@deepseek-ai/dsh-agent-loop": "workspace:^", @@ -49,7 +49,7 @@ "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-session-projection": "workspace:^" } } diff --git a/packages/guard/repeat-tool-reminder/package.json b/packages/guard/repeat-tool-reminder/package.json index e8fcc60605..64a40e0cc3 100644 --- a/packages/guard/repeat-tool-reminder/package.json +++ b/packages/guard/repeat-tool-reminder/package.json @@ -27,12 +27,12 @@ ], "license": "MIT", "dependencies": { - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "peerDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -41,7 +41,7 @@ "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-session-projection": "workspace:^" } } diff --git a/packages/guard/timeout-policy/package.json b/packages/guard/timeout-policy/package.json index b7f22c3002..96481352d5 100644 --- a/packages/guard/timeout-policy/package.json +++ b/packages/guard/timeout-policy/package.json @@ -30,12 +30,12 @@ "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-timeout": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-timeout": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/hooks/hook-protocol/package.json b/packages/hooks/hook-protocol/package.json index a2400f2893..ada42c6619 100644 --- a/packages/hooks/hook-protocol/package.json +++ b/packages/hooks/hook-protocol/package.json @@ -35,12 +35,12 @@ "@deepseek-ai/dsh-shell": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-shell": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/hooks/hooks-claude-code/package.json b/packages/hooks/hooks-claude-code/package.json index 1db3521903..68057a5d2e 100644 --- a/packages/hooks/hooks-claude-code/package.json +++ b/packages/hooks/hooks-claude-code/package.json @@ -27,7 +27,7 @@ ], "license": "MIT", "dependencies": { - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "peerDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -36,7 +36,7 @@ "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-subagent": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-session-projection": "workspace:^" }, "devDependencies": { @@ -52,7 +52,7 @@ "@deepseek-ai/dsh-session-persistence-jsonl": "workspace:^", "@deepseek-ai/dsh-subagent": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-session-projection": "workspace:^" } } diff --git a/packages/hooks/hooks-codex/package.json b/packages/hooks/hooks-codex/package.json index 3ed5db1650..39ec414cc7 100644 --- a/packages/hooks/hooks-codex/package.json +++ b/packages/hooks/hooks-codex/package.json @@ -27,7 +27,7 @@ ], "license": "MIT", "dependencies": { - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "peerDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -35,7 +35,7 @@ "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-session-projection": "workspace:^" }, "devDependencies": { @@ -50,7 +50,7 @@ "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-session-persistence-jsonl": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-session-projection": "workspace:^" } } diff --git a/packages/host/directory-picker-auto/package.json b/packages/host/directory-picker-auto/package.json index fc35b3d067..8be34c1710 100644 --- a/packages/host/directory-picker-auto/package.json +++ b/packages/host/directory-picker-auto/package.json @@ -27,8 +27,8 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", + "@deepseek-ai/cordis-plugin-loader": "workspace:*", "@deepseek-ai/dsh-client-ui-directory-picker-browse": "workspace:^", "@deepseek-ai/dsh-client-ui-directory-picker-native": "workspace:^", "@deepseek-ai/dsh-host-directory-picker-browse": "workspace:^", @@ -36,9 +36,9 @@ "@deepseek-ai/dsh-host-webserver": "workspace:^" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", - "@deepseek-ai/cordis-plugin-include": "workspace:^", - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", + "@deepseek-ai/cordis-plugin-include": "workspace:*", + "@deepseek-ai/cordis-plugin-loader": "workspace:*", "@deepseek-ai/dsh-client-ui-directory-picker-browse": "workspace:^", "@deepseek-ai/dsh-client-ui-directory-picker-native": "workspace:^", "@deepseek-ai/dsh-host-directory-picker": "workspace:^", diff --git a/packages/host/directory-picker-browse/package.json b/packages/host/directory-picker-browse/package.json index 850081c48a..6f70fe7462 100644 --- a/packages/host/directory-picker-browse/package.json +++ b/packages/host/directory-picker-browse/package.json @@ -28,12 +28,12 @@ "license": "MIT", "dependencies": { "@deepseek-ai/dsh-host-directory-picker": "workspace:^", - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/host/directory-picker-native/package.json b/packages/host/directory-picker-native/package.json index 36d4c902da..66c1532a9b 100644 --- a/packages/host/directory-picker-native/package.json +++ b/packages/host/directory-picker-native/package.json @@ -37,10 +37,10 @@ "koffi": "^3.1.0" }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "tsx": "^4.19.2" } } diff --git a/packages/host/directory-picker/package.json b/packages/host/directory-picker/package.json index a930512ac0..78511ee411 100644 --- a/packages/host/directory-picker/package.json +++ b/packages/host/directory-picker/package.json @@ -32,9 +32,9 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/host/frontend-static/package.json b/packages/host/frontend-static/package.json index 3caae0efac..5b4a21dc44 100644 --- a/packages/host/frontend-static/package.json +++ b/packages/host/frontend-static/package.json @@ -29,16 +29,16 @@ "peerDependencies": { "@deepseek-ai/dsh-host-webserver": "workspace:^", "@deepseek-ai/dsh-client-connection": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "dependencies": { - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis-plugin-loader": "workspace:*", "@deepseek-ai/dsh-client-connection": "workspace:^", "@deepseek-ai/dsh-credentials-local": "workspace:^", "@deepseek-ai/dsh-host-webserver": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/host/open-in-app/package.json b/packages/host/open-in-app/package.json index 9c070ef429..0219a7cb65 100644 --- a/packages/host/open-in-app/package.json +++ b/packages/host/open-in-app/package.json @@ -39,14 +39,14 @@ "@deepseek-ai/dsh-launch-environment": "workspace:^", "@deepseek-ai/dsh-native-command": "workspace:^", "@deepseek-ai/dsh-subprocess": "workspace:^", - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", + "@deepseek-ai/cordis-plugin-loader": "workspace:*", "@deepseek-ai/dsh-host-webserver": "workspace:^" } } diff --git a/packages/host/plugin-inventory/package.json b/packages/host/plugin-inventory/package.json index 616032b4ee..fb8aeed845 100644 --- a/packages/host/plugin-inventory/package.json +++ b/packages/host/plugin-inventory/package.json @@ -47,11 +47,11 @@ "zod": "^4.4.3" }, "peerDependencies": { - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis-plugin-loader": "workspace:*", "@deepseek-ai/dsh-agent-presets": "workspace:^", "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-typert-protocol": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "peerDependenciesMeta": { "@deepseek-ai/dsh-agent-presets": { @@ -59,10 +59,10 @@ } }, "devDependencies": { - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis-plugin-loader": "workspace:*", "@deepseek-ai/dsh-agent-presets": "workspace:^", "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-typert-protocol": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/host/webserver/package.json b/packages/host/webserver/package.json index 8fbede6744..ce0ea4e673 100644 --- a/packages/host/webserver/package.json +++ b/packages/host/webserver/package.json @@ -27,15 +27,15 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "dependencies": { - "@deepseek-ai/schemastery": "workspace:^", + "@deepseek-ai/schemastery": "workspace:*", "compression": "^1.8.1", "negotiator": "^1.0.0" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@types/compression": "^1.8.1", "@types/negotiator": "^0.6.5" } diff --git a/packages/identity/anonymous-user-id/package.json b/packages/identity/anonymous-user-id/package.json index 53d9671751..33dcaef9ee 100644 --- a/packages/identity/anonymous-user-id/package.json +++ b/packages/identity/anonymous-user-id/package.json @@ -29,11 +29,11 @@ "peerDependencies": { "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-home-paths": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-home-paths": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/interaction/commands/package.json b/packages/interaction/commands/package.json index 0be908a553..98f9010fe8 100644 --- a/packages/interaction/commands/package.json +++ b/packages/interaction/commands/package.json @@ -61,7 +61,7 @@ "@deepseek-ai/dsh-scope": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-typert-protocol": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "dependencies": { "@deepseek-ai/dsh-util-crypto": "workspace:^", @@ -76,6 +76,6 @@ "@deepseek-ai/dsh-scope": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-typert-protocol": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/interaction/permission-presets/package.json b/packages/interaction/permission-presets/package.json index ebba3f0f18..ad1646d1fb 100644 --- a/packages/interaction/permission-presets/package.json +++ b/packages/interaction/permission-presets/package.json @@ -50,10 +50,10 @@ "@deepseek-ai/dsh-session-projection": "workspace:^", "@deepseek-ai/dsh-settings": "workspace:^", "@deepseek-ai/dsh-user-approval": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "dependencies": { - "@deepseek-ai/schemastery": "workspace:^", + "@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": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/interaction/tool-ask-user/package.json b/packages/interaction/tool-ask-user/package.json index 03efa1b837..bd82bab404 100644 --- a/packages/interaction/tool-ask-user/package.json +++ b/packages/interaction/tool-ask-user/package.json @@ -30,7 +30,7 @@ "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", "@deepseek-ai/dsh-user-questions": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -38,6 +38,6 @@ "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", "@deepseek-ai/dsh-user-questions": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/interaction/user-approval/package.json b/packages/interaction/user-approval/package.json index 6e8354834c..64a7a2be77 100644 --- a/packages/interaction/user-approval/package.json +++ b/packages/interaction/user-approval/package.json @@ -44,10 +44,10 @@ "@deepseek-ai/dsh-scope": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-system-prompt": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "dependencies": { - "@deepseek-ai/schemastery": "workspace:^" + "@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": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/interaction/user-questions/package.json b/packages/interaction/user-questions/package.json index cbe8a2854b..b2a1bf8aea 100644 --- a/packages/interaction/user-questions/package.json +++ b/packages/interaction/user-questions/package.json @@ -35,12 +35,12 @@ "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-scope": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-scope": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/jobs/jobs-local/package.json b/packages/jobs/jobs-local/package.json index 110ba43f3e..e4d519dad8 100644 --- a/packages/jobs/jobs-local/package.json +++ b/packages/jobs/jobs-local/package.json @@ -31,14 +31,14 @@ "@deepseek-ai/dsh-scope": "workspace:^", "@deepseek-ai/dsh-jobs": "workspace:^", "@deepseek-ai/dsh-timeout": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "dependencies": { - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis-plugin-include": "workspace:^", - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis-plugin-include": "workspace:*", + "@deepseek-ai/cordis-plugin-loader": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-agent-loop-testkit": "workspace:^", "@deepseek-ai/dsh-brand": "workspace:^", @@ -46,6 +46,6 @@ "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-jobs": "workspace:^", "@deepseek-ai/dsh-timeout": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/jobs/jobs/package.json b/packages/jobs/jobs/package.json index ff310752ce..8da1246315 100644 --- a/packages/jobs/jobs/package.json +++ b/packages/jobs/jobs/package.json @@ -41,13 +41,13 @@ "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", - "@deepseek-ai/cordis": "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": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/jobs/tool-jobs/package.json b/packages/jobs/tool-jobs/package.json index 8c6adfb1c3..116531ef3b 100644 --- a/packages/jobs/tool-jobs/package.json +++ b/packages/jobs/tool-jobs/package.json @@ -27,7 +27,7 @@ ], "license": "MIT", "dependencies": { - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "peerDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -36,7 +36,7 @@ "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-jobs": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -47,6 +47,6 @@ "@deepseek-ai/dsh-jobs": "workspace:^", "@deepseek-ai/dsh-jobs-local": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/llm/deepseek-llm-api-extensions/package.json b/packages/llm/deepseek-llm-api-extensions/package.json index 88bb421385..362afd2c35 100644 --- a/packages/llm/deepseek-llm-api-extensions/package.json +++ b/packages/llm/deepseek-llm-api-extensions/package.json @@ -32,9 +32,9 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/llm/llm-deepseek/package.json b/packages/llm/llm-deepseek/package.json index 9db0a60fdc..d25c0f9429 100644 --- a/packages/llm/llm-deepseek/package.json +++ b/packages/llm/llm-deepseek/package.json @@ -27,7 +27,7 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-anonymous-user-id": "workspace:^", "@deepseek-ai/dsh-atomic-write": "workspace:^", "@deepseek-ai/dsh-attachment": "workspace:^", @@ -43,11 +43,11 @@ "dependencies": { "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-util-values": "workspace:^", - "@deepseek-ai/schemastery": "workspace:^", + "@deepseek-ai/schemastery": "workspace:*", "eventsource-parser": "^3.1.0" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-anonymous-user-id": "workspace:^", "@deepseek-ai/dsh-atomic-write": "workspace:^", diff --git a/packages/llm/llm-pi-ai/package.json b/packages/llm/llm-pi-ai/package.json index 6a10d5a6bb..291275e245 100644 --- a/packages/llm/llm-pi-ai/package.json +++ b/packages/llm/llm-pi-ai/package.json @@ -27,7 +27,7 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-attachment": "workspace:^", "@deepseek-ai/dsh-authorization": "workspace:^", "@deepseek-ai/dsh-credentials": "workspace:^", @@ -40,11 +40,11 @@ "dependencies": { "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-util-values": "workspace:^", - "@deepseek-ai/schemastery": "workspace:^", + "@deepseek-ai/schemastery": "workspace:*", "@earendil-works/pi-ai": "^0.85.1" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-attachment": "workspace:^", "@deepseek-ai/dsh-authorization": "workspace:^", "@deepseek-ai/dsh-credentials": "workspace:^", diff --git a/packages/llm/llm-retry/package.json b/packages/llm/llm-retry/package.json index f226562e4d..7e83c7f6a7 100644 --- a/packages/llm/llm-retry/package.json +++ b/packages/llm/llm-retry/package.json @@ -42,17 +42,17 @@ "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-timeout": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-session-projection": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "workspace:^", + "@deepseek-ai/schemastery": "workspace:*", "zod": "^4.4.3" }, "devDependencies": { "@deepseek-ai/dsh-brand": "workspace:^", - "@deepseek-ai/cordis-plugin-include": "workspace:^", - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@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:^", @@ -66,7 +66,7 @@ "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-timeout": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-session-projection": "workspace:^" } } diff --git a/packages/llm/llm/package.json b/packages/llm/llm/package.json index 570ac9af86..486e47ea0c 100644 --- a/packages/llm/llm/package.json +++ b/packages/llm/llm/package.json @@ -61,11 +61,11 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "dependencies": { "@deepseek-ai/dsh-util-crypto": "workspace:^", - "@deepseek-ai/schemastery": "workspace:^", + "@deepseek-ai/schemastery": "workspace:*", "zod": "^4.4.3", "@deepseek-ai/dsh-timeout": "workspace:^", "@deepseek-ai/dsh-brand": "workspace:^", @@ -75,6 +75,6 @@ "devDependencies": { "@deepseek-ai/dsh-attachment": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/llm/plugin-package-inventory-deepseek/package.json b/packages/llm/plugin-package-inventory-deepseek/package.json index f04bbc0539..469607d05e 100644 --- a/packages/llm/plugin-package-inventory-deepseek/package.json +++ b/packages/llm/plugin-package-inventory-deepseek/package.json @@ -33,11 +33,11 @@ "license": "MIT", "dependencies": { "@deepseek-ai/dsh-brand": "workspace:^", - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", + "@deepseek-ai/cordis-plugin-loader": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-agent-presets": "workspace:^", "@deepseek-ai/dsh-deepseek-llm-api-extensions": "workspace:^", @@ -49,9 +49,9 @@ } }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", - "@deepseek-ai/cordis-plugin-include": "workspace:^", - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", + "@deepseek-ai/cordis-plugin-include": "workspace:*", + "@deepseek-ai/cordis-plugin-loader": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-agent-presets": "workspace:^", "@deepseek-ai/dsh-deepseek-llm-api-extensions": "workspace:^", diff --git a/packages/llm/token-meter/package.json b/packages/llm/token-meter/package.json index 44223f3a96..e97a24ffec 100644 --- a/packages/llm/token-meter/package.json +++ b/packages/llm/token-meter/package.json @@ -32,7 +32,7 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-compaction": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-llm-retry": "workspace:^", @@ -41,11 +41,11 @@ }, "dependencies": { "@deepseek-ai/dsh-util-values": "workspace:^", - "@deepseek-ai/schemastery": "workspace:^", + "@deepseek-ai/schemastery": "workspace:*", "zod": "^4.4.3" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-compaction": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-llm-retry": "workspace:^", diff --git a/packages/lsp/lsp-stdio/package.json b/packages/lsp/lsp-stdio/package.json index 6428068eb0..d0cacbce8e 100644 --- a/packages/lsp/lsp-stdio/package.json +++ b/packages/lsp/lsp-stdio/package.json @@ -27,7 +27,7 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-fs": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", @@ -37,10 +37,10 @@ }, "dependencies": { "@deepseek-ai/dsh-util-values": "workspace:^", - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-fs": "workspace:^", "@deepseek-ai/dsh-fs-local": "workspace:^", diff --git a/packages/lsp/lsp/package.json b/packages/lsp/lsp/package.json index 4d8df70f5a..dad6904fde 100644 --- a/packages/lsp/lsp/package.json +++ b/packages/lsp/lsp/package.json @@ -29,11 +29,11 @@ "peerDependencies": { "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/lsp/tool-lsp/package.json b/packages/lsp/tool-lsp/package.json index f4df13c8a1..a38ba7f575 100644 --- a/packages/lsp/tool-lsp/package.json +++ b/packages/lsp/tool-lsp/package.json @@ -27,7 +27,7 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-lsp": "workspace:^", "@deepseek-ai/dsh-system-prompt": "workspace:^", @@ -36,10 +36,10 @@ }, "dependencies": { "@deepseek-ai/dsh-util-values": "workspace:^", - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-fs-local": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", diff --git a/packages/mcp/mcp-client/package.json b/packages/mcp/mcp-client/package.json index d5573b3f94..8ec0b808e9 100644 --- a/packages/mcp/mcp-client/package.json +++ b/packages/mcp/mcp-client/package.json @@ -33,11 +33,11 @@ "@deepseek-ai/dsh-subprocess": "workspace:^", "@deepseek-ai/dsh-timeout": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "dependencies": { "@modelcontextprotocol/sdk": "^1.12.0", - "@deepseek-ai/schemastery": "workspace:^", + "@deepseek-ai/schemastery": "workspace:*", "zod": "^4.4.3" }, "devDependencies": { @@ -50,7 +50,7 @@ "@deepseek-ai/dsh-tools": "workspace:^", "@modelcontextprotocol/server-everything": "^2026.7.4", "@modelcontextprotocol/server-filesystem": "^2026.7.4", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-http-proxy": "workspace:^" } } diff --git a/packages/plan/plan-mode/package.json b/packages/plan/plan-mode/package.json index 7d5898dacd..77c8258cfb 100644 --- a/packages/plan/plan-mode/package.json +++ b/packages/plan/plan-mode/package.json @@ -50,7 +50,7 @@ "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", "@deepseek-ai/dsh-user-questions": "workspace:^", - "@deepseek-ai/cordis": "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-questions": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/preset/agent-presets/package.json b/packages/preset/agent-presets/package.json index 61a2ad9f75..198e9cb3ad 100644 --- a/packages/preset/agent-presets/package.json +++ b/packages/preset/agent-presets/package.json @@ -54,8 +54,8 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis-plugin-include": "workspace:^", - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis-plugin-include": "workspace:*", + "@deepseek-ai/cordis-plugin-loader": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-atomic-write": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", @@ -67,17 +67,17 @@ "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", "@deepseek-ai/dsh-typert-protocol": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "dependencies": { "js-yaml": "^4.1.0", - "@deepseek-ai/schemastery": "workspace:^", + "@deepseek-ai/schemastery": "workspace:*", "zod": "^4.4.3" }, "devDependencies": { - "@deepseek-ai/cordis-plugin-group": "workspace:^", - "@deepseek-ai/cordis-plugin-include": "workspace:^", - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis-plugin-group": "workspace:*", + "@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-atomic-write": "workspace:^", @@ -92,6 +92,6 @@ "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", "@deepseek-ai/dsh-typert-protocol": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/preset/persona/package.json b/packages/preset/persona/package.json index ec116bd3dd..abb1f1d95f 100644 --- a/packages/preset/persona/package.json +++ b/packages/preset/persona/package.json @@ -28,14 +28,14 @@ "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-system-prompt": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "dependencies": { - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-scope": "workspace:^", "@deepseek-ai/dsh-system-prompt": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/runtime-diagnostics/invariants/package.json b/packages/runtime-diagnostics/invariants/package.json index 2d10a8814f..2a58624dd3 100644 --- a/packages/runtime-diagnostics/invariants/package.json +++ b/packages/runtime-diagnostics/invariants/package.json @@ -27,12 +27,12 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "dependencies": { - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/sandbox/sandbox-local/package.json b/packages/sandbox/sandbox-local/package.json index 76bf039d88..1e81d1c41e 100644 --- a/packages/sandbox/sandbox-local/package.json +++ b/packages/sandbox/sandbox-local/package.json @@ -27,7 +27,7 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-sandbox": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^" @@ -36,10 +36,10 @@ "@deepseek-ai/dsh-sandbox-windows-acl": "workspace:^", "@deepseek-ai/dsh-util-values": "workspace:^", "@deepseek-ai/node-addon-system": "workspace:^", - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-sandbox": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^" diff --git a/packages/sandbox/sandbox-policy/package.json b/packages/sandbox/sandbox-policy/package.json index 686d4266ba..88956c44aa 100644 --- a/packages/sandbox/sandbox-policy/package.json +++ b/packages/sandbox/sandbox-policy/package.json @@ -37,11 +37,11 @@ "@deepseek-ai/dsh-sandbox": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-system-prompt": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-session-projection": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "workspace:^", + "@deepseek-ai/schemastery": "workspace:*", "zod": "^4.4.3" }, "devDependencies": { @@ -50,7 +50,7 @@ "@deepseek-ai/dsh-sandbox": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-system-prompt": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-session-projection": "workspace:^" } } diff --git a/packages/sandbox/sandbox-windows-acl/package.json b/packages/sandbox/sandbox-windows-acl/package.json index b5f376607c..237fdf6c5e 100644 --- a/packages/sandbox/sandbox-windows-acl/package.json +++ b/packages/sandbox/sandbox-windows-acl/package.json @@ -33,7 +33,7 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "dependencies": { "@deepseek-ai/dsh-win32-process": "workspace:^", @@ -42,6 +42,6 @@ "devDependencies": { "@deepseek-ai/dsh-pwsh-local": "workspace:^", "@deepseek-ai/dsh-sandbox-local": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/sandbox/sandbox/package.json b/packages/sandbox/sandbox/package.json index 05e539d567..db96b4b4dd 100644 --- a/packages/sandbox/sandbox/package.json +++ b/packages/sandbox/sandbox/package.json @@ -27,12 +27,12 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^" }, diff --git a/packages/schedule/schedule/package.json b/packages/schedule/schedule/package.json index eb43fbbed4..9bb951f2c2 100644 --- a/packages/schedule/schedule/package.json +++ b/packages/schedule/schedule/package.json @@ -45,13 +45,13 @@ "@deepseek-ai/dsh-session-persistence": "workspace:^", "@deepseek-ai/dsh-session-projection": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "dependencies": { "zod": "^4.4.3" }, "devDependencies": { - "@deepseek-ai/cordis-plugin-loader": "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:^", @@ -64,6 +64,6 @@ "@deepseek-ai/dsh-session-projection": "workspace:^", "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/sdk/client/package.json b/packages/sdk/client/package.json index 272fbab849..b2f0a53b0a 100644 --- a/packages/sdk/client/package.json +++ b/packages/sdk/client/package.json @@ -32,12 +32,12 @@ "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-sdk-protocol": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-sdk-protocol": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/sdk/protocol/package.json b/packages/sdk/protocol/package.json index e65cf001d0..5d886f8917 100644 --- a/packages/sdk/protocol/package.json +++ b/packages/sdk/protocol/package.json @@ -29,12 +29,12 @@ "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-subagent": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-subagent": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/sdk/server/package.json b/packages/sdk/server/package.json index 56d1e7cad5..f2a67d92eb 100644 --- a/packages/sdk/server/package.json +++ b/packages/sdk/server/package.json @@ -28,10 +28,10 @@ "license": "MIT", "dependencies": { "@deepseek-ai/dsh-brand": "workspace:^", - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-attachment": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", @@ -42,8 +42,8 @@ "@deepseek-ai/dsh-subagent": "workspace:^" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis": "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:^", diff --git a/packages/session-query/session-log-export/package.json b/packages/session-query/session-log-export/package.json index f63702c964..df74a200f6 100644 --- a/packages/session-query/session-log-export/package.json +++ b/packages/session-query/session-log-export/package.json @@ -37,18 +37,18 @@ "license": "MIT", "dependencies": { "@deepseek-ai/dsh-session-format": "workspace:^", - "@deepseek-ai/schemastery": "workspace:^", + "@deepseek-ai/schemastery": "workspace:*", "fflate": "^0.8.2", "@deepseek-ai/dsh-brand": "workspace:^" }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-session-persistence": "workspace:^" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", + "@deepseek-ai/cordis-plugin-loader": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-attachment": "workspace:^", "@deepseek-ai/dsh-client-connection": "workspace:^", diff --git a/packages/session-query/session-query-sqlite/package.json b/packages/session-query/session-query-sqlite/package.json index ed79f3840e..6c002b89b1 100644 --- a/packages/session-query/session-query-sqlite/package.json +++ b/packages/session-query/session-query-sqlite/package.json @@ -30,7 +30,7 @@ "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-session-persistence": "workspace:^", "@deepseek-ai/dsh-session-query": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "peerDependenciesMeta": { "@deepseek-ai/dsh-session-persistence": { @@ -38,15 +38,15 @@ } }, "dependencies": { - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis-plugin-loader": "workspace:*", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-session-persistence": "workspace:^", "@deepseek-ai/dsh-session-persistence-jsonl": "workspace:^", "@deepseek-ai/dsh-session-query": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-session-projection": "workspace:^" } } diff --git a/packages/session-query/session-query/package.json b/packages/session-query/session-query/package.json index e383b1b413..209d8d3ae6 100644 --- a/packages/session-query/session-query/package.json +++ b/packages/session-query/session-query/package.json @@ -35,7 +35,7 @@ "@deepseek-ai/dsh-session-persistence": "workspace:^", "@deepseek-ai/dsh-session-projection": "workspace:^", "@deepseek-ai/dsh-session-projection-cache": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "peerDependenciesMeta": { "@deepseek-ai/dsh-session-persistence": { @@ -57,6 +57,6 @@ "@deepseek-ai/dsh-session-persistence": "workspace:^", "@deepseek-ai/dsh-session-projection": "workspace:^", "@deepseek-ai/dsh-session-projection-cache": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@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 1ad9a77b5c..459a310a4f 100644 --- a/packages/session-query/tool-session-query/package.json +++ b/packages/session-query/tool-session-query/package.json @@ -27,7 +27,7 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", @@ -39,10 +39,10 @@ }, "dependencies": { "@deepseek-ai/dsh-brand": "workspace:^", - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-agent-loop": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", diff --git a/packages/session/session-checkpoint-policy/package.json b/packages/session/session-checkpoint-policy/package.json index a817b06e4e..ea8f06bd48 100644 --- a/packages/session/session-checkpoint-policy/package.json +++ b/packages/session/session-checkpoint-policy/package.json @@ -27,7 +27,7 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", @@ -35,8 +35,8 @@ "@deepseek-ai/dsh-tools": "workspace:^" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis": "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:^", diff --git a/packages/session/session-format-catalog/package.json b/packages/session/session-format-catalog/package.json index f3ea35a6c8..35c64ad7c9 100644 --- a/packages/session/session-format-catalog/package.json +++ b/packages/session/session-format-catalog/package.json @@ -33,11 +33,11 @@ "@deepseek-ai/dsh-session-format-v2-to-v3": "workspace:^" }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-session": "workspace:^" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-session": "workspace:^" } } diff --git a/packages/session/session-format-v0-to-v1/package.json b/packages/session/session-format-v0-to-v1/package.json index ca5d77d640..237b0353ca 100644 --- a/packages/session/session-format-v0-to-v1/package.json +++ b/packages/session/session-format-v0-to-v1/package.json @@ -43,10 +43,10 @@ "@deepseek-ai/dsh-util-values": "workspace:^" }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-session": "workspace:^" } } diff --git a/packages/session/session-format-v1-to-v2/package.json b/packages/session/session-format-v1-to-v2/package.json index a44eef9856..7eff82299f 100644 --- a/packages/session/session-format-v1-to-v2/package.json +++ b/packages/session/session-format-v1-to-v2/package.json @@ -45,10 +45,10 @@ "@deepseek-ai/dsh-util-values": "workspace:^" }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-session": "workspace:^" } } diff --git a/packages/session/session-format-v2-to-v3/package.json b/packages/session/session-format-v2-to-v3/package.json index 637cd4f0fe..e893b3afa9 100644 --- a/packages/session/session-format-v2-to-v3/package.json +++ b/packages/session/session-format-v2-to-v3/package.json @@ -44,9 +44,9 @@ "@deepseek-ai/dsh-session-format-v1-to-v2": "workspace:^" }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/session/session-format/package.json b/packages/session/session-format/package.json index 4eaefdbea2..d76b1d576e 100644 --- a/packages/session/session-format/package.json +++ b/packages/session/session-format/package.json @@ -30,9 +30,9 @@ "@deepseek-ai/dsh-util-values": "workspace:^" }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/session/session-log-deepseek/package.json b/packages/session/session-log-deepseek/package.json index 4cbdc9e4f1..94050124cc 100644 --- a/packages/session/session-log-deepseek/package.json +++ b/packages/session/session-log-deepseek/package.json @@ -39,18 +39,18 @@ "dependencies": { "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-util-values": "workspace:^", - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-deepseek-llm-api-extensions": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", - "@deepseek-ai/cordis-plugin-include": "workspace:^", - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", + "@deepseek-ai/cordis-plugin-include": "workspace:*", + "@deepseek-ai/cordis-plugin-loader": "workspace:*", "@deepseek-ai/dsh-command-feedback": "workspace:^", "@deepseek-ai/dsh-deepseek-llm-api-extensions": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/session/session-persistence-jsonl/package.json b/packages/session/session-persistence-jsonl/package.json index 2756ed8ebd..80df4e2342 100644 --- a/packages/session/session-persistence-jsonl/package.json +++ b/packages/session/session-persistence-jsonl/package.json @@ -30,7 +30,7 @@ "peerDependencies": { "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-session-persistence": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "dependencies": { "@deepseek-ai/dsh-llm": "workspace:^", @@ -39,12 +39,12 @@ "@deepseek-ai/dsh-session-format-v2-to-v3": "workspace:^", "@deepseek-ai/node-addon-system": "workspace:^", "koffi": "^3.1.0", - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-session-format-v0-to-v1": "workspace:^", "@deepseek-ai/dsh-session-persistence": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/session/session-persistence/package.json b/packages/session/session-persistence/package.json index 1562f0f190..7140efbce9 100644 --- a/packages/session/session-persistence/package.json +++ b/packages/session/session-persistence/package.json @@ -27,13 +27,13 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-timeout": "workspace:^" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-scope": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", diff --git a/packages/session/session-projection-cache/package.json b/packages/session/session-projection-cache/package.json index bd1672e91a..8bad923651 100644 --- a/packages/session/session-projection-cache/package.json +++ b/packages/session/session-projection-cache/package.json @@ -28,17 +28,17 @@ "license": "MIT", "dependencies": { "@deepseek-ai/dsh-util-values": "workspace:^", - "@deepseek-ai/schemastery": "workspace:^", + "@deepseek-ai/schemastery": "workspace:*", "zod": "^4.4.3" }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-session-projection": "workspace:^", "@deepseek-ai/dsh-storage-domain": "workspace:^" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-session-projection": "workspace:^", "@deepseek-ai/dsh-storage": "workspace:^", diff --git a/packages/session/session-projection/package.json b/packages/session/session-projection/package.json index 6f426ab889..358aa65c23 100644 --- a/packages/session/session-projection/package.json +++ b/packages/session/session-projection/package.json @@ -36,10 +36,10 @@ }, "peerDependencies": { "@deepseek-ai/dsh-session": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-session": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/session/session-stats/package.json b/packages/session/session-stats/package.json index c62eb3b449..1f0561d70c 100644 --- a/packages/session/session-stats/package.json +++ b/packages/session/session-stats/package.json @@ -39,17 +39,17 @@ "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-session-projection": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "dependencies": { "zod": "^4.4.3" }, "devDependencies": { - "@deepseek-ai/cordis-plugin-include": "workspace:^", - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis-plugin-include": "workspace:*", + "@deepseek-ai/cordis-plugin-loader": "workspace:*", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-session-projection": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/session/session-telemetry-otel/package.json b/packages/session/session-telemetry-otel/package.json index 2da6d75acb..b3f1361173 100644 --- a/packages/session/session-telemetry-otel/package.json +++ b/packages/session/session-telemetry-otel/package.json @@ -33,7 +33,7 @@ "@opentelemetry/otlp-exporter-base": "^0.220.0", "@opentelemetry/resources": "^2.9.0", "@opentelemetry/sdk-logs": "^0.220.0", - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "peerDependencies": { "@deepseek-ai/dsh-command-feedback": "workspace:^", @@ -42,11 +42,11 @@ "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-session-telemetry": "workspace:^", "@deepseek-ai/dsh-anonymous-user-id": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis-plugin-logger-console": "workspace:^", - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis-plugin-logger-console": "workspace:*", + "@deepseek-ai/cordis-plugin-loader": "workspace:*", "@deepseek-ai/dsh-app-boot": "workspace:^", "@deepseek-ai/dsh-bash-local": "workspace:^", "@deepseek-ai/dsh-command-feedback": "workspace:^", @@ -59,7 +59,7 @@ "@deepseek-ai/dsh-session-telemetry": "workspace:^", "@deepseek-ai/dsh-subprocess-local": "workspace:^", "@deepseek-ai/dsh-anonymous-user-id": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-http-proxy": "workspace:^" } } diff --git a/packages/session/session-telemetry/package.json b/packages/session/session-telemetry/package.json index 1278879299..de05df1d90 100644 --- a/packages/session/session-telemetry/package.json +++ b/packages/session/session-telemetry/package.json @@ -29,11 +29,11 @@ "peerDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/session/session-title-all-prompts-llm/package.json b/packages/session/session-title-all-prompts-llm/package.json index 4ceac7914e..90417298b3 100644 --- a/packages/session/session-title-all-prompts-llm/package.json +++ b/packages/session/session-title-all-prompts-llm/package.json @@ -27,17 +27,17 @@ "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-session-title": "workspace:^", "@deepseek-ai/dsh-session-title-llm": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "dependencies": { - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "devDependencies": { "@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:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-session-projection": "workspace:^", "@deepseek-ai/dsh-agent-loop": "workspace:^" } diff --git a/packages/session/session-title-first-prompt-llm/package.json b/packages/session/session-title-first-prompt-llm/package.json index e88246e9e6..77e29c11af 100644 --- a/packages/session/session-title-first-prompt-llm/package.json +++ b/packages/session/session-title-first-prompt-llm/package.json @@ -27,20 +27,20 @@ "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-session-title": "workspace:^", "@deepseek-ai/dsh-session-title-llm": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "dependencies": { - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis-plugin-include": "workspace:^", - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis-plugin-include": "workspace:*", + "@deepseek-ai/cordis-plugin-loader": "workspace:*", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-llm-deepseek": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-session-title": "workspace:^", "@deepseek-ai/dsh-session-title-llm": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-session-projection": "workspace:^", "@deepseek-ai/dsh-agent-loop": "workspace:^" } diff --git a/packages/session/session-title-llm/package.json b/packages/session/session-title-llm/package.json index b7eef1d212..7dc081293d 100644 --- a/packages/session/session-title-llm/package.json +++ b/packages/session/session-title-llm/package.json @@ -27,7 +27,7 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-session-title": "workspace:^", @@ -35,10 +35,10 @@ }, "dependencies": { "@deepseek-ai/dsh-util-values": "workspace:^", - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-session-title": "workspace:^", diff --git a/packages/session/session-title/package.json b/packages/session/session-title/package.json index a7e9894f61..2cc7a6a604 100644 --- a/packages/session/session-title/package.json +++ b/packages/session/session-title/package.json @@ -41,7 +41,7 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", @@ -51,11 +51,11 @@ }, "dependencies": { "@deepseek-ai/dsh-util-values": "workspace:^", - "@deepseek-ai/schemastery": "workspace:^", + "@deepseek-ai/schemastery": "workspace:*", "zod": "^4.4.3" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-agent-loop": "workspace:^", "@deepseek-ai/dsh-brand": "workspace:^", diff --git a/packages/session/session-turn-outline/package.json b/packages/session/session-turn-outline/package.json index 14153bed1f..1ea6e8cc81 100644 --- a/packages/session/session-turn-outline/package.json +++ b/packages/session/session-turn-outline/package.json @@ -36,7 +36,7 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-session-projection": "workspace:^" @@ -45,9 +45,9 @@ "zod": "^4.4.3" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", - "@deepseek-ai/cordis-plugin-include": "workspace:^", - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", + "@deepseek-ai/cordis-plugin-include": "workspace:*", + "@deepseek-ai/cordis-plugin-loader": "workspace:*", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-session-projection": "workspace:^" diff --git a/packages/settings/settings-file/package.json b/packages/settings/settings-file/package.json index 6ab3a5b2b0..663c9682db 100644 --- a/packages/settings/settings-file/package.json +++ b/packages/settings/settings-file/package.json @@ -27,19 +27,19 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-atomic-write": "workspace:^", "@deepseek-ai/dsh-home-paths": "workspace:^", "@deepseek-ai/dsh-settings": "workspace:^" }, "dependencies": { "@deepseek-ai/dsh-util-values": "workspace:^", - "@deepseek-ai/schemastery": "workspace:^", + "@deepseek-ai/schemastery": "workspace:*", "chokidar": "^4.0.3", "yaml": "^2.9.0" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-atomic-write": "workspace:^", "@deepseek-ai/dsh-home-paths": "workspace:^", "@deepseek-ai/dsh-settings": "workspace:^" diff --git a/packages/settings/settings/package.json b/packages/settings/settings/package.json index 65a086cf07..9151e92d0b 100644 --- a/packages/settings/settings/package.json +++ b/packages/settings/settings/package.json @@ -37,18 +37,18 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "dependencies": { "@deepseek-ai/dsh-util-values": "workspace:^" diff --git a/packages/shell/bash-local/package.json b/packages/shell/bash-local/package.json index b5ce1e5135..87ba3b08e0 100644 --- a/packages/shell/bash-local/package.json +++ b/packages/shell/bash-local/package.json @@ -30,18 +30,18 @@ "@deepseek-ai/dsh-shell": "workspace:^", "@deepseek-ai/dsh-subprocess": "workspace:^", "@deepseek-ai/dsh-timeout": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-settings": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-shell": "workspace:^", "@deepseek-ai/dsh-subprocess": "workspace:^", "@deepseek-ai/dsh-subprocess-local": "workspace:^", "@deepseek-ai/dsh-timeout": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-settings": "workspace:^" } } diff --git a/packages/shell/bash-sandbox/package.json b/packages/shell/bash-sandbox/package.json index bfe649350b..7b0c17a2e4 100644 --- a/packages/shell/bash-sandbox/package.json +++ b/packages/shell/bash-sandbox/package.json @@ -31,7 +31,7 @@ "@deepseek-ai/dsh-bash-local": "workspace:^", "@deepseek-ai/dsh-sandbox": "workspace:^", "@deepseek-ai/dsh-sandbox-policy": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-shell": "workspace:^", @@ -40,7 +40,7 @@ "@deepseek-ai/dsh-sandbox": "workspace:^", "@deepseek-ai/dsh-sandbox-local": "workspace:^", "@deepseek-ai/dsh-sandbox-policy": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/node-addon-system": "workspace:^", "@deepseek-ai/dsh-session-projection": "workspace:^" } diff --git a/packages/shell/pwsh-local/package.json b/packages/shell/pwsh-local/package.json index 6925fc8509..7254df4d80 100644 --- a/packages/shell/pwsh-local/package.json +++ b/packages/shell/pwsh-local/package.json @@ -30,18 +30,18 @@ "@deepseek-ai/dsh-shell": "workspace:^", "@deepseek-ai/dsh-subprocess": "workspace:^", "@deepseek-ai/dsh-timeout": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-settings": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-shell": "workspace:^", "@deepseek-ai/dsh-subprocess": "workspace:^", "@deepseek-ai/dsh-subprocess-local": "workspace:^", "@deepseek-ai/dsh-timeout": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-settings": "workspace:^" } } diff --git a/packages/shell/pwsh-sandbox/package.json b/packages/shell/pwsh-sandbox/package.json index ad46833902..be6f6fe406 100644 --- a/packages/shell/pwsh-sandbox/package.json +++ b/packages/shell/pwsh-sandbox/package.json @@ -31,7 +31,7 @@ "@deepseek-ai/dsh-pwsh-local": "workspace:^", "@deepseek-ai/dsh-sandbox": "workspace:^", "@deepseek-ai/dsh-sandbox-policy": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-shell": "workspace:^", @@ -41,6 +41,6 @@ "@deepseek-ai/dsh-sandbox-policy": "workspace:^", "@deepseek-ai/dsh-session-projection": "workspace:^", "@deepseek-ai/dsh-subprocess-local": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/shell/shell-env/package.json b/packages/shell/shell-env/package.json index ddc0df2fd2..8956952748 100644 --- a/packages/shell/shell-env/package.json +++ b/packages/shell/shell-env/package.json @@ -30,10 +30,10 @@ "@deepseek-ai/dsh-shell": "workspace:^", "@deepseek-ai/dsh-home-paths": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "dependencies": { - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -41,6 +41,6 @@ "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-home-paths": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/shell/shell/package.json b/packages/shell/shell/package.json index 57a8573d6b..8821c3aeb8 100644 --- a/packages/shell/shell/package.json +++ b/packages/shell/shell/package.json @@ -29,13 +29,13 @@ "peerDependencies": { "@deepseek-ai/dsh-subprocess": "workspace:^", "@deepseek-ai/dsh-sandbox": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-settings": "workspace:^" }, "devDependencies": { "@deepseek-ai/dsh-subprocess": "workspace:^", "@deepseek-ai/dsh-sandbox": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-settings": "workspace:^" } } diff --git a/packages/shell/tool-bash-persistent/package.json b/packages/shell/tool-bash-persistent/package.json index 8551bd66d5..3e0a7a7a8c 100644 --- a/packages/shell/tool-bash-persistent/package.json +++ b/packages/shell/tool-bash-persistent/package.json @@ -30,14 +30,14 @@ "@deepseek-ai/dsh-terminal": "workspace:^", "@deepseek-ai/dsh-timeout": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "dependencies": { - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis-plugin-include": "workspace:^", - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis-plugin-include": "workspace:*", + "@deepseek-ai/cordis-plugin-loader": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-agent-loop-testkit": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", @@ -50,7 +50,7 @@ "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-timeout": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-session-projection": "workspace:^" } } diff --git a/packages/shell/tool-bash/package.json b/packages/shell/tool-bash/package.json index c6d4a937b1..d6308c9be3 100644 --- a/packages/shell/tool-bash/package.json +++ b/packages/shell/tool-bash/package.json @@ -37,10 +37,10 @@ "@deepseek-ai/dsh-jobs": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", "@deepseek-ai/dsh-user-approval": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "dependencies": { - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -61,7 +61,7 @@ "@deepseek-ai/dsh-tool-jobs": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", "@deepseek-ai/dsh-user-approval": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-session-projection": "workspace:^" } } diff --git a/packages/shell/tool-pwsh-persistent/package.json b/packages/shell/tool-pwsh-persistent/package.json index ae0d009f52..6b536ee67a 100644 --- a/packages/shell/tool-pwsh-persistent/package.json +++ b/packages/shell/tool-pwsh-persistent/package.json @@ -30,14 +30,14 @@ "@deepseek-ai/dsh-terminal": "workspace:^", "@deepseek-ai/dsh-timeout": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "dependencies": { - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis-plugin-include": "workspace:^", - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis-plugin-include": "workspace:*", + "@deepseek-ai/cordis-plugin-loader": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-agent-loop-testkit": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", @@ -52,6 +52,6 @@ "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-timeout": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/shell/tool-pwsh/package.json b/packages/shell/tool-pwsh/package.json index 30642f2ef5..455635d24d 100644 --- a/packages/shell/tool-pwsh/package.json +++ b/packages/shell/tool-pwsh/package.json @@ -27,7 +27,7 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-jobs": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", @@ -40,10 +40,10 @@ "@deepseek-ai/dsh-user-approval": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-agent-loop": "workspace:^", "@deepseek-ai/dsh-app-boot": "workspace:^", diff --git a/packages/skill/skill-badge/package.json b/packages/skill/skill-badge/package.json index dc0d6728e2..4965ecb35d 100644 --- a/packages/skill/skill-badge/package.json +++ b/packages/skill/skill-badge/package.json @@ -28,10 +28,10 @@ "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-skill": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-skill": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/skill/skill-filesystem/package.json b/packages/skill/skill-filesystem/package.json index afdb646aa6..12fc7ec3b2 100644 --- a/packages/skill/skill-filesystem/package.json +++ b/packages/skill/skill-filesystem/package.json @@ -30,17 +30,17 @@ "@deepseek-ai/dsh-fs": "workspace:^", "@deepseek-ai/dsh-home-paths": "workspace:^", "@deepseek-ai/dsh-skill": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "dependencies": { "chokidar": "^5.0.0", - "@deepseek-ai/schemastery": "workspace:^", + "@deepseek-ai/schemastery": "workspace:*", "yaml": "^2.4.2" }, "devDependencies": { "@deepseek-ai/dsh-fs": "workspace:^", "@deepseek-ai/dsh-home-paths": "workspace:^", "@deepseek-ai/dsh-skill": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/skill/skill/package.json b/packages/skill/skill/package.json index 01be87e133..d55f3a1897 100644 --- a/packages/skill/skill/package.json +++ b/packages/skill/skill/package.json @@ -27,16 +27,16 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-scope": "workspace:^" }, "dependencies": { "@deepseek-ai/dsh-util-values": "workspace:^", - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-scope": "workspace:^" } diff --git a/packages/skill/tool-skill/package.json b/packages/skill/tool-skill/package.json index a12fcde6eb..b79118fbd9 100644 --- a/packages/skill/tool-skill/package.json +++ b/packages/skill/tool-skill/package.json @@ -31,10 +31,10 @@ "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-skill": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "dependencies": { - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -45,6 +45,6 @@ "@deepseek-ai/dsh-skill": "workspace:^", "@deepseek-ai/dsh-skill-filesystem": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/spill/spill-local/package.json b/packages/spill/spill-local/package.json index 510acaf6b1..36bfb9cf3a 100644 --- a/packages/spill/spill-local/package.json +++ b/packages/spill/spill-local/package.json @@ -28,18 +28,18 @@ "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-spill": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "dependencies": { - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis-plugin-include": "workspace:^", - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis-plugin-include": "workspace:*", + "@deepseek-ai/cordis-plugin-loader": "workspace:*", "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-spill": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/spill/spill-policy/package.json b/packages/spill/spill-policy/package.json index e6e1dee090..88e42b054f 100644 --- a/packages/spill/spill-policy/package.json +++ b/packages/spill/spill-policy/package.json @@ -37,10 +37,10 @@ "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-spill": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "dependencies": { - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -50,6 +50,6 @@ "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-spill": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/spill/spill/package.json b/packages/spill/spill/package.json index b4a3c32097..fe381277f8 100644 --- a/packages/spill/spill/package.json +++ b/packages/spill/spill/package.json @@ -30,12 +30,12 @@ "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/storage/storage-domain/package.json b/packages/storage/storage-domain/package.json index 8fe6912da9..3b322ea6dd 100644 --- a/packages/storage/storage-domain/package.json +++ b/packages/storage/storage-domain/package.json @@ -34,15 +34,15 @@ "peerDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-storage": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "dependencies": { - "@deepseek-ai/schemastery": "workspace:^", + "@deepseek-ai/schemastery": "workspace:*", "zod": "^4.4.3" }, "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-storage": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/storage/storage-json/package.json b/packages/storage/storage-json/package.json index 9d21ecfec2..bf363340b4 100644 --- a/packages/storage/storage-json/package.json +++ b/packages/storage/storage-json/package.json @@ -28,13 +28,13 @@ "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-storage": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "dependencies": { - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-storage": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/storage/storage-sqlite/package.json b/packages/storage/storage-sqlite/package.json index d8dfc56910..d04fad5ef1 100644 --- a/packages/storage/storage-sqlite/package.json +++ b/packages/storage/storage-sqlite/package.json @@ -28,13 +28,13 @@ "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-storage": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "dependencies": { - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-storage": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/storage/storage/package.json b/packages/storage/storage/package.json index a418159f5c..30d2555ac2 100644 --- a/packages/storage/storage/package.json +++ b/packages/storage/storage/package.json @@ -27,9 +27,9 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/subagent/subagent-acp/package.json b/packages/subagent/subagent-acp/package.json index 45e0f6c99c..db33332e03 100644 --- a/packages/subagent/subagent-acp/package.json +++ b/packages/subagent/subagent-acp/package.json @@ -27,7 +27,7 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", @@ -38,11 +38,11 @@ "dependencies": { "@agentclientprotocol/sdk": "1.4.0", "@deepseek-ai/dsh-brand": "workspace:^", - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", + "@deepseek-ai/cordis-plugin-loader": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-app-boot": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", diff --git a/packages/subagent/subagent-claude-code/package.json b/packages/subagent/subagent-claude-code/package.json index 19d90f5a92..569dcb1e47 100644 --- a/packages/subagent/subagent-claude-code/package.json +++ b/packages/subagent/subagent-claude-code/package.json @@ -33,7 +33,7 @@ } }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-subagent": "workspace:^", @@ -44,12 +44,12 @@ "@anthropic-ai/claude-agent-sdk": "0.3.263", "@anthropic-ai/sdk": "0.93.0", "@deepseek-ai/dsh-brand": "workspace:^", - "@deepseek-ai/schemastery": "workspace:^", + "@deepseek-ai/schemastery": "workspace:*", "@modelcontextprotocol/sdk": "^1.29.0", "zod": "^4.4.3" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-app-boot": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", diff --git a/packages/subagent/subagent-codex/package.json b/packages/subagent/subagent-codex/package.json index c434b0b52d..847743c103 100644 --- a/packages/subagent/subagent-codex/package.json +++ b/packages/subagent/subagent-codex/package.json @@ -33,7 +33,7 @@ } }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-subagent": "workspace:^", @@ -43,12 +43,12 @@ "dependencies": { "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-sdk-protocol": "workspace:^", - "@deepseek-ai/schemastery": "workspace:^", + "@deepseek-ai/schemastery": "workspace:*", "@openai/codex": "0.153.4" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", + "@deepseek-ai/cordis-plugin-loader": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-app-boot": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", diff --git a/packages/subagent/subagent-dsh-sdk/package.json b/packages/subagent/subagent-dsh-sdk/package.json index 1a378f53f2..2129650bf9 100644 --- a/packages/subagent/subagent-dsh-sdk/package.json +++ b/packages/subagent/subagent-dsh-sdk/package.json @@ -27,7 +27,7 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-sdk-client": "workspace:^", @@ -37,11 +37,11 @@ }, "dependencies": { "@deepseek-ai/dsh-brand": "workspace:^", - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", + "@deepseek-ai/cordis-plugin-loader": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-agent-instructions": "workspace:^", "@deepseek-ai/dsh-app-boot": "workspace:^", diff --git a/packages/subagent/subagent-fork-in-process/package.json b/packages/subagent/subagent-fork-in-process/package.json index 22d147631e..507e1cd6be 100644 --- a/packages/subagent/subagent-fork-in-process/package.json +++ b/packages/subagent/subagent-fork-in-process/package.json @@ -31,13 +31,13 @@ "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-subagent": "workspace:^", "@deepseek-ai/dsh-subagent-in-process-driver": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "dependencies": { - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis-plugin-loader": "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:^", @@ -47,7 +47,7 @@ "@deepseek-ai/dsh-subagent": "workspace:^", "@deepseek-ai/dsh-subagent-in-process-driver": "workspace:^", "@deepseek-ai/dsh-subagent-spawn-in-process": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-session-projection": "workspace:^" } } diff --git a/packages/subagent/subagent-in-process-driver/package.json b/packages/subagent/subagent-in-process-driver/package.json index 2c3ede08bd..7c50e623de 100644 --- a/packages/subagent/subagent-in-process-driver/package.json +++ b/packages/subagent/subagent-in-process-driver/package.json @@ -27,7 +27,7 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", @@ -36,9 +36,9 @@ "@deepseek-ai/dsh-tools": "workspace:^" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", - "@deepseek-ai/cordis-plugin-include": "workspace:^", - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", + "@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:^", diff --git a/packages/subagent/subagent-spawn-in-process/package.json b/packages/subagent/subagent-spawn-in-process/package.json index a7c5e2f2a6..489d735a23 100644 --- a/packages/subagent/subagent-spawn-in-process/package.json +++ b/packages/subagent/subagent-spawn-in-process/package.json @@ -29,13 +29,13 @@ "peerDependencies": { "@deepseek-ai/dsh-subagent": "workspace:^", "@deepseek-ai/dsh-subagent-in-process-driver": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "dependencies": { - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis-plugin-loader": "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:^", @@ -49,7 +49,7 @@ "@deepseek-ai/dsh-subagent-in-process-driver": "workspace:^", "@deepseek-ai/dsh-tool-bash": "workspace:^", "@deepseek-ai/dsh-tool-subagent": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-session-projection": "workspace:^" } } diff --git a/packages/subagent/subagent/package.json b/packages/subagent/subagent/package.json index ea19ef9c7b..91c412970d 100644 --- a/packages/subagent/subagent/package.json +++ b/packages/subagent/subagent/package.json @@ -59,7 +59,7 @@ "zod": "^4.4.3" }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-agent-presets": "workspace:^", "@deepseek-ai/dsh-attachment": "workspace:^", @@ -110,7 +110,7 @@ } }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-agent-presets": "workspace:^", "@deepseek-ai/dsh-attachment": "workspace:^", diff --git a/packages/subagent/tool-subagent-control/package.json b/packages/subagent/tool-subagent-control/package.json index 2272a1c6a2..938bee4928 100644 --- a/packages/subagent/tool-subagent-control/package.json +++ b/packages/subagent/tool-subagent-control/package.json @@ -32,14 +32,14 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-subagent": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-agent-loop": "workspace:^", "@deepseek-ai/dsh-agent-loop-testkit": "workspace:^", diff --git a/packages/subagent/tool-subagent/package.json b/packages/subagent/tool-subagent/package.json index aba9a126eb..ea6d41aad7 100644 --- a/packages/subagent/tool-subagent/package.json +++ b/packages/subagent/tool-subagent/package.json @@ -48,14 +48,14 @@ "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-jobs": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "dependencies": { - "@deepseek-ai/schemastery": "workspace:^", + "@deepseek-ai/schemastery": "workspace:*", "zod": "^4.4.3" }, "devDependencies": { - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis-plugin-loader": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", @@ -71,7 +71,7 @@ "@deepseek-ai/dsh-jobs-local": "workspace:^", "@deepseek-ai/dsh-tool-jobs": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-session-projection": "workspace:^" } } diff --git a/packages/subprocess/subprocess-local/package.json b/packages/subprocess/subprocess-local/package.json index e9ee873f97..9ddd44aa8c 100644 --- a/packages/subprocess/subprocess-local/package.json +++ b/packages/subprocess/subprocess-local/package.json @@ -39,7 +39,7 @@ "peerDependencies": { "@deepseek-ai/dsh-subprocess": "workspace:^", "@deepseek-ai/dsh-timeout": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "dependencies": { "@deepseek-ai/dsh-win32-process": "workspace:^", @@ -50,6 +50,6 @@ "@deepseek-ai/dsh-loader-smoke": "workspace:^", "@deepseek-ai/dsh-subprocess": "workspace:^", "@deepseek-ai/dsh-timeout": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/subprocess/subprocess/package.json b/packages/subprocess/subprocess/package.json index f57e763bd7..86668ed669 100644 --- a/packages/subprocess/subprocess/package.json +++ b/packages/subprocess/subprocess/package.json @@ -27,11 +27,11 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-http-proxy": "workspace:^" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-http-proxy": "workspace:^", "@deepseek-ai/dsh-launch-environment": "workspace:^" } diff --git a/packages/subprocess/win32-process/package.json b/packages/subprocess/win32-process/package.json index 0338895db5..baaa455ffd 100644 --- a/packages/subprocess/win32-process/package.json +++ b/packages/subprocess/win32-process/package.json @@ -27,12 +27,12 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "dependencies": { "koffi": "^3.1.0" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/terminal/terminal-bash/package.json b/packages/terminal/terminal-bash/package.json index 619cd97da3..7dc1f47d67 100644 --- a/packages/terminal/terminal-bash/package.json +++ b/packages/terminal/terminal-bash/package.json @@ -33,12 +33,12 @@ "@deepseek-ai/dsh-sandbox-policy": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-subprocess": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-session-projection": "workspace:^" }, "dependencies": { "@deepseek-ai/dsh-pwsh-local": "workspace:^", - "@deepseek-ai/schemastery": "workspace:^", + "@deepseek-ai/schemastery": "workspace:*", "@xterm/headless": "^6.0.0" }, "devDependencies": { @@ -50,6 +50,6 @@ "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-subprocess": "workspace:^", "@deepseek-ai/dsh-subprocess-local": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/terminal/terminal/package.json b/packages/terminal/terminal/package.json index 6ae9f278ee..cdd4676fc8 100644 --- a/packages/terminal/terminal/package.json +++ b/packages/terminal/terminal/package.json @@ -29,13 +29,13 @@ "peerDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-brand": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-agent-loop-testkit": "workspace:^", "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/terminal/tool-terminal/package.json b/packages/terminal/tool-terminal/package.json index b9467f6204..62f9215d9e 100644 --- a/packages/terminal/tool-terminal/package.json +++ b/packages/terminal/tool-terminal/package.json @@ -27,7 +27,7 @@ ], "license": "MIT", "dependencies": { - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "peerDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -37,11 +37,11 @@ "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-jobs": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis-plugin-include": "workspace:^", - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis-plugin-include": "workspace:*", + "@deepseek-ai/cordis-plugin-loader": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-agent-loop-testkit": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", @@ -57,7 +57,7 @@ "@deepseek-ai/dsh-jobs-local": "workspace:^", "@deepseek-ai/dsh-tool-jobs": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-session-projection": "workspace:^" } } diff --git a/packages/test-support/agent-loop-testkit/package.json b/packages/test-support/agent-loop-testkit/package.json index e476648bfa..dd756655cb 100644 --- a/packages/test-support/agent-loop-testkit/package.json +++ b/packages/test-support/agent-loop-testkit/package.json @@ -34,7 +34,7 @@ "@deepseek-ai/dsh-session-projection": "workspace:^", "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "dependencies": {}, "devDependencies": { @@ -45,6 +45,6 @@ "@deepseek-ai/dsh-session-projection": "workspace:^", "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/test-support/client-runtime/package.json b/packages/test-support/client-runtime/package.json index 0d6844ea6a..2b1b3d0bf2 100644 --- a/packages/test-support/client-runtime/package.json +++ b/packages/test-support/client-runtime/package.json @@ -42,7 +42,7 @@ "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-subagent": "workspace:^", "@deepseek-ai/dsh-typert-protocol": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "react": "^18.2.0", "react-dom": "^18.2.0" }, @@ -64,7 +64,7 @@ "@deepseek-ai/dsh-typert-protocol": "workspace:^", "@types/react": "~18.3.1", "@types/react-dom": "~18.3.0", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "react": "^18.2.0", "react-dom": "^18.2.0" }, diff --git a/packages/test-support/llm-mock-server/package.json b/packages/test-support/llm-mock-server/package.json index 7a238460fb..eda9c672f6 100644 --- a/packages/test-support/llm-mock-server/package.json +++ b/packages/test-support/llm-mock-server/package.json @@ -27,9 +27,9 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/test-support/llm-replay/package.json b/packages/test-support/llm-replay/package.json index d3e4e4540e..245095b254 100644 --- a/packages/test-support/llm-replay/package.json +++ b/packages/test-support/llm-replay/package.json @@ -27,7 +27,7 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-compaction": "workspace:^", "@deepseek-ai/dsh-deepseek-llm-api-extensions": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", @@ -39,7 +39,7 @@ } }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-compaction": "workspace:^", "@deepseek-ai/dsh-deepseek-llm-api-extensions": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", diff --git a/packages/test-support/loader-smoke/package.json b/packages/test-support/loader-smoke/package.json index 7958561a39..d0bb80d2dd 100644 --- a/packages/test-support/loader-smoke/package.json +++ b/packages/test-support/loader-smoke/package.json @@ -31,14 +31,14 @@ "tsx": "^4.22.4" }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-http-proxy": "workspace:^" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-app-boot": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", diff --git a/packages/test-support/session-snapshot/package.json b/packages/test-support/session-snapshot/package.json index f3a6468992..ba37c3588f 100644 --- a/packages/test-support/session-snapshot/package.json +++ b/packages/test-support/session-snapshot/package.json @@ -36,12 +36,12 @@ "vitest": "^4.1.8" }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-http-proxy": "workspace:^" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-agent-loop": "workspace:^", "@deepseek-ai/dsh-compaction": "workspace:^", diff --git a/packages/todo/tool-todo/package.json b/packages/todo/tool-todo/package.json index 7eb98180dd..4d57bff520 100644 --- a/packages/todo/tool-todo/package.json +++ b/packages/todo/tool-todo/package.json @@ -37,7 +37,7 @@ ], "license": "MIT", "dependencies": { - "@deepseek-ai/schemastery": "workspace:^", + "@deepseek-ai/schemastery": "workspace:*", "zod": "^4.4.3" }, "peerDependencies": { @@ -46,11 +46,11 @@ "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-session-projection": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis-plugin-include": "workspace:^", - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@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:^", @@ -61,6 +61,6 @@ "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", "@deepseek-ai/dsh-user-questions": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/typert/generator/package.json b/packages/typert/generator/package.json index ab65157347..21cf25f8e9 100644 --- a/packages/typert/generator/package.json +++ b/packages/typert/generator/package.json @@ -36,12 +36,12 @@ "typescript": "^6.0.3" }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-tool-cordis": "workspace:^", "@deepseek-ai/dsh-typert-registry": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "zod": "^4.4.3" } } diff --git a/packages/typert/loader/package.json b/packages/typert/loader/package.json index d0873289e6..bcbb5548f8 100644 --- a/packages/typert/loader/package.json +++ b/packages/typert/loader/package.json @@ -27,17 +27,17 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis-plugin-loader": "workspace:*", "@deepseek-ai/dsh-typert-registry": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "dependencies": { - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis-plugin-loader": "workspace:*", "@deepseek-ai/dsh-typert-registry": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "zod": "^4.4.3" } } diff --git a/packages/typert/protocol/package.json b/packages/typert/protocol/package.json index 199936fcc5..347f804f31 100644 --- a/packages/typert/protocol/package.json +++ b/packages/typert/protocol/package.json @@ -32,9 +32,9 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/typert/registry/package.json b/packages/typert/registry/package.json index 307410ed20..d2b9e5c60f 100644 --- a/packages/typert/registry/package.json +++ b/packages/typert/registry/package.json @@ -51,10 +51,10 @@ "zod": "^4.4.3" }, "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-typert-protocol": "workspace:^" } } diff --git a/packages/util/atomic-write/package.json b/packages/util/atomic-write/package.json index 7aa769a1ba..b805131b48 100644 --- a/packages/util/atomic-write/package.json +++ b/packages/util/atomic-write/package.json @@ -27,9 +27,9 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/util/brand/package.json b/packages/util/brand/package.json index b108caf9cc..e389cf15eb 100644 --- a/packages/util/brand/package.json +++ b/packages/util/brand/package.json @@ -27,9 +27,9 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/util/chunked-list/package.json b/packages/util/chunked-list/package.json index e93ccec925..86505ac3bc 100644 --- a/packages/util/chunked-list/package.json +++ b/packages/util/chunked-list/package.json @@ -27,10 +27,10 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "dependencies": { "zod": "^4.4.3" diff --git a/packages/util/crypto/package.json b/packages/util/crypto/package.json index 3d1fb4e136..5ab63eb83a 100644 --- a/packages/util/crypto/package.json +++ b/packages/util/crypto/package.json @@ -27,9 +27,9 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/util/deque/package.json b/packages/util/deque/package.json index 37f6d8d589..d9f0a1804f 100644 --- a/packages/util/deque/package.json +++ b/packages/util/deque/package.json @@ -27,9 +27,9 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/util/home-paths/package.json b/packages/util/home-paths/package.json index 020b85dce1..4187d95fa2 100644 --- a/packages/util/home-paths/package.json +++ b/packages/util/home-paths/package.json @@ -27,9 +27,9 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/util/http-proxy/package.json b/packages/util/http-proxy/package.json index 87d0ddcc77..7a8170f50b 100644 --- a/packages/util/http-proxy/package.json +++ b/packages/util/http-proxy/package.json @@ -27,13 +27,13 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "dependencies": { "undici": "^8.10.0" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-invariants": "workspace:^" } } diff --git a/packages/util/launch-environment/package.json b/packages/util/launch-environment/package.json index 36f1f4be95..28a01033db 100644 --- a/packages/util/launch-environment/package.json +++ b/packages/util/launch-environment/package.json @@ -27,9 +27,9 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/util/native-command/package.json b/packages/util/native-command/package.json index 31d5770858..f4ce7b6ec2 100644 --- a/packages/util/native-command/package.json +++ b/packages/util/native-command/package.json @@ -27,9 +27,9 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/util/output-retention/package.json b/packages/util/output-retention/package.json index 1de1a53bd5..7048e841c1 100644 --- a/packages/util/output-retention/package.json +++ b/packages/util/output-retention/package.json @@ -27,9 +27,9 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/util/package-manifest/package.json b/packages/util/package-manifest/package.json index 85b8a0b1ff..c9b9121f69 100644 --- a/packages/util/package-manifest/package.json +++ b/packages/util/package-manifest/package.json @@ -27,9 +27,9 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/util/time/package.json b/packages/util/time/package.json index a191aa8376..81edeb6a94 100644 --- a/packages/util/time/package.json +++ b/packages/util/time/package.json @@ -27,9 +27,9 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/util/timeout/package.json b/packages/util/timeout/package.json index c1cbd2bae2..c5fab6aade 100644 --- a/packages/util/timeout/package.json +++ b/packages/util/timeout/package.json @@ -27,9 +27,9 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/util/values/package.json b/packages/util/values/package.json index b46eed22cc..af71263cbf 100644 --- a/packages/util/values/package.json +++ b/packages/util/values/package.json @@ -27,9 +27,9 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/util/workspace-path/package.json b/packages/util/workspace-path/package.json index a8dca334e3..3617c53018 100644 --- a/packages/util/workspace-path/package.json +++ b/packages/util/workspace-path/package.json @@ -27,9 +27,9 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/web/tool-web/package.json b/packages/web/tool-web/package.json index b3fe173fad..c731904124 100644 --- a/packages/web/tool-web/package.json +++ b/packages/web/tool-web/package.json @@ -27,7 +27,7 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", @@ -35,12 +35,12 @@ }, "dependencies": { "@deepseek-ai/dsh-util-values": "workspace:^", - "@deepseek-ai/schemastery": "workspace:^", + "@deepseek-ai/schemastery": "workspace:*", "@joplin/turndown-plugin-gfm": "^1.0.67", "turndown": "^7.2.4" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", diff --git a/packages/web/web-fetch-http/package.json b/packages/web/web-fetch-http/package.json index 85ab4871d8..c81a828ce4 100644 --- a/packages/web/web-fetch-http/package.json +++ b/packages/web/web-fetch-http/package.json @@ -27,18 +27,18 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-timeout": "workspace:^", "@deepseek-ai/dsh-web": "workspace:^", "@deepseek-ai/dsh-http-proxy": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "workspace:^", + "@deepseek-ai/schemastery": "workspace:*", "ipaddr.js": "^2.5.0", "undici": "^8.10.0" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-timeout": "workspace:^", "@deepseek-ai/dsh-web": "workspace:^", "@deepseek-ai/dsh-http-proxy": "workspace:^" diff --git a/packages/web/web-search-deepseek/package.json b/packages/web/web-search-deepseek/package.json index 26eeb35a32..98853ed968 100644 --- a/packages/web/web-search-deepseek/package.json +++ b/packages/web/web-search-deepseek/package.json @@ -32,11 +32,11 @@ "@deepseek-ai/dsh-launch-environment": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-web": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-settings": "workspace:^" }, "dependencies": { - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -45,7 +45,7 @@ "@deepseek-ai/dsh-launch-environment": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-web": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-settings": "workspace:^", "@deepseek-ai/dsh-http-proxy": "workspace:^" } diff --git a/packages/web/web-search-exa/package.json b/packages/web/web-search-exa/package.json index 85bedd66d4..9e5d349579 100644 --- a/packages/web/web-search-exa/package.json +++ b/packages/web/web-search-exa/package.json @@ -29,15 +29,15 @@ "peerDependencies": { "@deepseek-ai/dsh-launch-environment": "workspace:^", "@deepseek-ai/dsh-web": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "dependencies": { - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-launch-environment": "workspace:^", "@deepseek-ai/dsh-web": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-http-proxy": "workspace:^" } } diff --git a/packages/web/web-search-perplexity/package.json b/packages/web/web-search-perplexity/package.json index 1e5cc82fc5..f0f7b73280 100644 --- a/packages/web/web-search-perplexity/package.json +++ b/packages/web/web-search-perplexity/package.json @@ -29,15 +29,15 @@ "peerDependencies": { "@deepseek-ai/dsh-launch-environment": "workspace:^", "@deepseek-ai/dsh-web": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "dependencies": { - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-launch-environment": "workspace:^", "@deepseek-ai/dsh-web": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-http-proxy": "workspace:^" } } diff --git a/packages/web/web/package.json b/packages/web/web/package.json index 58fa29784a..b5e92eb755 100644 --- a/packages/web/web/package.json +++ b/packages/web/web/package.json @@ -28,13 +28,13 @@ "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-llm": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "dependencies": { - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-llm": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/webhook/webhook-github/package.json b/packages/webhook/webhook-github/package.json index e94244a5b8..6f40c1fce7 100644 --- a/packages/webhook/webhook-github/package.json +++ b/packages/webhook/webhook-github/package.json @@ -32,7 +32,7 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-credentials": "workspace:^", "@deepseek-ai/dsh-host-webserver": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", @@ -40,13 +40,13 @@ }, "dependencies": { "@deepseek-ai/dsh-util-values": "workspace:^", - "@deepseek-ai/schemastery": "workspace:^", + "@deepseek-ai/schemastery": "workspace:*", "@octokit/webhooks": "^14.2.0" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", - "@deepseek-ai/cordis-plugin-include": "workspace:^", - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", + "@deepseek-ai/cordis-plugin-include": "workspace:*", + "@deepseek-ai/cordis-plugin-loader": "workspace:*", "@deepseek-ai/dsh-credentials": "workspace:^", "@deepseek-ai/dsh-host-webserver": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", diff --git a/packages/webhook/webhook/package.json b/packages/webhook/webhook/package.json index ca075c0b3d..5f2277ba07 100644 --- a/packages/webhook/webhook/package.json +++ b/packages/webhook/webhook/package.json @@ -37,7 +37,7 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-agent-default-model": "workspace:^", "@deepseek-ai/dsh-agent-presets": "workspace:^", @@ -49,9 +49,9 @@ "@deepseek-ai/dsh-workspace": "workspace:^" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", - "@deepseek-ai/cordis-plugin-include": "workspace:^", - "@deepseek-ai/cordis-plugin-loader": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", + "@deepseek-ai/cordis-plugin-include": "workspace:*", + "@deepseek-ai/cordis-plugin-loader": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-agent-default-model": "workspace:^", "@deepseek-ai/dsh-agent-presets": "workspace:^", diff --git a/packages/workflow/tool-ralph/package.json b/packages/workflow/tool-ralph/package.json index 5f22369daa..70a82b6967 100644 --- a/packages/workflow/tool-ralph/package.json +++ b/packages/workflow/tool-ralph/package.json @@ -33,13 +33,13 @@ "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", "@deepseek-ai/dsh-workflow": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "dependencies": { - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis-plugin-loader": "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:^", @@ -52,7 +52,7 @@ "@deepseek-ai/dsh-tools": "workspace:^", "@deepseek-ai/dsh-workflow": "workspace:^", "@deepseek-ai/dsh-workflow-worker-thread": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-session-projection": "workspace:^" } } diff --git a/packages/workflow/tool-workflow/package.json b/packages/workflow/tool-workflow/package.json index bf6b1e1c60..4115427262 100644 --- a/packages/workflow/tool-workflow/package.json +++ b/packages/workflow/tool-workflow/package.json @@ -44,10 +44,10 @@ "@deepseek-ai/dsh-system-prompt": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", "@deepseek-ai/dsh-workflow": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "dependencies": { - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -59,7 +59,7 @@ "@deepseek-ai/dsh-tools": "workspace:^", "@deepseek-ai/dsh-workflow": "workspace:^", "@deepseek-ai/dsh-workflow-worker-thread": "workspace:^", - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-session-projection": "workspace:^" } } diff --git a/packages/workflow/workflow-worker-thread/package.json b/packages/workflow/workflow-worker-thread/package.json index 51507b52c1..259fe7527e 100644 --- a/packages/workflow/workflow-worker-thread/package.json +++ b/packages/workflow/workflow-worker-thread/package.json @@ -32,7 +32,7 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", @@ -43,10 +43,10 @@ "dependencies": { "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-util-values": "workspace:^", - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-agent-loop": "workspace:^", "@deepseek-ai/dsh-agent-loop-testkit": "workspace:^", diff --git a/packages/workflow/workflow/package.json b/packages/workflow/workflow/package.json index 8b958f9ceb..f1bfc1f276 100644 --- a/packages/workflow/workflow/package.json +++ b/packages/workflow/workflow/package.json @@ -42,7 +42,7 @@ "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" }, "devDependencies": { "@deepseek-ai/dsh-agent": "workspace:^", @@ -50,6 +50,6 @@ "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-llm": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", - "@deepseek-ai/cordis": "workspace:^" + "@deepseek-ai/cordis": "workspace:*" } } diff --git a/packages/workspace/workspace/package.json b/packages/workspace/workspace/package.json index 35df2dc687..b5fb6fe436 100644 --- a/packages/workspace/workspace/package.json +++ b/packages/workspace/workspace/package.json @@ -37,7 +37,7 @@ ], "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-session-persistence": "workspace:^", @@ -50,7 +50,7 @@ "zod": "^4.4.3" }, "devDependencies": { - "@deepseek-ai/cordis": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", "@deepseek-ai/dsh-invariants": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-session-persistence": "workspace:^", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index be1647c24b..91f79de0d8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -134,19 +134,19 @@ importers: apps/cli: dependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + 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-acp-app': specifier: workspace:^ @@ -544,10 +544,10 @@ importers: apps/desktop-host: dependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../vendor/cordis '@deepseek-ai/cordis-plugin-include': - specifier: workspace:^ + specifier: workspace:* version: link:../../vendor/include '@deepseek-ai/dsh': specifier: workspace:^ @@ -586,7 +586,7 @@ importers: apps/web: devDependencies: '@deepseek-ai/cordis-plugin-group': - specifier: workspace:^ + specifier: workspace:* version: link:../../vendor/group '@deepseek-ai/dsh-client-modules': specifier: workspace:^ @@ -667,7 +667,7 @@ importers: benchmarks: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -793,7 +793,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -854,7 +854,7 @@ importers: version: 8.21.0 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-brand': specifier: workspace:^ @@ -891,7 +891,7 @@ importers: version: link:../../util/values devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -991,7 +991,7 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -1118,7 +1118,7 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent-presets': specifier: workspace:^ @@ -1149,7 +1149,7 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-api-gateway': specifier: workspace:^ @@ -1192,7 +1192,7 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-api-gateway': specifier: workspace:^ @@ -1222,7 +1222,7 @@ importers: packages/attachment/attachment: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-brand': specifier: workspace:^ @@ -1238,7 +1238,7 @@ importers: version: 0.35.3(@types/node@22.20.0) devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-attachment': specifier: workspace:^ @@ -1263,22 +1263,22 @@ importers: version: 2.0.3 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-group': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/group '@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-home-paths': specifier: workspace:^ @@ -1299,13 +1299,13 @@ importers: packages/boot/cmdline: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@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 commander: specifier: ^15.0.0 @@ -1324,19 +1324,19 @@ importers: version: 15.0.0 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-include': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/include 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:^ @@ -1586,7 +1586,7 @@ importers: version: link:../../workflow/workflow-worker-thread devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis packages/bundle/headless: @@ -1611,10 +1611,10 @@ importers: version: 15.0.0 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-loader': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/loader '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -1651,16 +1651,16 @@ importers: version: 15.0.0 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-include': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/include packages/bundle/sdk-minimal: dependencies: '@deepseek-ai/cordis-plugin-timer': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/timer '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -1742,7 +1742,7 @@ importers: version: link:../../core/tools devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis packages/bundle/web-app: @@ -1989,10 +1989,10 @@ importers: version: 11.0.0 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-loader': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/loader '@deepseek-ai/dsh-shell-env': specifier: workspace:^ @@ -2014,7 +2014,7 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-api-session-controller': specifier: workspace:^ @@ -2063,7 +2063,7 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -2097,10 +2097,10 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-loader': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/loader '@deepseek-ai/dsh-client-modules': specifier: workspace:^ @@ -2119,7 +2119,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-api-remotes': specifier: workspace:^ @@ -2158,10 +2158,10 @@ importers: packages/client/modules: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-loader': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/loader '@deepseek-ai/dsh-host-webserver': specifier: workspace:^ @@ -2176,7 +2176,7 @@ importers: packages/client/resources: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-client-store': specifier: workspace:^ @@ -2197,7 +2197,7 @@ importers: packages/client/store: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis immer: specifier: ^10.1.1 @@ -2209,7 +2209,7 @@ importers: packages/client/ui-agent-preset: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent-presets': specifier: workspace:^ @@ -2266,7 +2266,7 @@ importers: packages/client/ui-approval: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-api-remotes': specifier: workspace:^ @@ -2311,7 +2311,7 @@ importers: packages/client/ui-attachment: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-attachment': specifier: workspace:^ @@ -2356,7 +2356,7 @@ importers: packages/client/ui-brand-official: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-client-ui-primitives': specifier: workspace:^ @@ -2387,7 +2387,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -2495,7 +2495,7 @@ importers: packages/client/ui-commands: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-api-remotes': specifier: workspace:^ @@ -2556,7 +2556,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-api-remotes': specifier: workspace:^ @@ -2689,7 +2689,7 @@ importers: version: link:../../typert/protocol devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -2770,7 +2770,7 @@ importers: packages/client/ui-directory-picker-browse: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-api-remotes': specifier: workspace:^ @@ -2812,7 +2812,7 @@ importers: packages/client/ui-directory-picker-native: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-client-ui-renderer': specifier: workspace:^ @@ -2836,7 +2836,7 @@ importers: packages/client/ui-dockkit: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-brand': specifier: workspace:^ @@ -2866,7 +2866,7 @@ importers: packages/client/ui-goal: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-api-remotes': specifier: workspace:^ @@ -2926,7 +2926,7 @@ importers: packages/client/ui-input-trigger: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-api-session-controller': specifier: workspace:^ @@ -2974,7 +2974,7 @@ importers: packages/client/ui-jobs: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-api-session-controller': specifier: workspace:^ @@ -3010,7 +3010,7 @@ importers: packages/client/ui-layout: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-brand': specifier: workspace:^ @@ -3043,7 +3043,7 @@ importers: packages/client/ui-message-feedback: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-api-remotes': specifier: workspace:^ @@ -3112,7 +3112,7 @@ importers: packages/client/ui-model-selection: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-api-remotes': specifier: workspace:^ @@ -3175,7 +3175,7 @@ importers: packages/client/ui-open-in-app: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-api-session-controller': specifier: workspace:^ @@ -3220,7 +3220,7 @@ importers: packages/client/ui-permission-presets: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-api-remotes': specifier: workspace:^ @@ -3271,7 +3271,7 @@ importers: packages/client/ui-plan: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-api-remotes': specifier: workspace:^ @@ -3313,7 +3313,7 @@ importers: packages/client/ui-primitives: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@shikijs/langs': specifier: ^4.3.1 @@ -3385,7 +3385,7 @@ importers: packages/client/ui-reference: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-api-remotes': specifier: workspace:^ @@ -3427,7 +3427,7 @@ importers: packages/client/ui-renderer: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-client-test-runtime': specifier: workspace:^ @@ -3460,7 +3460,7 @@ importers: packages/client/ui-schedule: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-api-session-controller': specifier: workspace:^ @@ -3511,7 +3511,7 @@ importers: packages/client/ui-session: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-api-session-controller': specifier: workspace:^ @@ -3538,7 +3538,7 @@ importers: packages/client/ui-settings: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-api-remotes': specifier: workspace:^ @@ -3575,7 +3575,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-api-remotes': specifier: workspace:^ @@ -3626,7 +3626,7 @@ importers: packages/client/ui-settings-models: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-api-remotes': specifier: workspace:^ @@ -3665,7 +3665,7 @@ importers: packages/client/ui-settings-plugin-inventory: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent-presets': specifier: workspace:^ @@ -3710,7 +3710,7 @@ importers: packages/client/ui-settings-plugins: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-api-remotes': specifier: workspace:^ @@ -3749,7 +3749,7 @@ importers: packages/client/ui-sidebar: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-api-workspace-controller': specifier: workspace:^ @@ -3794,7 +3794,7 @@ importers: packages/client/ui-sidebar-documentpreview: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-api-gateway': specifier: workspace:^ @@ -3866,7 +3866,7 @@ importers: packages/client/ui-sidebar-files: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-api-remotes': specifier: workspace:^ @@ -3929,7 +3929,7 @@ importers: packages/client/ui-sidebar-right: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-api-session-controller': specifier: workspace:^ @@ -3998,7 +3998,7 @@ importers: packages/client/ui-skill: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-api-remotes': specifier: workspace:^ @@ -4049,7 +4049,7 @@ importers: packages/client/ui-slots: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-client-store': specifier: workspace:^ @@ -4061,7 +4061,7 @@ importers: packages/client/ui-subagent: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-api-session-controller': specifier: workspace:^ @@ -4122,7 +4122,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-api-remotes': specifier: workspace:^ @@ -4170,7 +4170,7 @@ importers: packages/client/ui-tool: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -4254,7 +4254,7 @@ importers: packages/client/ui-trajectory: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -4326,7 +4326,7 @@ importers: packages/client/ui-user-questions: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -4389,7 +4389,7 @@ importers: packages/client/ui-workflow-run: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-api-session-controller': specifier: workspace:^ @@ -4440,7 +4440,7 @@ importers: packages/client/ui-workspace: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-api-remotes': specifier: workspace:^ @@ -4509,10 +4509,10 @@ importers: packages/client/web: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-loader': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/loader '@deepseek-ai/dsh-client-modules': specifier: workspace:^ @@ -4551,7 +4551,7 @@ importers: packages/code-runtime/code-runtime: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis packages/code-runtime/code-runtime-worker-thread: @@ -4564,7 +4564,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-code-runtime': specifier: workspace:^ @@ -4579,13 +4579,13 @@ importers: packages/compaction/command-compact: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@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/dsh-agent': specifier: workspace:^ @@ -4606,7 +4606,7 @@ importers: packages/compaction/compaction: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-brand': specifier: workspace:^ @@ -4634,13 +4634,13 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@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/dsh-agent': specifier: workspace:^ @@ -4692,13 +4692,13 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@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/dsh-compaction': specifier: workspace:^ @@ -4729,10 +4729,10 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-loader': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/loader '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -4777,7 +4777,7 @@ importers: packages/context/file-reference: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -4790,7 +4790,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -4821,13 +4821,13 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@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/dsh-agent': specifier: workspace:^ @@ -4894,7 +4894,7 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -4952,7 +4952,7 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -4979,7 +4979,7 @@ importers: packages/core/agent: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -5016,7 +5016,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -5044,7 +5044,7 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -5090,7 +5090,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -5114,7 +5114,7 @@ importers: packages/core/scope: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -5133,7 +5133,7 @@ importers: version: link:../../util/values devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -5155,7 +5155,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -5180,7 +5180,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -5213,7 +5213,7 @@ importers: packages/credentials/authorization: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-credentials': specifier: workspace:^ @@ -5232,7 +5232,7 @@ importers: version: link:../../util/brand devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -5251,7 +5251,7 @@ importers: version: 2.9.0 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-atomic-write': specifier: workspace:^ @@ -5276,7 +5276,7 @@ importers: version: 2.29.1 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -5330,7 +5330,7 @@ importers: packages/e2b/fs-e2b: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-e2b': specifier: workspace:^ @@ -5346,7 +5346,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-e2b': specifier: workspace:^ @@ -5371,7 +5371,7 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -5426,10 +5426,10 @@ importers: version: link:../tool-agent-team devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-include': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/include js-yaml: specifier: ^4.2.0 @@ -5442,10 +5442,10 @@ importers: version: link:../client-ui-agent-team devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-include': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/include js-yaml: specifier: ^4.2.0 @@ -5458,7 +5458,7 @@ importers: version: 18.3.1 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-api-remotes': specifier: workspace:^ @@ -5513,7 +5513,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-code-runtime': specifier: workspace:^ @@ -5544,13 +5544,13 @@ importers: version: 8.21.0 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@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/dsh-host-webserver': specifier: workspace:^ @@ -5572,7 +5572,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -5623,7 +5623,7 @@ importers: packages/experimental/webworker-packer: dependencies: '@deepseek-ai/cordis-plugin-include': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/include '@deepseek-ai/dsh-experimental-webworker-runtime': specifier: workspace:^ @@ -5639,7 +5639,7 @@ importers: version: 4.0.4 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-package-manifest': specifier: workspace:^ @@ -5676,10 +5676,10 @@ importers: version: 4.7.0 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-loader': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/loader '@deepseek-ai/dsh-api-gateway': specifier: workspace:^ @@ -5736,10 +5736,10 @@ importers: packages/extensions/cordis-client-runner: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-loader': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/loader '@deepseek-ai/dsh-api-remotes': specifier: workspace:^ @@ -5776,10 +5776,10 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-timer': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/timer '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -5806,10 +5806,10 @@ importers: packages/extensions/tool-cordis: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-loader': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/loader '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -5836,7 +5836,7 @@ importers: packages/extensions/ui-cordis: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-api-remotes': specifier: workspace:^ @@ -5888,13 +5888,13 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@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/dsh-agent': specifier: workspace:^ @@ -5928,13 +5928,13 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@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/dsh-brand': specifier: workspace:^ @@ -5961,7 +5961,7 @@ importers: packages/fs/fs: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-brand': specifier: workspace:^ @@ -5986,7 +5986,7 @@ importers: version: 3.1.1 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-fs': specifier: workspace:^ @@ -5998,7 +5998,7 @@ importers: packages/fs/fs-observation-policy: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-fs': specifier: workspace:^ @@ -6010,7 +6010,7 @@ importers: packages/fs/fs-sandbox: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-fs': specifier: workspace:^ @@ -6038,7 +6038,7 @@ importers: version: 9.0.0 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -6105,7 +6105,7 @@ importers: version: 1.18.0 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -6148,7 +6148,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -6191,7 +6191,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -6236,10 +6236,10 @@ importers: packages/goal/command-goal: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-loader': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/loader '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -6276,7 +6276,7 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -6327,7 +6327,7 @@ importers: packages/goal/goal-round-driver: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -6367,10 +6367,10 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-loader': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/loader '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -6407,7 +6407,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -6434,7 +6434,7 @@ importers: packages/guard/timeout-policy: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-llm': specifier: workspace:^ @@ -6449,7 +6449,7 @@ importers: packages/hooks/hook-protocol: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -6468,7 +6468,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -6517,7 +6517,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -6559,7 +6559,7 @@ importers: packages/host/directory-picker: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis packages/host/directory-picker-auto: @@ -6569,13 +6569,13 @@ importers: version: link:../../util/launch-environment devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@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/dsh-client-ui-directory-picker-browse': specifier: workspace:^ @@ -6606,7 +6606,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis packages/host/directory-picker-native: @@ -6622,7 +6622,7 @@ importers: version: 3.1.1 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis tsx: specifier: ^4.19.2 @@ -6635,10 +6635,10 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-loader': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/loader '@deepseek-ai/dsh-client-connection': specifier: workspace:^ @@ -6666,10 +6666,10 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-loader': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/loader '@deepseek-ai/dsh-host-webserver': specifier: workspace:^ @@ -6682,10 +6682,10 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-loader': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/loader '@deepseek-ai/dsh-agent-presets': specifier: workspace:^ @@ -6710,7 +6710,7 @@ importers: version: 1.0.0 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@types/compression': specifier: ^1.8.1 @@ -6722,7 +6722,7 @@ importers: packages/identity/anonymous-user-id: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-brand': specifier: workspace:^ @@ -6741,7 +6741,7 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -6778,7 +6778,7 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-commands': specifier: workspace:^ @@ -6811,7 +6811,7 @@ importers: packages/interaction/tool-ask-user: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -6836,7 +6836,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -6863,7 +6863,7 @@ importers: packages/interaction/user-questions: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -6878,7 +6878,7 @@ importers: packages/jobs/jobs: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -6900,13 +6900,13 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@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/dsh-agent': specifier: workspace:^ @@ -6937,7 +6937,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -6967,7 +6967,7 @@ importers: packages/llm/deepseek-llm-api-extensions: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis packages/llm/llm: @@ -6995,7 +6995,7 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-attachment': specifier: workspace:^ @@ -7020,7 +7020,7 @@ importers: version: 3.1.0 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -7090,7 +7090,7 @@ importers: version: 0.85.1(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(ws@8.21.0)(zod@4.4.3) devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-attachment': specifier: workspace:^ @@ -7133,13 +7133,13 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@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/dsh-agent': specifier: workspace:^ @@ -7194,13 +7194,13 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@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/dsh-agent': specifier: workspace:^ @@ -7234,7 +7234,7 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-compaction': specifier: workspace:^ @@ -7255,7 +7255,7 @@ importers: packages/lsp/lsp: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-brand': specifier: workspace:^ @@ -7274,7 +7274,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-brand': specifier: workspace:^ @@ -7317,7 +7317,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -7366,7 +7366,7 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-attachment': specifier: workspace:^ @@ -7406,7 +7406,7 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -7455,16 +7455,16 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-group': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/group '@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/dsh-agent': specifier: workspace:^ @@ -7516,7 +7516,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-scope': specifier: workspace:^ @@ -7532,7 +7532,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis packages/sandbox/sandbox: @@ -7542,7 +7542,7 @@ importers: version: link:../../util/values devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-llm': specifier: workspace:^ @@ -7567,7 +7567,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-llm': specifier: workspace:^ @@ -7589,7 +7589,7 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -7620,7 +7620,7 @@ importers: version: 3.1.1 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-pwsh-local': specifier: workspace:^ @@ -7636,10 +7636,10 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-loader': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/loader '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -7685,7 +7685,7 @@ importers: version: link:../../../apps/cli devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-llm': specifier: workspace:^ @@ -7700,7 +7700,7 @@ importers: packages/sdk/protocol: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-llm': specifier: workspace:^ @@ -7722,10 +7722,10 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-loader': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/loader '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -7780,10 +7780,10 @@ importers: version: 0.8.3 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-loader': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/loader '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -7840,7 +7840,7 @@ importers: packages/session-query/session-query: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-brand': specifier: workspace:^ @@ -7874,10 +7874,10 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-loader': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/loader '@deepseek-ai/dsh-session': specifier: workspace:^ @@ -7905,7 +7905,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -7953,10 +7953,10 @@ importers: packages/session/session-checkpoint-policy: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-loader': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/loader '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -7996,7 +7996,7 @@ importers: version: link:../../util/values devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis packages/session/session-format-catalog: @@ -8015,7 +8015,7 @@ importers: version: link:../session-format-v2-to-v3 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-session': specifier: workspace:^ @@ -8031,7 +8031,7 @@ importers: version: link:../../util/values devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-session': specifier: workspace:^ @@ -8053,7 +8053,7 @@ importers: version: link:../../util/values devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-session': specifier: workspace:^ @@ -8072,7 +8072,7 @@ importers: version: link:../session-format-v1-to-v2 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis packages/session/session-log-deepseek: @@ -8088,13 +8088,13 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@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/dsh-command-feedback': specifier: workspace:^ @@ -8131,7 +8131,7 @@ importers: version: link:../../util/values devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-brand': specifier: workspace:^ @@ -8171,7 +8171,7 @@ importers: version: 3.1.1 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-session': specifier: workspace:^ @@ -8190,7 +8190,7 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-session': specifier: workspace:^ @@ -8209,7 +8209,7 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-session': specifier: workspace:^ @@ -8234,13 +8234,13 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@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/dsh-llm': specifier: workspace:^ @@ -8255,7 +8255,7 @@ importers: packages/session/session-telemetry: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -8289,13 +8289,13 @@ importers: version: 0.220.0(@opentelemetry/api@1.9.1) devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-loader': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/loader '@deepseek-ai/cordis-plugin-logger-console': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/logger-console '@deepseek-ai/dsh-anonymous-user-id': specifier: workspace:^ @@ -8350,7 +8350,7 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -8384,7 +8384,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent-loop': specifier: workspace:^ @@ -8412,13 +8412,13 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@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/dsh-agent-loop': specifier: workspace:^ @@ -8452,7 +8452,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-llm': specifier: workspace:^ @@ -8474,13 +8474,13 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@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/dsh-llm': specifier: workspace:^ @@ -8502,7 +8502,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-brand': specifier: workspace:^ @@ -8530,7 +8530,7 @@ importers: version: 2.9.0 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-atomic-write': specifier: workspace:^ @@ -8549,7 +8549,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-settings': specifier: workspace:^ @@ -8570,7 +8570,7 @@ importers: packages/shell/bash-sandbox: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-bash-local': specifier: workspace:^ @@ -8604,7 +8604,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-settings': specifier: workspace:^ @@ -8625,7 +8625,7 @@ importers: packages/shell/pwsh-sandbox: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-pwsh-local': specifier: workspace:^ @@ -8652,7 +8652,7 @@ importers: packages/shell/shell: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-sandbox': specifier: workspace:^ @@ -8671,7 +8671,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -8696,7 +8696,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -8763,13 +8763,13 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@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/dsh-agent': specifier: workspace:^ @@ -8818,7 +8818,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -8882,13 +8882,13 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@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/dsh-agent': specifier: workspace:^ @@ -8943,7 +8943,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-llm': specifier: workspace:^ @@ -8955,7 +8955,7 @@ importers: packages/skill/skill-badge: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-skill': specifier: workspace:^ @@ -8974,7 +8974,7 @@ importers: version: 2.9.0 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-fs': specifier: workspace:^ @@ -8993,7 +8993,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -9023,7 +9023,7 @@ importers: packages/spill/spill: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-brand': specifier: workspace:^ @@ -9042,13 +9042,13 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@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/dsh-brand': specifier: workspace:^ @@ -9070,7 +9070,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -9097,7 +9097,7 @@ importers: packages/storage/storage: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis packages/storage/storage-domain: @@ -9110,7 +9110,7 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -9126,7 +9126,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-storage': specifier: workspace:^ @@ -9139,7 +9139,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-storage': specifier: workspace:^ @@ -9161,7 +9161,7 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -9246,10 +9246,10 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-loader': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/loader '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -9313,7 +9313,7 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -9380,10 +9380,10 @@ importers: version: 0.153.4 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-loader': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/loader '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -9441,10 +9441,10 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-loader': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/loader '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -9505,10 +9505,10 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-loader': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/loader '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -9548,13 +9548,13 @@ importers: version: link:../../util/brand devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@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/dsh-agent': specifier: workspace:^ @@ -9609,10 +9609,10 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-loader': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/loader '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -9667,10 +9667,10 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-loader': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/loader '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -9731,7 +9731,7 @@ importers: version: link:../../util/values devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -9776,7 +9776,7 @@ importers: packages/subprocess/subprocess: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-http-proxy': specifier: workspace:^ @@ -9798,7 +9798,7 @@ importers: version: 1.2.0-beta.15(patch_hash=b40ae545608897914bd25fb009c97eeac478c34e8a910298ddcb01b746534bb0) devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-loader-smoke': specifier: workspace:^ @@ -9817,13 +9817,13 @@ importers: version: 3.1.1 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis packages/terminal/terminal: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -9854,7 +9854,7 @@ importers: version: 6.0.0 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -9888,13 +9888,13 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@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/dsh-agent': specifier: workspace:^ @@ -9948,7 +9948,7 @@ importers: packages/test-support/agent-loop-testkit: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -9985,7 +9985,7 @@ importers: version: 4.1.8(@opentelemetry/api@1.9.1)(@types/node@25.9.3)(@vitest/coverage-v8@4.1.8)(happy-dom@20.11.6)(jsdom@29.1.1(@noble/hashes@2.3.0))(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: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-api-session-controller': specifier: workspace:^ @@ -10048,7 +10048,7 @@ importers: packages/test-support/llm-mock-server: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis packages/test-support/llm-replay: @@ -10061,7 +10061,7 @@ importers: version: link:../../util/values devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-compaction': specifier: workspace:^ @@ -10086,7 +10086,7 @@ importers: version: 4.22.4 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -10129,7 +10129,7 @@ importers: version: 4.1.8(@opentelemetry/api@1.9.1)(@types/node@25.9.3)(@vitest/coverage-v8@4.1.8)(happy-dom@20.11.6)(jsdom@29.1.1(@noble/hashes@2.3.0))(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: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -10178,13 +10178,13 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@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/dsh-agent': specifier: workspace:^ @@ -10227,7 +10227,7 @@ importers: version: 6.0.3 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-tool-cordis': specifier: workspace:^ @@ -10246,10 +10246,10 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-loader': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/loader '@deepseek-ai/dsh-typert-registry': specifier: workspace:^ @@ -10261,7 +10261,7 @@ importers: packages/typert/protocol: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis packages/typert/registry: @@ -10271,7 +10271,7 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-typert-protocol': specifier: workspace:^ @@ -10280,13 +10280,13 @@ importers: packages/util/atomic-write: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis packages/util/brand: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis packages/util/chunked-list: @@ -10296,25 +10296,25 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis packages/util/crypto: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis packages/util/deque: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis packages/util/home-paths: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis packages/util/http-proxy: @@ -10324,7 +10324,7 @@ importers: version: 8.10.0 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -10333,49 +10333,49 @@ importers: packages/util/launch-environment: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis packages/util/native-command: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis packages/util/output-retention: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis packages/util/package-manifest: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis packages/util/time: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis packages/util/timeout: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis packages/util/values: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis packages/util/workspace-path: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis packages/web/tool-web: @@ -10394,7 +10394,7 @@ importers: version: 7.2.4 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -10443,7 +10443,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-llm': specifier: workspace:^ @@ -10462,7 +10462,7 @@ importers: version: 8.10.0 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-http-proxy': specifier: workspace:^ @@ -10481,7 +10481,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -10515,7 +10515,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-http-proxy': specifier: workspace:^ @@ -10534,7 +10534,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-http-proxy': specifier: workspace:^ @@ -10556,13 +10556,13 @@ importers: version: link:../../util/values devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@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/dsh-agent': specifier: workspace:^ @@ -10605,13 +10605,13 @@ importers: version: 14.2.0 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@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/dsh-credentials': specifier: workspace:^ @@ -10633,10 +10633,10 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/cordis-plugin-loader': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/loader '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -10685,7 +10685,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -10721,7 +10721,7 @@ importers: packages/workflow/workflow: devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -10752,7 +10752,7 @@ importers: version: link:../../../vendor/schemastery devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-agent': specifier: workspace:^ @@ -10807,7 +10807,7 @@ importers: version: 4.4.3 devDependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ @@ -10831,19 +10831,19 @@ importers: python/sdk-runtime: dependencies: '@deepseek-ai/cordis': - specifier: workspace:^ + specifier: workspace:* version: link:../../vendor/cordis '@deepseek-ai/cordis-plugin-group': - specifier: workspace:^ + specifier: workspace:* version: link:../../vendor/group '@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/cosmokit': specifier: link:../../vendor/cosmokit diff --git a/python/sdk-runtime/package.json b/python/sdk-runtime/package.json index 3a3f128cf5..12056e2255 100644 --- a/python/sdk-runtime/package.json +++ b/python/sdk-runtime/package.json @@ -5,12 +5,12 @@ "private": true, "type": "module", "dependencies": { - "@deepseek-ai/cordis": "workspace:^", - "@deepseek-ai/cordis-plugin-group": "workspace:^", - "@deepseek-ai/cordis-plugin-include": "workspace:^", - "@deepseek-ai/cordis-plugin-loader": "workspace:^", - "@deepseek-ai/cordis-plugin-timer": "workspace:^", - "@deepseek-ai/cosmokit": "workspace:^", + "@deepseek-ai/cordis": "workspace:*", + "@deepseek-ai/cordis-plugin-group": "workspace:*", + "@deepseek-ai/cordis-plugin-include": "workspace:*", + "@deepseek-ai/cordis-plugin-loader": "workspace:*", + "@deepseek-ai/cordis-plugin-timer": "workspace:*", + "@deepseek-ai/cosmokit": "workspace:*", "@deepseek-ai/dsh": "workspace:^", "@deepseek-ai/dsh-acp": "workspace:^", "@deepseek-ai/dsh-agent": "workspace:^", @@ -130,6 +130,6 @@ "@deepseek-ai/dsh-web-search-perplexity": "workspace:^", "@deepseek-ai/dsh-workflow": "workspace:^", "@deepseek-ai/dsh-workflow-worker-thread": "workspace:^", - "@deepseek-ai/schemastery": "workspace:^" + "@deepseek-ai/schemastery": "workspace:*" } } diff --git a/scripts/verify-package-dependencies.spec.ts b/scripts/verify-package-dependencies.spec.ts index 4f49bebc5d..8652d7a361 100644 --- a/scripts/verify-package-dependencies.spec.ts +++ b/scripts/verify-package-dependencies.spec.ts @@ -932,6 +932,37 @@ describe('dependency sections', () => { ])) }) + it.each([ + CORDIS, + '@deepseek-ai/cosmokit', + '@deepseek-ai/schemastery', + '@deepseek-ai/cordis-plugin-loader', + '@deepseek-ai/cordis-plugin-include', + '@deepseek-ai/cordis-plugin-group', + '@deepseek-ai/cordis-plugin-timer', + '@deepseek-ai/cordis-plugin-hmr', + '@deepseek-ai/cordis-plugin-logger-console', + ])('preserves a release-line vendor pin on %s', (name) => { + const manifest: PackageDependencyManifest = { + name: '@deepseek-ai/dsh-probe', + dependencies: { [name]: 'workspace:*' }, + devDependencies: { [CORDIS]: 'workspace:*' }, + peerDependencies: { [CORDIS]: 'workspace:*' }, + } + const base = facts(manifest) + const subject = { ...base, workspaceNames: new Set([...base.workspaceNames, name]) } + const state = { facts: [subject], packages: [], policyViolations: [], workspaceNames: subject.workspaceNames } + + repairPackageDependencyManifest(subject) + expect(manifest[name === CORDIS ? 'peerDependencies' : 'dependencies']?.[name]).toBe('workspace:*') + expect(manifest.devDependencies?.[CORDIS]).toBe('workspace:*') + expect(manifest.dependencies?.['@deepseek-ai/dsh-runtime']).toBe('workspace:^') + expect(collectPackageDependencyViolations(state)).toEqual([]) + const repaired = structuredClone(manifest) + repairPackageDependencyManifest(subject) + expect(manifest).toEqual(repaired) + }) + it('repairs owned relationships without changing unrelated dependencies', () => { const root = mkdtempSync(join(tmpdir(), 'dsh-package-dependencies-')) roots.push(root) @@ -954,7 +985,7 @@ describe('dependency sections', () => { expect(fixPackageDependencies(root, state)).toEqual([manifestPath]) const fixed = JSON.parse(readFileSync(join(root, manifestPath), 'utf8')) as PackageDependencyManifest expect(fixed.dependencies).toEqual({ - '@deepseek-ai/schemastery': 'workspace:^', + '@deepseek-ai/schemastery': 'workspace:*', external: '^1.0.0', '@deepseek-ai/dsh-runtime': 'workspace:^', }) diff --git a/scripts/verify-package-dependencies.ts b/scripts/verify-package-dependencies.ts index 537fac154a..8d04b024eb 100644 --- a/scripts/verify-package-dependencies.ts +++ b/scripts/verify-package-dependencies.ts @@ -7,6 +7,7 @@ import { dirname, extname, join, normalize, relative, resolve, sep } from 'node: import ts from 'typescript' import { WorkspaceTypertGenerator } from '../packages/typert/generator/src/workspace.ts' import { writeModuleGraph } from './gen-module-graph.ts' +import { releaseFamily } from './release/families.ts' import { hasClientDeclaration, PACKAGE_DEPENDENCY_POLICY, @@ -20,7 +21,8 @@ import { const GATE = 'verify-package-dependencies' const CORDIS = '@deepseek-ai/cordis' -const WORKSPACE_RANGE = 'workspace:^' +const VENDOR_PACKAGES = new Set(releaseFamily('vendor').members(resolve(import.meta.dirname, '..')) + .map(member => member.name)) const RELEASE_MANIFEST_GLOB = 'packages/!(experimental)/*/package.json' const WORKSPACE_MANIFEST_GLOBS = [ 'apps/*/package.json', @@ -664,6 +666,12 @@ function describeSections(sections: readonly DependencySection[]): string { return sections.length === 0 ? 'no dependency section' : sections.join(' + ') } +function workspaceRange(facts: PackageDependencyFacts, name: string): string { + const pinned = VENDOR_PACKAGES.has(name) + && declaredSections(facts.manifest, name).some(sectionName => section(facts.manifest, sectionName)[name] === 'workspace:*') + return pinned ? 'workspace:*' : 'workspace:^' +} + /** Return all manifest and policy violations in stable order. */ export function collectPackageDependencyViolations(state: PackageDependencyState): string[] { const violations = [...state.policyViolations] @@ -671,15 +679,16 @@ export function collectPackageDependencyViolations(state: PackageDependencyState for (const facts of state.facts) { for (const [name, rule] of expectedPackageDependencies(facts)) { const actual = declaredSections(facts.manifest, name) + const expectedRange = workspaceRange(facts, name) if (rule.section === 'peer-dev') { if (actual.length === 2 && actual.includes('peerDependencies') && actual.includes('devDependencies') - && section(facts.manifest, 'peerDependencies')[name] === WORKSPACE_RANGE - && section(facts.manifest, 'devDependencies')[name] === WORKSPACE_RANGE + && section(facts.manifest, 'peerDependencies')[name] === expectedRange + && section(facts.manifest, 'devDependencies')[name] === expectedRange && facts.manifest.peerDependenciesMeta?.[name] === undefined) continue violations.push( - `${facts.manifestPath}: ${name} must be matching peerDependencies + devDependencies at ${WORKSPACE_RANGE}; found ${describeSections(actual)}`, + `${facts.manifestPath}: ${name} must be matching peerDependencies + devDependencies at ${expectedRange}; found ${describeSections(actual)}`, ) continue } @@ -687,17 +696,18 @@ export function collectPackageDependencyViolations(state: PackageDependencyState const range = section(facts.manifest, expectedSection)[name] if (actual.length === 1 && actual[0] === expectedSection - && (!facts.workspaceNames.has(name) || range === WORKSPACE_RANGE)) continue + && (!facts.workspaceNames.has(name) || range === expectedRange)) continue violations.push( `${facts.manifestPath}: ${name} (${rule.origins.join(', ')}) must be ${expectedSection}-only` - + (facts.workspaceNames.has(name) ? ` at ${WORKSPACE_RANGE}` : '') + + (facts.workspaceNames.has(name) ? ` at ${expectedRange}` : '') + `; found ${describeSections(actual)}`, ) } for (const sectionName of ['dependencies', 'devDependencies', 'optionalDependencies', 'peerDependencies'] as const) { for (const [name, range] of Object.entries(section(facts.manifest, sectionName))) { - if (!facts.workspaceNames.has(name) || range === WORKSPACE_RANGE) continue - violations.push(`${facts.manifestPath}: ${sectionName}.${name} must use ${WORKSPACE_RANGE}, found ${range}`) + const expectedRange = workspaceRange(facts, name) + if (!facts.workspaceNames.has(name) || range === expectedRange) continue + violations.push(`${facts.manifestPath}: ${sectionName}.${name} must use ${expectedRange}, found ${range}`) } } for (const name of Object.keys(facts.manifest.peerDependenciesMeta ?? {})) { @@ -742,7 +752,7 @@ function preferredRange( name: string, target: ExpectedPackageDependency['section'], ): string { - if (name === CORDIS || facts.workspaceNames.has(name)) return WORKSPACE_RANGE + if (name === CORDIS || facts.workspaceNames.has(name)) return workspaceRange(facts, name) const order: readonly DependencySection[] = target === 'dependencies' ? ['dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies'] : ['devDependencies', 'peerDependencies', 'dependencies', 'optionalDependencies'] @@ -767,8 +777,8 @@ export function repairPackageDependencyManifest(facts: PackageDependencyFacts): for (const sectionName of ['dependencies', 'optionalDependencies'] as const) { deleteDependency(facts.manifest, sectionName, name) } - mutableSection(facts.manifest, 'peerDependencies')[name] = WORKSPACE_RANGE - mutableSection(facts.manifest, 'devDependencies')[name] = WORKSPACE_RANGE + mutableSection(facts.manifest, 'peerDependencies')[name] = range + mutableSection(facts.manifest, 'devDependencies')[name] = range deletePeerMeta(facts.manifest, name) continue } @@ -783,7 +793,7 @@ export function repairPackageDependencyManifest(facts: PackageDependencyFacts): } for (const sectionName of ['dependencies', 'devDependencies', 'optionalDependencies', 'peerDependencies'] as const) { for (const name of Object.keys(section(facts.manifest, sectionName))) { - if (facts.workspaceNames.has(name)) mutableSection(facts.manifest, sectionName)[name] = WORKSPACE_RANGE + if (facts.workspaceNames.has(name)) mutableSection(facts.manifest, sectionName)[name] = workspaceRange(facts, name) } } } From 8e7cca22ca5174eda1404511a829d38878ee4103 Mon Sep 17 00:00:00 2001 From: imccyu Date: Tue, 22 Sep 2026 13:08:07 +0800 Subject: [PATCH 09/29] release(dsh): 0.1.5-rc.3 --- apps/cli/package.json | 2 +- apps/desktop-host/package.json | 2 +- apps/desktop/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/api/session-controller/package.json | 2 +- packages/api/settings-controller/package.json | 2 +- packages/api/workspace-controller/package.json | 2 +- packages/api/workspace-files/package.json | 2 +- packages/attachment/attachment-local/package.json | 2 +- packages/attachment/attachment/package.json | 2 +- packages/boot/app-boot/package.json | 2 +- packages/boot/cmdline/package.json | 2 +- packages/bundle/acp-app/package.json | 2 +- packages/bundle/base/package.json | 2 +- packages/bundle/headless/package.json | 2 +- packages/bundle/sdk-app/package.json | 2 +- packages/bundle/sdk-minimal/package.json | 2 +- packages/bundle/web-app/package.json | 2 +- packages/client/connection/package.json | 2 +- packages/client/file-upload/package.json | 2 +- packages/client/hmr/package.json | 2 +- packages/client/locale/package.json | 2 +- packages/client/modules/package.json | 2 +- packages/client/resources/package.json | 2 +- packages/client/store/package.json | 2 +- packages/client/ui-agent-preset/package.json | 2 +- packages/client/ui-approval/package.json | 2 +- packages/client/ui-attachment/package.json | 2 +- packages/client/ui-brand-official/package.json | 2 +- packages/client/ui-chat/package.json | 2 +- packages/client/ui-commands/package.json | 2 +- packages/client/ui-conversation/package.json | 2 +- packages/client/ui-deliverables/package.json | 2 +- packages/client/ui-directory-picker-browse/package.json | 2 +- packages/client/ui-directory-picker-native/package.json | 2 +- packages/client/ui-dockkit/package.json | 2 +- packages/client/ui-goal/package.json | 2 +- packages/client/ui-input-trigger/package.json | 2 +- packages/client/ui-jobs/package.json | 2 +- packages/client/ui-layout/package.json | 2 +- packages/client/ui-message-feedback/package.json | 2 +- packages/client/ui-model-selection/package.json | 2 +- packages/client/ui-open-in-app/package.json | 2 +- packages/client/ui-permission-presets/package.json | 2 +- packages/client/ui-plan/package.json | 2 +- packages/client/ui-primitives/package.json | 2 +- packages/client/ui-reference/package.json | 2 +- packages/client/ui-renderer/package.json | 2 +- packages/client/ui-schedule/package.json | 2 +- packages/client/ui-session/package.json | 2 +- packages/client/ui-settings-general/package.json | 2 +- packages/client/ui-settings-models/package.json | 2 +- packages/client/ui-settings-plugin-inventory/package.json | 2 +- packages/client/ui-settings-plugins/package.json | 2 +- packages/client/ui-settings/package.json | 2 +- packages/client/ui-sidebar-documentpreview/package.json | 2 +- packages/client/ui-sidebar-files/package.json | 2 +- packages/client/ui-sidebar-right/package.json | 2 +- packages/client/ui-sidebar/package.json | 2 +- packages/client/ui-skill/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-user-questions/package.json | 2 +- packages/client/ui-workflow-run/package.json | 2 +- packages/client/ui-workspace/package.json | 2 +- packages/client/web/package.json | 2 +- packages/code-runtime/code-runtime-worker-thread/package.json | 2 +- packages/code-runtime/code-runtime/package.json | 2 +- packages/compaction/command-compact/package.json | 2 +- packages/compaction/compaction-basic/package.json | 2 +- packages/compaction/compaction-tool-result-pruner/package.json | 2 +- packages/compaction/compaction/package.json | 2 +- packages/context/agent-instructions/package.json | 2 +- packages/context/file-reference-local/package.json | 2 +- packages/context/file-reference/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/core/agent-default-model/package.json | 2 +- packages/core/agent-loop/package.json | 2 +- packages/core/agent-tool-presentation/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/authorization/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/experimental/agent-team-profile/package.json | 2 +- packages/experimental/agent-team-web-profile/package.json | 2 +- packages/experimental/agent-team/package.json | 2 +- packages/experimental/client-ui-agent-team/package.json | 2 +- packages/experimental/code-runtime-python/package.json | 2 +- packages/experimental/inspector/package.json | 2 +- packages/experimental/tool-agent-team/package.json | 2 +- packages/experimental/webworker-packer/package.json | 2 +- packages/experimental/webworker-runtime/package.json | 2 +- packages/extensions/cordis-client-runner/package.json | 2 +- packages/extensions/cordis-host-runner/package.json | 2 +- packages/extensions/tool-cordis/package.json | 2 +- packages/extensions/ui-cordis/package.json | 2 +- packages/feedback/command-feedback/package.json | 2 +- packages/feedback/message-feedback/package.json | 2 +- packages/fs/fs-local/package.json | 2 +- packages/fs/fs-observation-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-present/package.json | 2 +- packages/fs/tool-str-replace-editor/package.json | 2 +- packages/goal/command-goal/package.json | 2 +- packages/goal/goal-round-driver/package.json | 2 +- packages/goal/goal/package.json | 2 +- packages/goal/tool-goal/package.json | 2 +- packages/guard/repeat-tool-reminder/package.json | 2 +- packages/guard/timeout-policy/package.json | 2 +- packages/hooks/hook-protocol/package.json | 2 +- packages/hooks/hooks-claude-code/package.json | 2 +- packages/hooks/hooks-codex/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/open-in-app/package.json | 2 +- packages/host/plugin-inventory/package.json | 2 +- packages/host/webserver/package.json | 2 +- packages/identity/anonymous-user-id/package.json | 2 +- packages/interaction/commands/package.json | 2 +- packages/interaction/permission-presets/package.json | 2 +- packages/interaction/tool-ask-user/package.json | 2 +- packages/interaction/user-approval/package.json | 2 +- packages/interaction/user-questions/package.json | 2 +- packages/jobs/jobs-local/package.json | 2 +- packages/jobs/jobs/package.json | 2 +- packages/jobs/tool-jobs/package.json | 2 +- packages/llm/deepseek-llm-api-extensions/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/plugin-package-inventory-deepseek/package.json | 2 +- packages/llm/token-meter/package.json | 2 +- packages/lsp/lsp-stdio/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/runtime-diagnostics/invariants/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/schedule/schedule/package.json | 2 +- packages/sdk/client/package.json | 2 +- packages/sdk/protocol/package.json | 2 +- packages/sdk/server/package.json | 2 +- packages/session-query/session-log-export/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-format-catalog/package.json | 2 +- packages/session/session-format-v0-to-v1/package.json | 2 +- packages/session/session-format-v1-to-v2/package.json | 2 +- packages/session/session-format-v2-to-v3/package.json | 2 +- packages/session/session-format/package.json | 2 +- packages/session/session-log-deepseek/package.json | 2 +- packages/session/session-persistence-jsonl/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-stats/package.json | 2 +- packages/session/session-telemetry-otel/package.json | 2 +- packages/session/session-telemetry/package.json | 2 +- packages/session/session-title-all-prompts-llm/package.json | 2 +- packages/session/session-title-first-prompt-llm/package.json | 2 +- packages/session/session-title-llm/package.json | 2 +- packages/session/session-title/package.json | 2 +- packages/session/session-turn-outline/package.json | 2 +- packages/settings/settings-file/package.json | 2 +- packages/settings/settings/package.json | 2 +- packages/shell/bash-local/package.json | 2 +- packages/shell/bash-sandbox/package.json | 2 +- packages/shell/pwsh-local/package.json | 2 +- packages/shell/pwsh-sandbox/package.json | 2 +- packages/shell/shell-env/package.json | 2 +- packages/shell/shell/package.json | 2 +- packages/shell/tool-bash-persistent/package.json | 2 +- packages/shell/tool-bash/package.json | 2 +- packages/shell/tool-pwsh-persistent/package.json | 2 +- packages/shell/tool-pwsh/package.json | 2 +- packages/skill/skill-badge/package.json | 2 +- packages/skill/skill-filesystem/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-in-process/package.json | 2 +- packages/subagent/subagent-in-process-driver/package.json | 2 +- packages/subagent/subagent-spawn-in-process/package.json | 2 +- packages/subagent/subagent/package.json | 2 +- packages/subagent/tool-subagent-control/package.json | 2 +- packages/subagent/tool-subagent/package.json | 2 +- packages/subprocess/subprocess-local/package.json | 2 +- packages/subprocess/subprocess/package.json | 2 +- packages/subprocess/win32-process/package.json | 2 +- packages/terminal/terminal-bash/package.json | 2 +- packages/terminal/terminal/package.json | 2 +- packages/terminal/tool-terminal/package.json | 2 +- packages/test-support/agent-loop-testkit/package.json | 2 +- packages/test-support/client-runtime/package.json | 2 +- packages/test-support/llm-mock-server/package.json | 2 +- packages/test-support/llm-replay/package.json | 2 +- packages/test-support/loader-smoke/package.json | 2 +- packages/test-support/session-snapshot/package.json | 2 +- packages/todo/tool-todo/package.json | 2 +- packages/typert/generator/package.json | 2 +- packages/typert/loader/package.json | 2 +- packages/typert/protocol/package.json | 2 +- packages/typert/registry/package.json | 2 +- packages/util/atomic-write/package.json | 2 +- packages/util/brand/package.json | 2 +- packages/util/chunked-list/package.json | 2 +- packages/util/crypto/package.json | 2 +- packages/util/deque/package.json | 2 +- packages/util/home-paths/package.json | 2 +- packages/util/http-proxy/package.json | 2 +- packages/util/launch-environment/package.json | 2 +- packages/util/native-command/package.json | 2 +- packages/util/output-retention/package.json | 2 +- packages/util/package-manifest/package.json | 2 +- packages/util/time/package.json | 2 +- packages/util/timeout/package.json | 2 +- packages/util/values/package.json | 2 +- packages/util/workspace-path/package.json | 2 +- packages/web/tool-web/package.json | 2 +- packages/web/web-fetch-http/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/webhook/webhook-github/package.json | 2 +- packages/webhook/webhook/package.json | 2 +- packages/workflow/tool-ralph/package.json | 2 +- packages/workflow/tool-workflow/package.json | 2 +- packages/workflow/workflow-worker-thread/package.json | 2 +- packages/workflow/workflow/package.json | 2 +- packages/workspace/workspace/package.json | 2 +- 272 files changed, 272 insertions(+), 272 deletions(-) diff --git a/apps/cli/package.json b/apps/cli/package.json index b265db2e3e..52b399f15e 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/apps/desktop-host/package.json b/apps/desktop-host/package.json index 99eb2b4904..06e557d113 100644 --- a/apps/desktop-host/package.json +++ b/apps/desktop-host/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-desktop-host", "description": "Private upstream-Node host process for the Electron desktop application", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "private": true, "license": "MIT", "type": "module", diff --git a/apps/desktop/package.json b/apps/desktop/package.json index f414377a20..3b2cca5aa4 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-desktop", "description": "Electron desktop shell for an isolated pnpm-installed dsh runtime", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "private": true, "license": "MIT", "type": "module", diff --git a/apps/web/package.json b/apps/web/package.json index 50e6e88070..0ff4d574c2 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-web-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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/package.json b/package.json index a9b7c19269..a084efa26d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@deepseek-ai/dsh-root", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "license": "MIT", "private": true, "type": "module", diff --git a/packages/acp/acp/package.json b/packages/acp/acp/package.json index 3bf01229ec..2b7690eb2a 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/api/gateway/package.json b/packages/api/gateway/package.json index 03dbbc8245..57d9808f69 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/api/remotes/package.json b/packages/api/remotes/package.json index 1415ffdc5f..d0d938f9a2 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 for application-selected Host capabilities", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/api/session-controller/package.json b/packages/api/session-controller/package.json index f8378d4010..2220e2e850 100644 --- a/packages/api/session-controller/package.json +++ b/packages/api/session-controller/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-api-session-controller", "description": "Session Remote commands, cold reads, and live control transport", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/api/settings-controller/package.json b/packages/api/settings-controller/package.json index 28caa71fed..4192d1a695 100644 --- a/packages/api/settings-controller/package.json +++ b/packages/api/settings-controller/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-api-settings-controller", "description": "Remote owner for the configuration surfaces over the settings-domain seams", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/api/workspace-controller/package.json b/packages/api/workspace-controller/package.json index dc6691b4f9..5bd395714a 100644 --- a/packages/api/workspace-controller/package.json +++ b/packages/api/workspace-controller/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-api-workspace-controller", "description": "Workspace Remote commands and reconnect-safe state transport", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/api/workspace-files/package.json b/packages/api/workspace-files/package.json index 9592cc40be..e826c71916 100644 --- a/packages/api/workspace-files/package.json +++ b/packages/api/workspace-files/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-api-workspace-files", "description": "Workspace file service and Client resource provider: bounded reads, directory listing, and live metadata over the workspaceFiles Remote namespace", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/attachment/attachment-local/package.json b/packages/attachment/attachment-local/package.json index 8e4f2850b4..22173c3d69 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/attachment/attachment/package.json b/packages/attachment/attachment/package.json index 8bfc20cb06..998bd16964 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/boot/app-boot/package.json b/packages/boot/app-boot/package.json index c4b1a011e7..0b00676ff1 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/boot/cmdline/package.json b/packages/boot/cmdline/package.json index 57c18c4452..878c7e33fd 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/bundle/acp-app/package.json b/packages/bundle/acp-app/package.json index 01b4862970..f7f61f84da 100644 --- a/packages/bundle/acp-app/package.json +++ b/packages/bundle/acp-app/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-acp-app", "description": "The dsh ACP profile bundle: automation-only JSON-RPC stdio and process lifecycle over dsh-base", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/bundle/base/package.json b/packages/bundle/base/package.json index 5a6e059e55..d796aba27b 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: the first patch layer of base-backed profiles, inserting core rows over the empty profile root", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/bundle/headless/package.json b/packages/bundle/headless/package.json index 46b1f112f4..5d650eca9a 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/bundle/sdk-app/package.json b/packages/bundle/sdk-app/package.json index 20f002c9a4..7c321347cb 100644 --- a/packages/bundle/sdk-app/package.json +++ b/packages/bundle/sdk-app/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-sdk-app", "description": "The dsh SDK profile bundle: stdio JSON-RPC serving and process lifecycle over dsh-base", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/bundle/sdk-minimal/package.json b/packages/bundle/sdk-minimal/package.json index 5208226eac..e91fc03db8 100644 --- a/packages/bundle/sdk-minimal/package.json +++ b/packages/bundle/sdk-minimal/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-sdk-minimal", "description": "The standalone minimal SDK profile bundle: JSON-RPC, one DeepSeek adapter, persistent shell, and JSONL sessions", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/bundle/web-app/package.json b/packages/bundle/web-app/package.json index 2392881d50..2f38466c40 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/client/connection/package.json b/packages/client/connection/package.json index dab23d2d88..1eeda4bd6d 100644 --- a/packages/client/connection/package.json +++ b/packages/client/connection/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-connection", "description": "Authenticated RPC transport, generation lifecycle, and browser fixture", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/client/file-upload/package.json b/packages/client/file-upload/package.json index 0b3f35d369..b669fbe4d8 100644 --- a/packages/client/file-upload/package.json +++ b/packages/client/file-upload/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-file-upload", "description": "Agent-scoped browser file upload, streaming intake, and staged receipt service", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/client/hmr/package.json b/packages/client/hmr/package.json index 05ab26abea..c033186f37 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/client/locale/package.json b/packages/client/locale/package.json index bf980b6fb9..5c3974a574 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 preference, extensible language catalog, browser fallback, and typed built-in dictionaries", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/client/modules/package.json b/packages/client/modules/package.json index ed5f826661..e755ac7a24 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/client/resources/package.json b/packages/client/resources/package.json index 689f352ede..551c20811a 100644 --- a/packages/client/resources/package.json +++ b/packages/client/resources/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-resources", "description": "Unified client resource model: protocol-registered providers turn URL addresses into live values, consumed through the useResource global standard hook", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/client/store/package.json b/packages/client/store/package.json index 00bc212768..ab9f1e9056 100644 --- a/packages/client/store/package.json +++ b/packages/client/store/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-store", "description": "React-free observable and snapshot-store contracts with the shared Zustand/Immer engine", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/client/ui-agent-preset/package.json b/packages/client/ui-agent-preset/package.json index 6d072209e3..ce349095a5 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/client/ui-approval/package.json b/packages/client/ui-approval/package.json index 86ecffb2ff..75293548d5 100644 --- a/packages/client/ui-approval/package.json +++ b/packages/client/ui-approval/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-approval", "description": "Approval composer takeover over the scoped Remote Event waterfall", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/client/ui-attachment/package.json b/packages/client/ui-attachment/package.json index 6e19205536..c47e3ed081 100644 --- a/packages/client/ui-attachment/package.json +++ b/packages/client/ui-attachment/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-attachment", "description": "Dynamic attachment presentation plugin for conversation input, message-image, and trajectory image slots", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/client/ui-brand-official/package.json b/packages/client/ui-brand-official/package.json index 6a1af745e0..112ca4ea98 100644 --- a/packages/client/ui-brand-official/package.json +++ b/packages/client/ui-brand-official/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-brand-official", "description": "Official DeepSeek Harness brand occupants for the Web client's sidebar slots", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/client/ui-chat/package.json b/packages/client/ui-chat/package.json index f62bf82962..4e299904f1 100644 --- a/packages/client/ui-chat/package.json +++ b/packages/client/ui-chat/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-chat", "description": "Chat Conversation target, node definitions, renderers, and details surface", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/client/ui-commands/package.json b/packages/client/ui-commands/package.json index a058e1b14f..5ac75b0482 100644 --- a/packages/client/ui-commands/package.json +++ b/packages/client/ui-commands/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-commands", "description": "Client command surface: global directory cache, '/' source, three command UI kinds, popupSelect registry", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/client/ui-conversation/package.json b/packages/client/ui-conversation/package.json index 8628f0b603..fa62be4830 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": "Target-neutral Conversation assembly, shell, composer, queue, and view navigation", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/client/ui-deliverables/package.json b/packages/client/ui-deliverables/package.json index f9160c942e..53a2eff6b6 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 and clickable final-response file references for Web", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/client/ui-directory-picker-browse/package.json b/packages/client/ui-directory-picker-browse/package.json index 24cfcb3575..bb68eb79a3 100644 --- a/packages/client/ui-directory-picker-browse/package.json +++ b/packages/client/ui-directory-picker-browse/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-directory-picker-browse", "description": "In-app directory browsing surface: the workspace directory-flow owner rendering the host's listing and creation primitives", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/client/ui-directory-picker-native/package.json b/packages/client/ui-directory-picker-native/package.json index 7ed364f0ce..6f5a996c5a 100644 --- a/packages/client/ui-directory-picker-native/package.json +++ b/packages/client/ui-directory-picker-native/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-directory-picker-native", "description": "Native directory-picker surface: the renderless workspace directory-flow occupant driving the host's OS chooser", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/client/ui-dockkit/package.json b/packages/client/ui-dockkit/package.json index d64cb583b8..6766973b6f 100644 --- a/packages/client/ui-dockkit/package.json +++ b/packages/client/ui-dockkit/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-dockkit", "description": "Docking layout kit: split-tree engine with invertible operations, and the React components that render and drive it (zero cordis)", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/client/ui-goal/package.json b/packages/client/ui-goal/package.json index 371fc27b12..01d22201f1 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/client/ui-input-trigger/package.json b/packages/client/ui-input-trigger/package.json index 4af96ec488..f8c021db93 100644 --- a/packages/client/ui-input-trigger/package.json +++ b/packages/client/ui-input-trigger/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-input-trigger", "description": "Input trigger pipeline: '/' and '@' detection, candidate menu, pick routing to registered sources", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/client/ui-jobs/package.json b/packages/client/ui-jobs/package.json index e6668f556c..a691e9c053 100644 --- a/packages/client/ui-jobs/package.json +++ b/packages/client/ui-jobs/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-jobs", "description": "Session-header background-job list: live registry state mirrored from session/jobs frames", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "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 7ab0b24dcf..bf0d77ba88 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/client/ui-message-feedback/package.json b/packages/client/ui-message-feedback/package.json index c589cd4c23..3ecce41bed 100644 --- a/packages/client/ui-message-feedback/package.json +++ b/packages/client/ui-message-feedback/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-message-feedback", "description": "The Web feedback surface: per-message Like/Dislike in the assistant-message action strip and the feedback dialog behind both ratings and /feedback, backed by the messageFeedback and sessionFeedback Host Remotes", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/client/ui-model-selection/package.json b/packages/client/ui-model-selection/package.json index 463be8cc2d..9120ba1db1 100644 --- a/packages/client/ui-model-selection/package.json +++ b/packages/client/ui-model-selection/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-model-selection", "description": "Model selection over the shared model catalog, Session projection, and session.selectModel", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/client/ui-open-in-app/package.json b/packages/client/ui-open-in-app/package.json index 0c726ef252..7d08fbcfe9 100644 --- a/packages/client/ui-open-in-app/package.json +++ b/packages/client/ui-open-in-app/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-open-in-app", "description": "Web Session-header \"Open In...\" split button opening the session workspace directory in a locally installed application", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/client/ui-permission-presets/package.json b/packages/client/ui-permission-presets/package.json index 21aaaba411..b5b56a346d 100644 --- a/packages/client/ui-permission-presets/package.json +++ b/packages/client/ui-permission-presets/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-permission-presets", "description": "Permission surfaces: a new-session default in General settings and a current-session /permission popup over the permissions projection", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/client/ui-plan/package.json b/packages/client/ui-plan/package.json index 596adb6ee0..7da05fb9de 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/client/ui-primitives/package.json b/packages/client/ui-primitives/package.json index 70f7fba6cb..f9a0a9726f 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/client/ui-reference/package.json b/packages/client/ui-reference/package.json index 4c00e9d339..f5aa167243 100644 --- a/packages/client/ui-reference/package.json +++ b/packages/client/ui-reference/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-reference", "description": "Unified Web @file and @session reference source", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/client/ui-renderer/package.json b/packages/client/ui-renderer/package.json index 99272ba2ea..0b94dd78a8 100644 --- a/packages/client/ui-renderer/package.json +++ b/packages/client/ui-renderer/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-renderer", "description": "Browser UI renderer: React slot bindings, ctx.uiRenderer, and the assembled application root", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/client/ui-schedule/package.json b/packages/client/ui-schedule/package.json index a0f43a1da0..9c7aa82ce2 100644 --- a/packages/client/ui-schedule/package.json +++ b/packages/client/ui-schedule/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-schedule", "description": "Read-only active Schedule catalog in the Web Session header", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/packages/client/ui-session/package.json b/packages/client/ui-session/package.json index c4430b80df..fc3fc1669b 100644 --- a/packages/client/ui-session/package.json +++ b/packages/client/ui-session/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-session", "description": "Session Controller adapter for React and session-scoped slots", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/client/ui-settings-general/package.json b/packages/client/ui-settings-general/package.json index 2c4ce21271..f25443df03 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/client/ui-settings-models/package.json b/packages/client/ui-settings-models/package.json index b8195de272..2be454a33e 100644 --- a/packages/client/ui-settings-models/package.json +++ b/packages/client/ui-settings-models/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-settings-models", "description": "Models settings and shared product-onboarding dialogs over existing settings and credential joins", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/client/ui-settings-plugin-inventory/package.json b/packages/client/ui-settings-plugin-inventory/package.json index f7b778f8ab..404b28be0c 100644 --- a/packages/client/ui-settings-plugin-inventory/package.json +++ b/packages/client/ui-settings-plugin-inventory/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-settings-plugin-inventory", "description": "Read-only Cordis Loader inventory tab in Web Plugins settings", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/client/ui-settings-plugins/package.json b/packages/client/ui-settings-plugins/package.json index c442b85e1d..66806f3de3 100644 --- a/packages/client/ui-settings-plugins/package.json +++ b/packages/client/ui-settings-plugins/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-settings-plugins", "description": "Plugins settings section with feature-owned tabs and configurable host-plane plugin cards", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/client/ui-settings/package.json b/packages/client/ui-settings/package.json index 77e3121444..72c431cbc6 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 domain base plugin: the settings-namespace scope service and the canonical settings slot-type contract", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/client/ui-sidebar-documentpreview/package.json b/packages/client/ui-sidebar-documentpreview/package.json index 6dff631937..9b6c2015ae 100644 --- a/packages/client/ui-sidebar-documentpreview/package.json +++ b/packages/client/ui-sidebar-documentpreview/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-sidebar-documentpreview", "description": "Extensible document previews for Sidebar files: Markdown, highlighted code, images, PDF, HTML, and plain text", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/client/ui-sidebar-files/package.json b/packages/client/ui-sidebar-files/package.json index 2da4742959..4a768030ec 100644 --- a/packages/client/ui-sidebar-files/package.json +++ b/packages/client/ui-sidebar-files/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-sidebar-files", "description": "Workspace file tree tab type for the right Sidebar: lazy directory listing over the workspaceFiles Remote namespace, opening files into the Sidebar", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/client/ui-sidebar-right/package.json b/packages/client/ui-sidebar-right/package.json index ab8a79d601..f6800423a9 100644 --- a/packages/client/ui-sidebar-right/package.json +++ b/packages/client/ui-sidebar-right/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-sidebar-right", "description": "Right Sidebar: the docking surface's session-bound state, its panel and header expand control, and the navigation service over it", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/client/ui-sidebar/package.json b/packages/client/ui-sidebar/package.json index c15eb7aa15..2c15372562 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/client/ui-skill/package.json b/packages/client/ui-skill/package.json index faad887629..daa9ae2e3e 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/client/ui-slots/package.json b/packages/client/ui-slots/package.json index c4e442da26..3649e07ef0 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/client/ui-subagent/package.json b/packages/client/ui-subagent/package.json index a25900dea8..b375b77559 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/client/ui-theme/package.json b/packages/client/ui-theme/package.json index eca96065c0..0614f4c62c 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: Host bootstrap for the pre-plugin palette; DOM-free ThemeRuntime for light/dark/system state; --dsw-* token styles and Appearance settings row", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/client/ui-tool/package.json b/packages/client/ui-tool/package.json index 11ddae1f81..3135041778 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/client/ui-trajectory/package.json b/packages/client/ui-trajectory/package.json index 32e664d600..6f2c2fae06 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/client/ui-user-questions/package.json b/packages/client/ui-user-questions/package.json index 2c8e881b99..adf9809890 100644 --- a/packages/client/ui-user-questions/package.json +++ b/packages/client/ui-user-questions/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-user-questions", "description": "Web ask_user_question composer takeover and plan-review presentation UI", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/client/ui-workflow-run/package.json b/packages/client/ui-workflow-run/package.json index 98a545b350..a80befef1e 100644 --- a/packages/client/ui-workflow-run/package.json +++ b/packages/client/ui-workflow-run/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-workflow-run", "description": "Durable workflow-run Conversation Node and nested member disclosure for dsh web", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/client/ui-workspace/package.json b/packages/client/ui-workspace/package.json index 96f844a25b..b39247b7b5 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/client/web/package.json b/packages/client/web/package.json index 07f0783d0f..b733898664 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 boot kernel: static module table, Cordis loader, framework-free boot page, and UI-renderer handoff", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/code-runtime/code-runtime-worker-thread/package.json b/packages/code-runtime/code-runtime-worker-thread/package.json index 9491b8e996..6a35870ae1 100644 --- a/packages/code-runtime/code-runtime-worker-thread/package.json +++ b/packages/code-runtime/code-runtime-worker-thread/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-code-runtime-worker-thread", "description": "Worker-thread implementation of the DeepSeek Harness code-execution seam", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/code-runtime/code-runtime/package.json b/packages/code-runtime/code-runtime/package.json index 070c598183..3222db8a1e 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/compaction/command-compact/package.json b/packages/compaction/command-compact/package.json index de807314c1..ec8f75a087 100644 --- a/packages/compaction/command-compact/package.json +++ b/packages/compaction/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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/compaction/compaction-basic/package.json b/packages/compaction/compaction-basic/package.json index 60eac2756d..0c31e6db3d 100644 --- a/packages/compaction/compaction-basic/package.json +++ b/packages/compaction/compaction-basic/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-compaction-basic", "description": "Token-meter-driven compaction policy and LLM summarization backend for the DeepSeek Harness", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/compaction/compaction-tool-result-pruner/package.json b/packages/compaction/compaction-tool-result-pruner/package.json index d163cc7f2b..b89920b5e0 100644 --- a/packages/compaction/compaction-tool-result-pruner/package.json +++ b/packages/compaction/compaction-tool-result-pruner/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-compaction-tool-result-pruner", "description": "Replay-safe model-free head/middle/tail pruning for tool-result surface nodes", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/compaction/compaction/package.json b/packages/compaction/compaction/package.json index 8d21374edb..7a5e2c016d 100644 --- a/packages/compaction/compaction/package.json +++ b/packages/compaction/compaction/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-compaction", "description": "Abstract compaction service seam (ctx.compaction) for the DeepSeek Harness", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/context/agent-instructions/package.json b/packages/context/agent-instructions/package.json index 1531f9a2b3..7f91f9e737 100644 --- a/packages/context/agent-instructions/package.json +++ b/packages/context/agent-instructions/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-agent-instructions", "description": "Workspace context loader for AGENTS.md/CLAUDE.md instruction files", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/context/file-reference-local/package.json b/packages/context/file-reference-local/package.json index 90b4656d9f..b206a114b7 100644 --- a/packages/context/file-reference-local/package.json +++ b/packages/context/file-reference-local/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-file-reference-local", "description": "Local-filesystem ctx.fileReferences provider with bounded fuzzy indexes", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/context/file-reference/package.json b/packages/context/file-reference/package.json index f0334f1da6..fd20d1345b 100644 --- a/packages/context/file-reference/package.json +++ b/packages/context/file-reference/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-file-reference", "description": "File-reference discovery contract and shared @file grammar", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/context/session-reference/package.json b/packages/context/session-reference/package.json index 3b89b9786e..c6c284cfdd 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.sessionReferenceResolver)", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/context/time-context/package.json b/packages/context/time-context/package.json index fcbdda6b7b..1b9caf48bb 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/context/tmux-context/package.json b/packages/context/tmux-context/package.json index b1021c6215..9aa3ce7754 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/core/agent-default-model/package.json b/packages/core/agent-default-model/package.json index ade673f6d5..67ec3ea087 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/core/agent-loop/package.json b/packages/core/agent-loop/package.json index 5091fddbdd..3377b1f571 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/core/agent-tool-presentation/package.json b/packages/core/agent-tool-presentation/package.json index 5bc00141ab..86a610b01b 100644 --- a/packages/core/agent-tool-presentation/package.json +++ b/packages/core/agent-tool-presentation/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-agent-tool-presentation", "description": "Agent-plane presentation selector: composes one agent's tools as PTC mode, native, or both", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/core/agent/package.json b/packages/core/agent/package.json index f85e083ab8..a8ef1afde9 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/core/scope/package.json b/packages/core/scope/package.json index 268e0fdbe9..5c1cbeb8f3 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/core/session/package.json b/packages/core/session/package.json index 4215779d0c..1284d1424a 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/core/system-prompt/package.json b/packages/core/system-prompt/package.json index 8ec4194a77..81c499b85e 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/core/tools/package.json b/packages/core/tools/package.json index 0e37581818..1fcf3d05c6 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/credentials/authorization/package.json b/packages/credentials/authorization/package.json index 76e5b79cef..183c4ff143 100644 --- a/packages/credentials/authorization/package.json +++ b/packages/credentials/authorization/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-authorization", "description": "Authorization seam (ctx.authorization): plugin-owned flows that obtain a credential through a conversation with the human", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/credentials/credentials-local/package.json b/packages/credentials/credentials-local/package.json index c7d7d2128a..0f0eaabbba 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/credentials/credentials/package.json b/packages/credentials/credentials/package.json index bc5c80beb8..d188ac80d1 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/e2b/e2b/package.json b/packages/e2b/e2b/package.json index 602ed51b2c..ad316adbe8 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/e2b/fs-e2b/package.json b/packages/e2b/fs-e2b/package.json index 6f989f2b8a..dc46ee8a09 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/e2b/subprocess-e2b/package.json b/packages/e2b/subprocess-e2b/package.json index c6a7342657..bc1544812b 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/experimental/agent-team-profile/package.json b/packages/experimental/agent-team-profile/package.json index 1414ef126c..51454847cf 100644 --- a/packages/experimental/agent-team-profile/package.json +++ b/packages/experimental/agent-team-profile/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-experimental-agent-team-profile", "description": "Experimental profile bundle enabling Agent Teams over dsh-base", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/experimental/agent-team-web-profile/package.json b/packages/experimental/agent-team-web-profile/package.json index 1bd3692f3e..55c95e5d72 100644 --- a/packages/experimental/agent-team-web-profile/package.json +++ b/packages/experimental/agent-team-web-profile/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-experimental-agent-team-web-profile", "description": "Experimental Web profile layer for Agent Teams Remote and UI plugins", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/experimental/agent-team/package.json b/packages/experimental/agent-team/package.json index c15441b1a7..bfe664f644 100644 --- a/packages/experimental/agent-team/package.json +++ b/packages/experimental/agent-team/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-experimental-agent-team", "description": "Implicit-root Agent Teams roster, durable peer mailbox, and shared task DAG", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/experimental/client-ui-agent-team/package.json b/packages/experimental/client-ui-agent-team/package.json index 563a2c7a75..aec4ee7f17 100644 --- a/packages/experimental/client-ui-agent-team/package.json +++ b/packages/experimental/client-ui-agent-team/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-experimental-client-ui-agent-team", "description": "Web Agent Teams roster, task board, and teammate navigation", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/experimental/code-runtime-python/package.json b/packages/experimental/code-runtime-python/package.json index ceaa310bdf..1c2cfd1011 100644 --- a/packages/experimental/code-runtime-python/package.json +++ b/packages/experimental/code-runtime-python/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-experimental-code-runtime-python", "description": "CPython subprocess implementation of the DeepSeek Harness code-execution seam", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "repository": { "type": "git", "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", diff --git a/packages/experimental/inspector/package.json b/packages/experimental/inspector/package.json index fe46f14acc..5c1e429a95 100644 --- a/packages/experimental/inspector/package.json +++ b/packages/experimental/inspector/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-experimental-inspector", "description": "Experimental cross-realm CDP hub for Host debugging and Client Runtime inspection", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "private": true, "repository": { "type": "git", diff --git a/packages/experimental/tool-agent-team/package.json b/packages/experimental/tool-agent-team/package.json index 7f08e60b07..6d2e2c0698 100644 --- a/packages/experimental/tool-agent-team/package.json +++ b/packages/experimental/tool-agent-team/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-experimental-tool-agent-team", "description": "Scoped model-facing Agent Teams tools over ctx.agentTeams", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/experimental/webworker-packer/package.json b/packages/experimental/webworker-packer/package.json index a98d0e2064..419bb0e33b 100644 --- a/packages/experimental/webworker-packer/package.json +++ b/packages/experimental/webworker-packer/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-experimental-webworker-packer", "description": "Build-time packer for the browser runtime's base VFS image and ordered data-overlay archives", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "private": true, "repository": { "type": "git", diff --git a/packages/experimental/webworker-runtime/package.json b/packages/experimental/webworker-runtime/package.json index ac04c0d104..d667ddbd1c 100644 --- a/packages/experimental/webworker-runtime/package.json +++ b/packages/experimental/webworker-runtime/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-experimental-webworker-runtime", "description": "Browser-only harness runtime: in-memory VFS, module transform and loader, postMessage tunnel, and the dedicated Web Worker assembly, with the Node-compatibility layer that lets the host tree run unchanged", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "private": true, "repository": { "type": "git", diff --git a/packages/extensions/cordis-client-runner/package.json b/packages/extensions/cordis-client-runner/package.json index ceb94aeaed..32b00e97d6 100644 --- a/packages/extensions/cordis-client-runner/package.json +++ b/packages/extensions/cordis-client-runner/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-cordis-client-runner", "description": "Browser half of dynamic dual-half plugin packages: event subscription, closure evaluation, guard facade, and loader entries", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/extensions/cordis-host-runner/package.json b/packages/extensions/cordis-host-runner/package.json index d8ebc413e8..fc16c9faee 100644 --- a/packages/extensions/cordis-host-runner/package.json +++ b/packages/extensions/cordis-host-runner/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-cordis-host-runner", "description": "Dynamic package definition registry, host-half sandbox lifecycle, and invoke handler table for model-mounted dual-half packages", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/extensions/tool-cordis/package.json b/packages/extensions/tool-cordis/package.json index d19d0fb5ef..aac95c8823 100644 --- a/packages/extensions/tool-cordis/package.json +++ b/packages/extensions/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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/extensions/ui-cordis/package.json b/packages/extensions/ui-cordis/package.json index 32b78e9ed7..ca2eecf8af 100644 --- a/packages/extensions/ui-cordis/package.json +++ b/packages/extensions/ui-cordis/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-cordis", "description": "Cordis dynamic-plugin definition card: the keyed cordis_define tool row with its run/stop switch", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/feedback/command-feedback/package.json b/packages/feedback/command-feedback/package.json index 77fb5b7fc7..c2edd8c779 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: the record event, the sessionFeedback Host Remote, and the human-facing slash command", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/feedback/message-feedback/package.json b/packages/feedback/message-feedback/package.json index abfa697159..9052c044aa 100644 --- a/packages/feedback/message-feedback/package.json +++ b/packages/feedback/message-feedback/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-message-feedback", "description": "Canonical Session-log ratings and notes for finalized assistant messages", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/fs/fs-local/package.json b/packages/fs/fs-local/package.json index 56a9da2f6a..d79a6f2255 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/fs/fs-observation-policy/package.json b/packages/fs/fs-observation-policy/package.json index 59ad5acad9..1af4cf4034 100644 --- a/packages/fs/fs-observation-policy/package.json +++ b/packages/fs/fs-observation-policy/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-fs-observation-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 API)", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/fs/fs-sandbox/package.json b/packages/fs/fs-sandbox/package.json index dc2bb684d9..f89eaf2a9c 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/fs/fs/package.json b/packages/fs/fs/package.json index a46cf65967..8439d17348 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/fs/tool-fs-search/package.json b/packages/fs/tool-fs-search/package.json index 20ecda599d..8a7c6be277 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/fs/tool-fs/package.json b/packages/fs/tool-fs/package.json index 03f16c0632..343fbeccdd 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/fs/tool-present/package.json b/packages/fs/tool-present/package.json index 659cea88a0..9b023e2a2e 100644 --- a/packages/fs/tool-present/package.json +++ b/packages/fs/tool-present/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-tool-present", "description": "Explicit workspace file delivery declarations for the DeepSeek Harness", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/fs/tool-str-replace-editor/package.json b/packages/fs/tool-str-replace-editor/package.json index e1e35a2a86..2dbd933a52 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/goal/command-goal/package.json b/packages/goal/command-goal/package.json index 96d36bc0ad..65fc278a2f 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/goal/goal-round-driver/package.json b/packages/goal/goal-round-driver/package.json index 9f3b170dee..4abcc68206 100644 --- a/packages/goal/goal-round-driver/package.json +++ b/packages/goal/goal-round-driver/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-goal-round-driver", "description": "Race-fenced same-session goal-round driver", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/goal/goal/package.json b/packages/goal/goal/package.json index 07496de265..29588f456f 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/goal/tool-goal/package.json b/packages/goal/tool-goal/package.json index 51bd83f6fd..1aaa86f575 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/guard/repeat-tool-reminder/package.json b/packages/guard/repeat-tool-reminder/package.json index 64a40e0cc3..6e57a886a3 100644 --- a/packages/guard/repeat-tool-reminder/package.json +++ b/packages/guard/repeat-tool-reminder/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-repeat-tool-reminder", "description": "Repeat-tool-call guard plugin: advisory reminders when an agent loops on identical tool calls", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/guard/timeout-policy/package.json b/packages/guard/timeout-policy/package.json index 96481352d5..14b7d621ea 100644 --- a/packages/guard/timeout-policy/package.json +++ b/packages/guard/timeout-policy/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-tool-call-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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/hooks/hook-protocol/package.json b/packages/hooks/hook-protocol/package.json index ada42c6619..49a85fe3bd 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/hooks/hooks-claude-code/package.json b/packages/hooks/hooks-claude-code/package.json index 68057a5d2e..70d0b1bde7 100644 --- a/packages/hooks/hooks-claude-code/package.json +++ b/packages/hooks/hooks-claude-code/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-hooks-claude-code", "description": "Bridge plugin: run a Claude Code hooks.json / settings hook config on the DeepSeek Harness interception seams", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/hooks/hooks-codex/package.json b/packages/hooks/hooks-codex/package.json index 39ec414cc7..b7a20f5cd9 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/host/directory-picker-auto/package.json b/packages/host/directory-picker-auto/package.json index 8be34c1710..1088c95483 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/host/directory-picker-browse/package.json b/packages/host/directory-picker-browse/package.json index 6f70fe7462..38002d75f8 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/host/directory-picker-native/package.json b/packages/host/directory-picker-native/package.json index 66c1532a9b..a191b4b1cd 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/host/directory-picker/package.json b/packages/host/directory-picker/package.json index 78511ee411..00eebac289 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/host/frontend-static/package.json b/packages/host/frontend-static/package.json index 5b4a21dc44..ef03cd5fdf 100644 --- a/packages/host/frontend-static/package.json +++ b/packages/host/frontend-static/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-host-frontend-static", "description": "SPA dist server for the Web shell: owns the webserver fallback seat, serving explicit index entries and static assets with traversal rejection and 404 misses", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/host/open-in-app/package.json b/packages/host/open-in-app/package.json index 0219a7cb65..58cff2e44e 100644 --- a/packages/host/open-in-app/package.json +++ b/packages/host/open-in-app/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-host-open-in-app", "description": "Host half of open-in-app: resolved application catalog, icons, and the launch endpoint as three webServer routes", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/host/plugin-inventory/package.json b/packages/host/plugin-inventory/package.json index fb8aeed845..e72377b7b4 100644 --- a/packages/host/plugin-inventory/package.json +++ b/packages/host/plugin-inventory/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-host-plugin-inventory", "description": "Read-only Remote projection of current Cordis Loader plugin state", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/host/webserver/package.json b/packages/host/webserver/package.json index ce0ea4e673..697de34315 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/identity/anonymous-user-id/package.json b/packages/identity/anonymous-user-id/package.json index 33dcaef9ee..08f585899d 100644 --- a/packages/identity/anonymous-user-id/package.json +++ b/packages/identity/anonymous-user-id/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-anonymous-user-id", "description": "Shared anonymous user identity for DeepSeek Harness telemetry and feedback correlation", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/interaction/commands/package.json b/packages/interaction/commands/package.json index 98f9010fe8..b75e2f4ddd 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 UIs", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/interaction/permission-presets/package.json b/packages/interaction/permission-presets/package.json index ad1646d1fb..b28f1b5eec 100644 --- a/packages/interaction/permission-presets/package.json +++ b/packages/interaction/permission-presets/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-permission-presets", "description": "User-facing permission presets (ctx.permissionPresets) 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/interaction/tool-ask-user/package.json b/packages/interaction/tool-ask-user/package.json index bd82bab404..cc3fe60cc0 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.userQuestions seam", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/interaction/user-approval/package.json b/packages/interaction/user-approval/package.json index 64a7a2be77..3ca3f0f525 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/interaction/user-questions/package.json b/packages/interaction/user-questions/package.json index b2a1bf8aea..9afed4c94a 100644 --- a/packages/interaction/user-questions/package.json +++ b/packages/interaction/user-questions/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-user-questions", "description": "Abstract user-questions seam (ctx.userQuestions) for asking the human during agent runs", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/jobs/jobs-local/package.json b/packages/jobs/jobs-local/package.json index e4d519dad8..6f948e53a7 100644 --- a/packages/jobs/jobs-local/package.json +++ b/packages/jobs/jobs-local/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-jobs-local", "description": "Process-local implementation of the DeepSeek Harness background job registry seam", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/jobs/jobs/package.json b/packages/jobs/jobs/package.json index 8da1246315..84677930f0 100644 --- a/packages/jobs/jobs/package.json +++ b/packages/jobs/jobs/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-jobs", "description": "Background job registry (ctx.jobs) for the DeepSeek Harness — shared ids, owner isolation, polling, cancellation, and completion listeners for long-running tool work", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/jobs/tool-jobs/package.json b/packages/jobs/tool-jobs/package.json index 116531ef3b..24f3db873d 100644 --- a/packages/jobs/tool-jobs/package.json +++ b/packages/jobs/tool-jobs/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-tool-jobs", "description": "Model-facing background job control tools (job_output, job_list, job_kill) over the ctx.jobs registry", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/llm/deepseek-llm-api-extensions/package.json b/packages/llm/deepseek-llm-api-extensions/package.json index 362afd2c35..0ca77d15ba 100644 --- a/packages/llm/deepseek-llm-api-extensions/package.json +++ b/packages/llm/deepseek-llm-api-extensions/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-deepseek-llm-api-extensions", "description": "Additive request-field registry for the official DeepSeek LLM API adapter", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/llm/llm-deepseek/package.json b/packages/llm/llm-deepseek/package.json index d25c0f9429..96a1f09daa 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/llm/llm-pi-ai/package.json b/packages/llm/llm-pi-ai/package.json index 291275e245..ac40412c74 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/llm/llm-retry/package.json b/packages/llm/llm-retry/package.json index 7e83c7f6a7..b014875abb 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/llm/llm/package.json b/packages/llm/llm/package.json index 486e47ea0c..42607c948a 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/llm/plugin-package-inventory-deepseek/package.json b/packages/llm/plugin-package-inventory-deepseek/package.json index 469607d05e..e3a342138f 100644 --- a/packages/llm/plugin-package-inventory-deepseek/package.json +++ b/packages/llm/plugin-package-inventory-deepseek/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-plugin-package-inventory-deepseek", "description": "Active Loader-backed plugin package inventory for official DeepSeek LLM API requests", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/llm/token-meter/package.json b/packages/llm/token-meter/package.json index e97a24ffec..26277f7f7e 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/lsp/lsp-stdio/package.json b/packages/lsp/lsp-stdio/package.json index d0cacbce8e..fd0a4daa96 100644 --- a/packages/lsp/lsp-stdio/package.json +++ b/packages/lsp/lsp-stdio/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-lsp-stdio", "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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/lsp/lsp/package.json b/packages/lsp/lsp/package.json index dad6904fde..5f06b7bbc2 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/lsp/tool-lsp/package.json b/packages/lsp/tool-lsp/package.json index a38ba7f575..50c138faac 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/mcp/mcp-client/package.json b/packages/mcp/mcp-client/package.json index 8ec0b808e9..b4a44591e2 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/plan/plan-mode/package.json b/packages/plan/plan-mode/package.json index 77c8258cfb..f220584cb1 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/preset/agent-presets/package.json b/packages/preset/agent-presets/package.json index 198e9cb3ad..8864d9cbc9 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/preset/persona/package.json b/packages/preset/persona/package.json index abb1f1d95f..d36ac063e7 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/runtime-diagnostics/invariants/package.json b/packages/runtime-diagnostics/invariants/package.json index 2a58624dd3..88ffd72ca5 100644 --- a/packages/runtime-diagnostics/invariants/package.json +++ b/packages/runtime-diagnostics/invariants/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-invariants", "description": "Registry service for package-owned DeepSeek Harness runtime invariants", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/sandbox/sandbox-local/package.json b/packages/sandbox/sandbox-local/package.json index 1e81d1c41e..b09d192393 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/sandbox/sandbox-policy/package.json b/packages/sandbox/sandbox-policy/package.json index 88956c44aa..bb670d47be 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/sandbox/sandbox-windows-acl/package.json b/packages/sandbox/sandbox-windows-acl/package.json index 237fdf6c5e..aa9f18f337 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 capability-SID write allowlist) for the DeepSeek Harness sandbox seam", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/sandbox/sandbox/package.json b/packages/sandbox/sandbox/package.json index db96b4b4dd..e58a4360e2 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/schedule/schedule/package.json b/packages/schedule/schedule/package.json index 9bb951f2c2..36e3a7ab3b 100644 --- a/packages/schedule/schedule/package.json +++ b/packages/schedule/schedule/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-schedule", "description": "Agent-scoped durable after, at, and fixed-rate reminders over the session event log", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/sdk/client/package.json b/packages/sdk/client/package.json index b2f0a53b0a..c5568acce1 100644 --- a/packages/sdk/client/package.json +++ b/packages/sdk/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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/sdk/protocol/package.json b/packages/sdk/protocol/package.json index 5d886f8917..437026797c 100644 --- a/packages/sdk/protocol/package.json +++ b/packages/sdk/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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/sdk/server/package.json b/packages/sdk/server/package.json index f2a67d92eb..ec10f6c44e 100644 --- a/packages/sdk/server/package.json +++ b/packages/sdk/server/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-sdk-jsonrpc-server", "description": "Stdio JSON-RPC server plugin for out-of-process DeepSeek Harness SDK clients", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/session-query/session-log-export/package.json b/packages/session-query/session-log-export/package.json index df74a200f6..61e19ed507 100644 --- a/packages/session-query/session-log-export/package.json +++ b/packages/session-query/session-log-export/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-session-log-export", "description": "Web Session-log export command and shared download dialog", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/session-query/session-query-sqlite/package.json b/packages/session-query/session-query-sqlite/package.json index 6c002b89b1..b1c46dfc9b 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/session-query/session-query/package.json b/packages/session-query/session-query/package.json index 209d8d3ae6..6e6ea9bcd3 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/session-query/tool-session-query/package.json b/packages/session-query/tool-session-query/package.json index 459a310a4f..a4b2ce8125 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/session/session-checkpoint-policy/package.json b/packages/session/session-checkpoint-policy/package.json index ea8f06bd48..073d8b9301 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/session/session-format-catalog/package.json b/packages/session/session-format-catalog/package.json index 35c64ad7c9..7b05cf37dc 100644 --- a/packages/session/session-format-catalog/package.json +++ b/packages/session/session-format-catalog/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-session-format-catalog", "description": "Build-static first-party Session format codec and migration catalog", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/session/session-format-v0-to-v1/package.json b/packages/session/session-format-v0-to-v1/package.json index 237b0353ca..1e96ded8e6 100644 --- a/packages/session/session-format-v0-to-v1/package.json +++ b/packages/session/session-format-v0-to-v1/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-session-format-v0-to-v1", "description": "Frozen released-v0 Session codec and identity migration to v1", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/session/session-format-v1-to-v2/package.json b/packages/session/session-format-v1-to-v2/package.json index 7eff82299f..b1a302805e 100644 --- a/packages/session/session-format-v1-to-v2/package.json +++ b/packages/session/session-format-v1-to-v2/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-session-format-v1-to-v2", "description": "Frozen released-v1 Session codec and assistant-stream migration to v2", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/session/session-format-v2-to-v3/package.json b/packages/session/session-format-v2-to-v3/package.json index e893b3afa9..2ab1d8b825 100644 --- a/packages/session/session-format-v2-to-v3/package.json +++ b/packages/session/session-format-v2-to-v3/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-session-format-v2-to-v3", "description": "Streaming system-prompt, canonical-envelope and PTC migration into V3", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/session/session-format/package.json b/packages/session/session-format/package.json index d76b1d576e..e9e8c772eb 100644 --- a/packages/session/session-format/package.json +++ b/packages/session/session-format/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-session-format", "description": "Streaming adjacent Session format migration machinery", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/session/session-log-deepseek/package.json b/packages/session/session-log-deepseek/package.json index 94050124cc..f8e5421b20 100644 --- a/packages/session/session-log-deepseek/package.json +++ b/packages/session/session-log-deepseek/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-session-log-deepseek", "description": "Incremental lossless session-log request extension for the official DeepSeek LLM API", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/session/session-persistence-jsonl/package.json b/packages/session/session-persistence-jsonl/package.json index 80df4e2342..051c990c56 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/session/session-persistence/package.json b/packages/session/session-persistence/package.json index 7140efbce9..4d4f14bc46 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/session/session-projection-cache/package.json b/packages/session/session-projection-cache/package.json index 8bad923651..9fb680ffb2 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 checkpoint records on the session_projcache storage domain (per-record layout), throttled write-behind, and the cached listing read", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/session/session-projection/package.json b/packages/session/session-projection/package.json index 358aa65c23..ecf64e41b8 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/session/session-stats/package.json b/packages/session/session-stats/package.json index 1f0561d70c..ed0320ebf3 100644 --- a/packages/session/session-stats/package.json +++ b/packages/session/session-stats/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-session-stats", "description": "Whole-log conversation counts and wall times projection (sessionStats) for the DeepSeek Harness", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/session/session-telemetry-otel/package.json b/packages/session/session-telemetry-otel/package.json index b3f1361173..fdccda3937 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/session/session-telemetry/package.json b/packages/session/session-telemetry/package.json index de05df1d90..501654fc92 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": "SessionTelemetryBackend seam for the DeepSeek Harness: session-event capture, projection, redaction, and handoff to a reporting backend", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/session/session-title-all-prompts-llm/package.json b/packages/session/session-title-all-prompts-llm/package.json index 90417298b3..ebe626e54e 100644 --- a/packages/session/session-title-all-prompts-llm/package.json +++ b/packages/session/session-title-all-prompts-llm/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-session-title-all-prompts-llm", "description": "All-user-messages LLM provider plugin for DeepSeek Harness session titles", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/session/session-title-first-prompt-llm/package.json b/packages/session/session-title-first-prompt-llm/package.json index 77e29c11af..550bbbd087 100644 --- a/packages/session/session-title-first-prompt-llm/package.json +++ b/packages/session/session-title-first-prompt-llm/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-session-title-first-prompt-llm", "description": "First-message LLM provider plugin for DeepSeek Harness session titles", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/session/session-title-llm/package.json b/packages/session/session-title-llm/package.json index 7dc081293d..2a34c0522d 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/session/session-title/package.json b/packages/session/session-title/package.json index 2cc7a6a604..aa48bb7059 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/session/session-turn-outline/package.json b/packages/session/session-turn-outline/package.json index 1ea6e8cc81..0894dc23f8 100644 --- a/packages/session/session-turn-outline/package.json +++ b/packages/session/session-turn-outline/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-session-turn-outline", "description": "Whole-log turn outline projection (turnOutline) for the DeepSeek Harness", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/settings/settings-file/package.json b/packages/settings/settings-file/package.json index 663c9682db..e317cb4a4b 100644 --- a/packages/settings/settings-file/package.json +++ b/packages/settings/settings-file/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-settings-file", "description": "File-backed settings provider (settings.yaml) for the DeepSeek Harness", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/settings/settings/package.json b/packages/settings/settings/package.json index 9151e92d0b..a175d964d1 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/shell/bash-local/package.json b/packages/shell/bash-local/package.json index 87ba3b08e0..14f6c3def0 100644 --- a/packages/shell/bash-local/package.json +++ b/packages/shell/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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/shell/bash-sandbox/package.json b/packages/shell/bash-sandbox/package.json index 7b0c17a2e4..94afedadab 100644 --- a/packages/shell/bash-sandbox/package.json +++ b/packages/shell/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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/shell/pwsh-local/package.json b/packages/shell/pwsh-local/package.json index 7254df4d80..5449e63832 100644 --- a/packages/shell/pwsh-local/package.json +++ b/packages/shell/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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/shell/pwsh-sandbox/package.json b/packages/shell/pwsh-sandbox/package.json index be6f6fe406..c6ab3fe73f 100644 --- a/packages/shell/pwsh-sandbox/package.json +++ b/packages/shell/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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/shell/shell-env/package.json b/packages/shell/shell-env/package.json index 8956952748..b2cd4eadad 100644 --- a/packages/shell/shell-env/package.json +++ b/packages/shell/shell-env/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-shell-env", "description": "Tool-independent managed DSH_* shell environment registry", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/shell/shell/package.json b/packages/shell/shell/package.json index 8821c3aeb8..89ba9cbf1b 100644 --- a/packages/shell/shell/package.json +++ b/packages/shell/shell/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-shell", "description": "Abstract bash executor seam (ctx.shell) for the DeepSeek Harness", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/shell/tool-bash-persistent/package.json b/packages/shell/tool-bash-persistent/package.json index 3e0a7a7a8c..c371cbe14e 100644 --- a/packages/shell/tool-bash-persistent/package.json +++ b/packages/shell/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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/shell/tool-bash/package.json b/packages/shell/tool-bash/package.json index d6308c9be3..73c8784e36 100644 --- a/packages/shell/tool-bash/package.json +++ b/packages/shell/tool-bash/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-tool-bash", "description": "Model-facing bash tool with optional generic background-job and sandbox-escalation support", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/shell/tool-pwsh-persistent/package.json b/packages/shell/tool-pwsh-persistent/package.json index 6b536ee67a..d83c8aa391 100644 --- a/packages/shell/tool-pwsh-persistent/package.json +++ b/packages/shell/tool-pwsh-persistent/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-tool-pwsh-persistent", "description": "Model-facing owner-scoped persistent PowerShell tool backed by the Harness PTY service", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/shell/tool-pwsh/package.json b/packages/shell/tool-pwsh/package.json index 455635d24d..ad4edddb51 100644 --- a/packages/shell/tool-pwsh/package.json +++ b/packages/shell/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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/skill/skill-badge/package.json b/packages/skill/skill-badge/package.json index 4965ecb35d..a2df18c583 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/skill/skill-filesystem/package.json b/packages/skill/skill-filesystem/package.json index 12fc7ec3b2..1a09d7ea55 100644 --- a/packages/skill/skill-filesystem/package.json +++ b/packages/skill/skill-filesystem/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-skill-filesystem", "description": "Local filesystem skill provider for the DeepSeek Harness", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/skill/skill/package.json b/packages/skill/skill/package.json index d55f3a1897..6b7a052581 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/skill/tool-skill/package.json b/packages/skill/tool-skill/package.json index b79118fbd9..90173f9f12 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/spill/spill-local/package.json b/packages/spill/spill-local/package.json index 36bfb9cf3a..3dca8cdb97 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/spill/spill-policy/package.json b/packages/spill/spill-policy/package.json index 88e42b054f..beae462383 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 API)", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/spill/spill/package.json b/packages/spill/spill/package.json index fe381277f8..6744b3bef2 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/storage/storage-domain/package.json b/packages/storage/storage-domain/package.json index 3b322ea6dd..25e93ba114 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/storage/storage-json/package.json b/packages/storage/storage-json/package.json index bf363340b4..bfd9a9548e 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/storage/storage-sqlite/package.json b/packages/storage/storage-sqlite/package.json index d04fad5ef1..f2d2d97371 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/storage/storage/package.json b/packages/storage/storage/package.json index 30d2555ac2..683f16ed89 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/subagent/subagent-acp/package.json b/packages/subagent/subagent-acp/package.json index db33332e03..fdefecef3f 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/subagent/subagent-claude-code/package.json b/packages/subagent/subagent-claude-code/package.json index 569dcb1e47..ad5d61a1b0 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/subagent/subagent-codex/package.json b/packages/subagent/subagent-codex/package.json index 847743c103..9fd53d3f6b 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/subagent/subagent-dsh-sdk/package.json b/packages/subagent/subagent-dsh-sdk/package.json index 2129650bf9..75366da19d 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/subagent/subagent-fork-in-process/package.json b/packages/subagent/subagent-fork-in-process/package.json index 507e1cd6be..ac1c994a81 100644 --- a/packages/subagent/subagent-fork-in-process/package.json +++ b/packages/subagent/subagent-fork-in-process/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-subagent-fork-in-process", "description": "In-process fork subagent backend: runs a child agent seeded with a prefix of the parent's log", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/subagent/subagent-in-process-driver/package.json b/packages/subagent/subagent-in-process-driver/package.json index 7c50e623de..2cffea484b 100644 --- a/packages/subagent/subagent-in-process-driver/package.json +++ b/packages/subagent/subagent-in-process-driver/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-subagent-in-process-driver", "description": "Shared in-process subagent run driver: drives a child agent on ctx.agents (used by the spawn and fork backends)", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/subagent/subagent-spawn-in-process/package.json b/packages/subagent/subagent-spawn-in-process/package.json index 489d735a23..fddaca056b 100644 --- a/packages/subagent/subagent-spawn-in-process/package.json +++ b/packages/subagent/subagent-spawn-in-process/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-subagent-spawn-in-process", "description": "In-process spawn subagent backend: runs a fresh child agent on ctx.agents", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/subagent/subagent/package.json b/packages/subagent/subagent/package.json index 91c412970d..e80b2c60d3 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/subagent/tool-subagent-control/package.json b/packages/subagent/tool-subagent-control/package.json index 938bee4928..adf00d10a2 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/subagent/tool-subagent/package.json b/packages/subagent/tool-subagent/package.json index ea6d41aad7..cfd711a58c 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/subprocess/subprocess-local/package.json b/packages/subprocess/subprocess-local/package.json index 9ddd44aa8c..5d931ca699 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/subprocess/subprocess/package.json b/packages/subprocess/subprocess/package.json index 86668ed669..e1e4a52318 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/subprocess/win32-process/package.json b/packages/subprocess/win32-process/package.json index baaa455ffd..fa94953d38 100644 --- a/packages/subprocess/win32-process/package.json +++ b/packages/subprocess/win32-process/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-win32-process", "description": "Shared low-level Win32 process, stdio, and Job Object primitives", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/terminal/terminal-bash/package.json b/packages/terminal/terminal-bash/package.json index 7dc1f47d67..88757151b1 100644 --- a/packages/terminal/terminal-bash/package.json +++ b/packages/terminal/terminal-bash/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-terminal-bash", "description": "Persistent shell PTY backend over the DeepSeek Harness subprocess terminal primitive", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/terminal/terminal/package.json b/packages/terminal/terminal/package.json index cdd4676fc8..f81401e660 100644 --- a/packages/terminal/terminal/package.json +++ b/packages/terminal/terminal/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-terminal", "description": "Persistent PTY session seam for the DeepSeek Harness — owner-scoped ids, backend registry, interactive sends, reads, signals, and awaited cleanup", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/terminal/tool-terminal/package.json b/packages/terminal/tool-terminal/package.json index 62f9215d9e..52ed02d241 100644 --- a/packages/terminal/tool-terminal/package.json +++ b/packages/terminal/tool-terminal/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-tool-terminal", "description": "Six model-facing persistent PTY tools with owner isolation and generic background-job integration", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/test-support/agent-loop-testkit/package.json b/packages/test-support/agent-loop-testkit/package.json index dd756655cb..70fed66a8d 100644 --- a/packages/test-support/agent-loop-testkit/package.json +++ b/packages/test-support/agent-loop-testkit/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-agent-loop-testkit", "description": "Prerequisite mounting, production AgentLoop drivers, and Inbox stubs for tests", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/test-support/client-runtime/package.json b/packages/test-support/client-runtime/package.json index 2b1b3d0bf2..f23b3e2d63 100644 --- a/packages/test-support/client-runtime/package.json +++ b/packages/test-support/client-runtime/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-test-runtime", "description": "jsdom slot test runtime: real Cordis Context + SlotRegistry + UI renderer with test-owned session/workspace doubles for feature specs", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/test-support/llm-mock-server/package.json b/packages/test-support/llm-mock-server/package.json index eda9c672f6..efba8e4d14 100644 --- a/packages/test-support/llm-mock-server/package.json +++ b/packages/test-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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/test-support/llm-replay/package.json b/packages/test-support/llm-replay/package.json index 245095b254..b316098c5c 100644 --- a/packages/test-support/llm-replay/package.json +++ b/packages/test-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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/test-support/loader-smoke/package.json b/packages/test-support/loader-smoke/package.json index d0bb80d2dd..dbf7331cd9 100644 --- a/packages/test-support/loader-smoke/package.json +++ b/packages/test-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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/test-support/session-snapshot/package.json b/packages/test-support/session-snapshot/package.json index ba37c3588f..138894273a 100644 --- a/packages/test-support/session-snapshot/package.json +++ b/packages/test-support/session-snapshot/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-session-snapshot", "description": "Session-log snapshot core with an ACP protocol adapter, expected-output normalization, and fixture invariants", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/todo/tool-todo/package.json b/packages/todo/tool-todo/package.json index 4d57bff520..5ca2d72f9d 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/typert/generator/package.json b/packages/typert/generator/package.json index 21cf25f8e9..b3aa62a13c 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/typert/loader/package.json b/packages/typert/loader/package.json index bcbb5548f8..b456b74760 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/typert/protocol/package.json b/packages/typert/protocol/package.json index 347f804f31..db5a2cc7de 100644 --- a/packages/typert/protocol/package.json +++ b/packages/typert/protocol/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-typert-protocol", "description": "Compiler-independent Remote metadata and Typert provider protocols", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/typert/registry/package.json b/packages/typert/registry/package.json index d2b9e5c60f..c2dc26fb03 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/util/atomic-write/package.json b/packages/util/atomic-write/package.json index b805131b48..6fdfc94e10 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/util/brand/package.json b/packages/util/brand/package.json index e389cf15eb..03a8ed4cb9 100644 --- a/packages/util/brand/package.json +++ b/packages/util/brand/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-brand", "description": "Stateless branded primitive types for the DeepSeek Harness", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/util/chunked-list/package.json b/packages/util/chunked-list/package.json index 86505ac3bc..ac0e863eaf 100644 --- a/packages/util/chunked-list/package.json +++ b/packages/util/chunked-list/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-chunked-list", "description": "Persistent append-only chunked lists with bounded copying and JSON checkpoint validation", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/util/crypto/package.json b/packages/util/crypto/package.json index 5ab63eb83a..cc9cfb2a3b 100644 --- a/packages/util/crypto/package.json +++ b/packages/util/crypto/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-util-crypto", "description": "Zero-dependency browser-safe UUID and byte-encoding helpers", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/util/deque/package.json b/packages/util/deque/package.json index d9f0a1804f..598cb5f035 100644 --- a/packages/util/deque/package.json +++ b/packages/util/deque/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-deque", "description": "Zero-dependency circular deque with amortized constant-time end operations and bounded vacant storage", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/util/home-paths/package.json b/packages/util/home-paths/package.json index 4187d95fa2..2db1274725 100644 --- a/packages/util/home-paths/package.json +++ b/packages/util/home-paths/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-home-paths", "description": "Shared filesystem path helpers for the DeepSeek Harness", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/util/http-proxy/package.json b/packages/util/http-proxy/package.json index 7a8170f50b..347b01616e 100644 --- a/packages/util/http-proxy/package.json +++ b/packages/util/http-proxy/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-http-proxy", "description": "Process-wide outbound HTTP proxy policy for DeepSeek Harness: resolve it from the launch environment and install it as undici's global dispatcher", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/util/launch-environment/package.json b/packages/util/launch-environment/package.json index 28a01033db..8486d4c28c 100644 --- a/packages/util/launch-environment/package.json +++ b/packages/util/launch-environment/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-launch-environment", "description": "Immutable DeepSeek Harness launch environment that records which layer supplied each value", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/util/native-command/package.json b/packages/util/native-command/package.json index f4ce7b6ec2..9f1d01ac3b 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": "Host-native command and path-opening utilities with shell-free execution, cancellation, desktop detection, and WSL handoff", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/util/output-retention/package.json b/packages/util/output-retention/package.json index 7048e841c1..c13057bbf4 100644 --- a/packages/util/output-retention/package.json +++ b/packages/util/output-retention/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-output-retention", "description": "Zero-dependency bounded-retention primitive: ItemRetainer/TextRetainer + neutral notice helpers (what did we keep, what did we omit)", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/util/package-manifest/package.json b/packages/util/package-manifest/package.json index c9b9121f69..10edfdf497 100644 --- a/packages/util/package-manifest/package.json +++ b/packages/util/package-manifest/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-package-manifest", "description": "Shared type declarations for package.json.dsh configuration fields", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/util/time/package.json b/packages/util/time/package.json index 81edeb6a94..9c4b1e12e6 100644 --- a/packages/util/time/package.json +++ b/packages/util/time/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-util-time", "description": "Zero-dependency time vocabulary shared by wire boundaries: canonicalClientTimeZone (IANA zone validation and canonicalization only, no formatting)", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/util/timeout/package.json b/packages/util/timeout/package.json index c5fab6aade..0ce35639af 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/util/values/package.json b/packages/util/values/package.json index af71263cbf..296695f127 100644 --- a/packages/util/values/package.json +++ b/packages/util/values/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-util-values", "description": "Duplicate-install-safe value primitives for the DeepSeek Harness", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/util/workspace-path/package.json b/packages/util/workspace-path/package.json index 3617c53018..a2e8ec073d 100644 --- a/packages/util/workspace-path/package.json +++ b/packages/util/workspace-path/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-util-workspace-path", "description": "Browser-safe Workspace path and display helpers", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/web/tool-web/package.json b/packages/web/tool-web/package.json index c731904124..60aff70ad0 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/web/web-fetch-http/package.json b/packages/web/web-fetch-http/package.json index c81a828ce4..ca30ce34f9 100644 --- a/packages/web/web-fetch-http/package.json +++ b/packages/web/web-fetch-http/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-web-fetch-http", "description": "Anonymous public HTTP(S) fetch provider for the DeepSeek Harness web capability seam (ctx.web)", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/web/web-search-deepseek/package.json b/packages/web/web-search-deepseek/package.json index 98853ed968..539fa43cb4 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/web/web-search-exa/package.json b/packages/web/web-search-exa/package.json index 9e5d349579..8e7a4ee727 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/web/web-search-perplexity/package.json b/packages/web/web-search-perplexity/package.json index f0f7b73280..fb8b89a771 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/web/web/package.json b/packages/web/web/package.json index b5e92eb755..3edb726b7b 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/webhook/webhook-github/package.json b/packages/webhook/webhook-github/package.json index 6f40c1fce7..ab473bbd2b 100644 --- a/packages/webhook/webhook-github/package.json +++ b/packages/webhook/webhook-github/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-webhook-github", "description": "Signed GitHub HTTP webhook adapter for the DeepSeek Harness webhook runtime", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/webhook/webhook/package.json b/packages/webhook/webhook/package.json index 5f2277ba07..fae2c0cc69 100644 --- a/packages/webhook/webhook/package.json +++ b/packages/webhook/webhook/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-webhook", "description": "Fire-and-forget webhook rule runtime that creates Workspace-backed DeepSeek Harness Sessions", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/workflow/tool-ralph/package.json b/packages/workflow/tool-ralph/package.json index 70a82b6967..3b16bf9ba3 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.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/workflow/tool-workflow/package.json b/packages/workflow/tool-workflow/package.json index 4115427262..f5dbad243b 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.workflowEngine", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/workflow/workflow-worker-thread/package.json b/packages/workflow/workflow-worker-thread/package.json index 259fe7527e..2a42dd5163 100644 --- a/packages/workflow/workflow-worker-thread/package.json +++ b/packages/workflow/workflow-worker-thread/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-workflow-worker-thread", "description": "worker-thread workflow engine: executes model-written orchestration scripts off the host event loop, bridging agent() calls back to ctx.subagents", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/workflow/workflow/package.json b/packages/workflow/workflow/package.json index f1bfc1f276..e027f779c0 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.workflowEngine service, run vocabulary, and workflow/* events", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, diff --git a/packages/workspace/workspace/package.json b/packages/workspace/workspace/package.json index b5fb6fe436..eb2151b3ab 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.workspaceRegistry): durable workspace records with validated session attachment over the domain data form for the DeepSeek Harness", - "version": "0.1.5-rc.2", + "version": "0.1.5-rc.3", "publishConfig": { "access": "public" }, From bed4a2b5653f8766293a1c7e8885a0e5445be332 Mon Sep 17 00:00:00 2001 From: winewill <324803222+winewill@users.noreply.github.com> Date: Tue, 22 Sep 2026 14:30:56 +0800 Subject: [PATCH 10/29] fix(desktop): address review of the extraction failure report - Headline skips the archive path 7-Zip echoes before an open failure (also when the path contains spaces) and prefers the operation line. - Raw process statuses such as 0xC0000005 are kept and printed in hex instead of being clamped to INT_MAX. - The expanded panel excerpts the result and 7-Zip's own lines rather than the report header. - The saved report keeps up to 16 MiB of output, records any cut, and trims a partial UTF-8 sequence before decoding. - The details view no longer reads the UTF-8 log as ANSI; the test seam define and the zero-padded GetTime order are documented; the smoke asserts a year-first report name and normalizes -FrameLibrary. - README names the real updater cache directory. --- apps/desktop/README.i18n.yaml | 4 +- apps/desktop/README.md | 2 +- apps/desktop/README.zh.md | 2 +- apps/desktop/installer/extract-report.h | 90 ++++++++++++++----- apps/desktop/installer/extract.h | 7 +- apps/desktop/installer/window-frame.cpp | 2 +- apps/desktop/scripts/installer.nsh | 15 ++-- .../scripts/smoke-installer-directories.ps1 | 3 +- .../windows-installer-extract-report.cpp | 48 +++++++--- 9 files changed, 121 insertions(+), 52 deletions(-) diff --git a/apps/desktop/README.i18n.yaml b/apps/desktop/README.i18n.yaml index f33e5b54c0..a1081d564f 100644 --- a/apps/desktop/README.i18n.yaml +++ b/apps/desktop/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 apps/desktop/README.md -README.md: adb17f4cd3615e407baa7993bec17f8ad70bb1a9 -README.zh.md: 1410e08eec9bbf5c271ea74900e9f1e4562697b0 +README.md: 81871171931a0d49a9063b6514ea1afc897958f2 +README.zh.md: b3931a91c6e299400d093cb6b0b9ada31c435443 diff --git a/apps/desktop/README.md b/apps/desktop/README.md index adb17f4cd3..8187117193 100644 --- a/apps/desktop/README.md +++ b/apps/desktop/README.md @@ -195,7 +195,7 @@ pwsh -NoProfile -File apps/desktop/scripts/smoke-windows.ps1 -Makensis $Makensis The Windows installer extracts the new version beside the installation directory, stops the old application, and replaces directories through same-volume renames. Same-path upgrades preserve the old directory until promotion succeeds; extraction failure leaves it intact, and promotion failure attempts to restore it. The installer removes the old backup before launch. Forced termination or power loss can leave `.new-*` or `.old-*` directories; installation-location and scope migrations retain electron-builder's old-uninstaller flow. -When extraction fails, the installer writes a report with the 7-Zip result and its complete error output to `%LOCALAPPDATA%\deepseek harness-updater\installer-logs\extract-failure-.log` and shows the first error line with a **Copy error details** button; silent installs write only the report. Unsigned Windows builds (`DSH_DESKTOP_UNSIGNED=1`) name their installer `deepseek-harness--win-x64-unsigned.exe` so they cannot be mistaken for release artifacts. +When extraction fails, the installer writes a report with the 7-Zip result and its complete error output to the updater cache directory as `%LOCALAPPDATA%\-updater\installer-logs\extract-failure-.log` (currently `@deepseek-aidsh-desktop-updater`) and shows the first error line with a **Copy error details** button; silent installs write only the report. Unsigned Windows builds (`DSH_DESKTOP_UNSIGNED=1`) name their installer `deepseek-harness--win-x64-unsigned.exe` so they cannot be mistaken for release artifacts. diff --git a/apps/desktop/README.zh.md b/apps/desktop/README.zh.md index 1410e08eec..b3931a91c6 100644 --- a/apps/desktop/README.zh.md +++ b/apps/desktop/README.zh.md @@ -195,7 +195,7 @@ pwsh -NoProfile -File apps/desktop/scripts/smoke-windows.ps1 -Makensis $Makensis Windows 安装器先将新版本解压到安装目录旁边,再退出旧应用并通过同卷目录改名完成替换。同路径升级在替换成功前保留旧目录;解压失败时旧版不变,替换失败时尝试恢复旧目录。安装器在启动前清理旧版备份。强制结束安装器或断电可能留下 `.new-*` 或 `.old-*` 目录;不同安装位置或安装范围迁移仍使用 electron-builder 的旧卸载器流程。 -解压失败时,安装器会把 7-Zip 的结果和完整错误输出写入 `%LOCALAPPDATA%\deepseek harness-updater\installer-logs\extract-failure-<时间戳>.log`,并在弹窗中显示首条错误行和 **复制错误信息** 按钮;静默安装只写入报告。未签名的 Windows 构建(`DSH_DESKTOP_UNSIGNED=1`)会将安装包命名为 `deepseek-harness-<版本>-win-x64-unsigned.exe`,以免被误当作发布产物。 +解压失败时,安装器会把 7-Zip 的结果和完整错误输出写入更新缓存目录 `%LOCALAPPDATA%\<按包名派生>-updater\installer-logs\extract-failure-<时间戳>.log`(当前为 `@deepseek-aidsh-desktop-updater`),并在弹窗中显示首条错误行和 **复制错误信息** 按钮;静默安装只写入报告。未签名的 Windows 构建(`DSH_DESKTOP_UNSIGNED=1`)会将安装包命名为 `deepseek-harness-<版本>-win-x64-unsigned.exe`,以免被误当作发布产物。 diff --git a/apps/desktop/installer/extract-report.h b/apps/desktop/installer/extract-report.h index eb83f431a5..c885816c75 100644 --- a/apps/desktop/installer/extract-report.h +++ b/apps/desktop/installer/extract-report.h @@ -10,11 +10,13 @@ namespace extract_report { -constexpr size_t kOutputLimit = 256 * 1024; +constexpr size_t kOutputLimit = 16 * 1024 * 1024; constexpr size_t kHeadlineLimit = 160; constexpr size_t kExcerptLineLimit = 120; constexpr size_t kExcerptLines = 10; constexpr size_t kExcerptChars = 1000; +constexpr wchar_t kEllipsis = 0x2026; +constexpr wchar_t kOutputMarker[] = L"7-Zip output:"; // Exit codes documented by 7-Zip; the installer treats every non-zero value as fatal. inline const wchar_t* SevenZipMeaning(int code) { @@ -49,8 +51,6 @@ inline std::vector Lines(const std::wstring& text) { return lines; } -constexpr wchar_t kEllipsis = 0x2026; - inline std::wstring Truncate(const std::wstring& text, size_t limit) { if (text.size() <= limit) return text; return text.substr(0, limit - 1) + kEllipsis; @@ -65,24 +65,47 @@ inline std::wstring Win32Message(DWORD error) { return message; } -// Positive results are 7-Zip exit codes; negative results are negated Win32 errors from launching or supervising it. -inline std::wstring DescribeResult(int code) { - if (code >= 0) return L"7-Zip exit code " + std::to_wstring(code) + L" (" + SevenZipMeaning(code) + L")"; - const DWORD error = static_cast(-static_cast(code)); - std::wstring message = Win32Message(error); - return L"Windows error " + std::to_wstring(error) + L" while running 7-Zip" + (message.empty() ? L"" : L" (" + message + L")"); +// Positive results up to 255 are 7-Zip exit codes and small negative results are negated Win32 errors from launching or +// supervising it; anything else is the raw process status (for example an NTSTATUS from a crash), printed in hex. +constexpr int kMaxSevenZipExitCode = 255; +constexpr int kMaxWin32Error = 0xFFFF; + +inline std::wstring HexStatus(int code) { + WCHAR text[16]; + wsprintfW(text, L"0x%08X", static_cast(code)); + return text; } -// 7-Zip prefixes the failing operation and path with "ERROR:"; the bare archive name it prints first says nothing. -inline std::wstring Headline(int code, const std::wstring& output) { +inline std::wstring DescribeResult(int code) { + if (code >= 0 && code <= kMaxSevenZipExitCode) { + return L"7-Zip exit code " + std::to_wstring(code) + L" (" + SevenZipMeaning(code) + L")"; + } + if (code < 0 && -static_cast(code) <= kMaxWin32Error) { + const DWORD error = static_cast(-static_cast(code)); + std::wstring message = Win32Message(error); + return L"Windows error " + std::to_wstring(error) + L" while running 7-Zip" + (message.empty() ? L"" : L" (" + message + L")"); + } + return L"7-Zip terminated with status " + HexStatus(code); +} + +inline bool EqualsIgnoreCase(const std::wstring& left, const std::wstring& right) { + return left.size() == right.size() && _wcsnicmp(left.c_str(), right.c_str(), left.size()) == 0; +} + +// 7-Zip reports failures as " ERROR: " or "ERROR: : : "; it also echoes the +// bare archive path after "ERROR:" before an open failure, which names nothing and is skipped. +inline std::wstring Headline(int code, const std::wstring& output, const std::wstring& archive) { + const auto separator = archive.find_last_of(L"\\/"); + const std::wstring archiveName = separator == std::wstring::npos ? archive : archive.substr(separator + 1); std::wstring fallback; for (const std::wstring& raw : Lines(output)) { const std::wstring line = Trim(raw); const auto marker = line.find(L"ERROR"); if (marker == std::wstring::npos) continue; - const std::wstring detail = Trim(line.substr(line.find(L':', marker) == std::wstring::npos ? line.size() : line.find(L':', marker) + 1)); - if (detail.empty()) continue; - if (detail.find(L" : ") != std::wstring::npos || detail.find(L' ') != std::wstring::npos) return Truncate(line, kHeadlineLimit); + const auto colon = line.find(L':', marker); + const std::wstring detail = colon == std::wstring::npos ? L"" : Trim(line.substr(colon + 1)); + if (detail.empty() || EqualsIgnoreCase(detail, archive) || EqualsIgnoreCase(detail, archiveName)) continue; + if (detail.find(L" : ") != std::wstring::npos) return Truncate(line, kHeadlineLimit); if (fallback.empty()) fallback = line; } if (!fallback.empty()) return Truncate(fallback, kHeadlineLimit); @@ -97,7 +120,7 @@ inline std::wstring Compose(int code, const std::wstring& archive, const std::ws report += L"Archive: " + archive + L"\r\n"; report += L"Destination: " + destination + L"\r\n"; report += L"Windows: " + windowsVersion + L"\r\n"; - report += L"\r\n7-Zip output:\r\n"; + report += L"\r\n" + std::wstring(kOutputMarker) + L"\r\n"; const std::wstring trimmed = Trim(output); if (trimmed.empty()) { report += L"(none)\r\n"; @@ -107,9 +130,16 @@ inline std::wstring Compose(int code, const std::wstring& archive, const std::ws return report; } -// The dialog stays compact: long lines are cut and a trailing note counts what the report still holds. +// The expanded panel adds 7-Zip's own lines beneath the result; long lines are cut and a trailing note counts what the +// saved report still holds. Header fields already appear in the report file and clipboard. inline std::wstring Excerpt(const std::wstring& report, size_t maxLines = kExcerptLines, size_t maxChars = kExcerptChars) { - const std::vector lines = Lines(Trim(report)); + std::vector lines; + bool inOutput = false; + for (const std::wstring& line : Lines(Trim(report))) { + if (inOutput) lines.push_back(line); + else if (line.rfind(L"Result: ", 0) == 0) lines.push_back(line); + else if (line == kOutputMarker) inOutput = true; + } std::wstring excerpt; size_t shown = 0; for (const std::wstring& line : lines) { @@ -124,6 +154,16 @@ inline std::wstring Excerpt(const std::wstring& report, size_t maxLines = kExcer return excerpt; } +// A cut inside a multi-byte sequence would make the whole UTF-8 attempt fail; drop the incomplete tail first. +inline void TrimPartialUtf8(std::string& bytes) { + size_t trailing = 0; + while (trailing < 3 && trailing < bytes.size() && (static_cast(bytes[bytes.size() - 1 - trailing]) & 0xC0) == 0x80) ++trailing; + if (trailing >= bytes.size()) return; + const unsigned char lead = static_cast(bytes[bytes.size() - 1 - trailing]); + const size_t expected = lead >= 0xF0 ? 4 : lead >= 0xE0 ? 3 : lead >= 0xC0 ? 2 : 1; + if (expected > trailing + 1) bytes.resize(bytes.size() - 1 - trailing); +} + inline std::wstring Decode(const std::string& bytes) { if (bytes.empty()) return L""; for (UINT codePage : {static_cast(CP_UTF8), static_cast(CP_ACP)}) { @@ -137,17 +177,27 @@ inline std::wstring Decode(const std::string& bytes) { return L"(undecodable 7-Zip output)"; } +// The saved report keeps everything 7-Zip wrote; only pathological output beyond kOutputLimit is cut, and the cut is recorded. inline std::wstring ReadOutput(LPCWSTR path) { HANDLE file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); if (file == INVALID_HANDLE_VALUE) return L""; std::string bytes; char buffer[8192]; DWORD count = 0; - while (bytes.size() < kOutputLimit && ReadFile(file, buffer, sizeof(buffer), &count, nullptr) && count) { - bytes.append(buffer, std::min(count, kOutputLimit - bytes.size())); + bool truncated = false; + while (ReadFile(file, buffer, sizeof(buffer), &count, nullptr) && count) { + if (bytes.size() + count > kOutputLimit) { + bytes.append(buffer, kOutputLimit - bytes.size()); + truncated = true; + break; + } + bytes.append(buffer, count); } CloseHandle(file); - return Decode(bytes); + if (truncated) TrimPartialUtf8(bytes); + std::wstring output = Decode(bytes); + if (truncated) output += L"\r\n[7-Zip output truncated after " + std::to_wstring(kOutputLimit / (1024 * 1024)) + L" MiB]\r\n"; + return output; } inline std::wstring Timestamp() { diff --git a/apps/desktop/installer/extract.h b/apps/desktop/installer/extract.h index af30077912..f63a94061b 100644 --- a/apps/desktop/installer/extract.h +++ b/apps/desktop/installer/extract.h @@ -1,6 +1,5 @@ // The pinned 7-Zip executable owns extraction; this pipe reader publishes its work percentage. #pragma once -#include #include #include #include "extract-progress.h" @@ -92,11 +91,13 @@ static int ExtractApplication(HWND parent, LPCWSTR tool, LPCWSTR archive, LPCWST DWORD result; if (!GetExitCodeProcess(process.value, &result)) return LaunchFailure(GetLastError()); if (result == 0 && parent) SetPropW(parent, L"HarnessInstaller.ExtractProgress", reinterpret_cast(100)); - return result > INT_MAX ? INT_MAX : static_cast(result); + // A crash status such as 0xC0000005 comes back bit-for-bit; the report prints anything beyond 7-Zip's exit codes in hex. + return static_cast(result); } // Runs on the NSIS worker; only an exit code of zero permits directory promotion. -// Positive results are 7-Zip exit codes; negative results are negated Win32 errors from launching or supervising it. +// Results 0-255 are 7-Zip exit codes, small negative results are negated Win32 errors from launching or supervising it, +// and any other value is the raw process status. extern "C" __declspec(dllexport) int __cdecl InstallerExtract(HWND parent, LPCWSTR tool, LPCWSTR archive, LPCWSTR destination, LPCWSTR log) { try { return ExtractApplication(parent, tool, archive, destination, log); } catch (const std::bad_alloc&) { return LaunchFailure(ERROR_NOT_ENOUGH_MEMORY); } diff --git a/apps/desktop/installer/window-frame.cpp b/apps/desktop/installer/window-frame.cpp index 0a81fae33e..889ede54f0 100644 --- a/apps/desktop/installer/window-frame.cpp +++ b/apps/desktop/installer/window-frame.cpp @@ -32,7 +32,7 @@ extern "C" __declspec(dllexport) int __cdecl InstallerReportExtractFailure( const auto placeholder = footer.find(L"%s"); if (saved && placeholder != std::wstring::npos) footer.replace(placeholder, 2, reportPath); const extract_report::DialogStrings strings{title, heading, copy, expand, collapse, footer.c_str(), copied}; - const std::wstring content = extract_report::Headline(code, output) + L"\r\n\r\n" + hint; + const std::wstring content = extract_report::Headline(code, output, archive) + L"\r\n\r\n" + hint; extract_report::Show(parent, content, extract_report::Excerpt(report), report, strings); } return saved ? 1 : 0; diff --git a/apps/desktop/scripts/installer.nsh b/apps/desktop/scripts/installer.nsh index 7ddda5aa85..5980287859 100644 --- a/apps/desktop/scripts/installer.nsh +++ b/apps/desktop/scripts/installer.nsh @@ -121,19 +121,13 @@ ManifestDPIAware true System::Call /NOUNLOAD '$PLUGINSDIR\window-frame.dll::InstallerExtract(p $HWNDPARENT, w "$PLUGINSDIR\dsh-7za.exe", w "${Archive}", w "$INSTDIR", w "$PLUGINSDIR\extract.log") i.s ?c' System::Store "L" Pop $R0 + ; The failure report owns 7-Zip's UTF-8 output; the details view only needs the result code. StrCpy $R1 "$R0" - ${If} $R0 != 0 - Push $0 - FileOpen $0 "$PLUGINSDIR\extract.log" r - ${IfNot} ${Errors} - FileRead $0 $R1 - FileClose $0 - ${EndIf} - Pop $0 - ${EndIf} !macroend -; The report outlives $PLUGINSDIR so a user can send it; silent installs keep only the file. +; The report outlives $PLUGINSDIR so a user can send it; silent installs keep only the file. The updater cache +; directory is never an installation target and leaves with the application on uninstall. +; The directory smoke fixture predefines DSH_INSTALLER_LOG_DIR to keep reports inside its scratch tree. !ifndef DSH_INSTALLER_LOG_DIR !define DSH_INSTALLER_LOG_DIR "$LOCALAPPDATA\${DSH_UPDATER_CACHE_NAME}\installer-logs" !endif @@ -146,6 +140,7 @@ ManifestDPIAware true Push $4 Push $5 Push $6 + ; GetTime yields zero-padded day, month, year, weekday, hour, minute, second. ${GetTime} "" "L" $0 $1 $2 $3 $4 $5 $6 StrCpy $0 "${DSH_INSTALLER_LOG_DIR}\extract-failure-$2$1$0-$4$5$6.log" StrCpy $1 1 diff --git a/apps/desktop/scripts/smoke-installer-directories.ps1 b/apps/desktop/scripts/smoke-installer-directories.ps1 index 283f168016..092750b2c1 100644 --- a/apps/desktop/scripts/smoke-installer-directories.ps1 +++ b/apps/desktop/scripts/smoke-installer-directories.ps1 @@ -8,6 +8,7 @@ param( $ErrorActionPreference = 'Stop' $Makensis = [System.IO.Path]::GetFullPath($Makensis) $SevenZip = [System.IO.Path]::GetFullPath($SevenZip) +if ($FrameLibrary) { $FrameLibrary = [System.IO.Path]::GetFullPath($FrameLibrary) } $scratch = [System.IO.Directory]::CreateTempSubdirectory('dsh-directory-smoke-').FullName $fixture = Join-Path $PSScriptRoot '../tests/fixtures/installer-directory-smoke.nsi' @@ -84,7 +85,7 @@ try { # Only an extraction failure writes a report; it must quote 7-Zip's verdict so support can read the cause. $reports = @(if (Test-Path -LiteralPath $reportDir) { Get-ChildItem -LiteralPath $reportDir -File }) if ($mode -eq 'broken') { - if ($reports.Count -ne 1 -or $reports[0].Name -notmatch '^extract-failure-\d{8}-\d{6}\.log$') { + if ($reports.Count -ne 1 -or $reports[0].Name -notmatch '^extract-failure-20\d{6}-\d{6}\.log$') { throw "Directory smoke $mode did not save exactly one extraction report" } $report = Get-Content -LiteralPath $reports[0].FullName -Raw -Encoding UTF8 diff --git a/apps/desktop/tests/windows-installer-extract-report.cpp b/apps/desktop/tests/windows-installer-extract-report.cpp index ea73fd2fd1..355d16dd94 100644 --- a/apps/desktop/tests/windows-installer-extract-report.cpp +++ b/apps/desktop/tests/windows-installer-extract-report.cpp @@ -36,21 +36,28 @@ static void WriteBytes(const std::wstring& path, const std::string& bytes) { int wmain() { using namespace extract_report; - // Result codes distinguish 7-Zip's own exit codes from Win32 failures around its process. + // Result codes distinguish 7-Zip's own exit codes, Win32 failures around its process, and raw crash statuses. assert(DescribeResult(2) == L"7-Zip exit code 2 (fatal error)"); assert(DescribeResult(9) == L"7-Zip exit code 9 (unexpected exit code)"); assert(DescribeResult(-5).rfind(L"Windows error 5 while running 7-Zip", 0) == 0); assert(Contains(DescribeResult(-ERROR_FILE_NOT_FOUND), L"Windows error 2")); + assert(DescribeResult(static_cast(0xC0000005)) == L"7-Zip terminated with status 0xC0000005"); + assert(DescribeResult(1000) == L"7-Zip terminated with status 0x000003E8"); - // The headline prefers the line naming the failing operation over the archive name 7-Zip prints first. - const std::wstring broken = L"ERROR: broken.7z\r\nbroken.7z\r\nOpen ERROR: Cannot open the file as [7z] archive\r\n\r\n\r\nERRORS:\r\nIs not archive\r\n"; - assert(Headline(2, broken) == L"Open ERROR: Cannot open the file as [7z] archive"); + // The headline prefers the line naming the failing operation; the archive path 7-Zip echoes first is skipped + // even when it contains spaces. + const std::wstring spacedArchive = L"C:\\Users\\Jane Doe\\AppData\\Local\\Temp\\nsa1F2C.tmp\\app-64.7z"; + const std::wstring broken = L"ERROR: " + spacedArchive + L"\r\napp-64.7z\r\nOpen ERROR: Cannot open the file as [7z] archive\r\n\r\n\r\nERRORS:\r\nIs not archive\r\n"; + assert(Headline(2, broken, spacedArchive) == L"Open ERROR: Cannot open the file as [7z] archive"); + assert(Headline(2, L"ERROR: app-64.7z\r\nOpen ERROR: Is not archive\r\n", spacedArchive) == L"Open ERROR: Is not archive"); const std::wstring locked = L"ERROR: Cannot delete output file : The process cannot access the file. : C:\\Apps\\Harness.new-1\\resources\\app.node\r\n"; - assert(Headline(2, locked) == Trim(locked)); - assert(Headline(-ERROR_ACCESS_DENIED, L"") == DescribeResult(-ERROR_ACCESS_DENIED)); - assert(Headline(1, L"ERROR: only-a-path\r\n") == L"ERROR: only-a-path"); + assert(Headline(2, locked, spacedArchive) == Trim(locked)); + assert(Headline(2, L"ERROR: " + spacedArchive + L"\r\n" + locked, spacedArchive) == Trim(locked)); + assert(Headline(-ERROR_ACCESS_DENIED, L"", spacedArchive) == DescribeResult(-ERROR_ACCESS_DENIED)); + assert(Headline(2, L"ERROR: " + spacedArchive + L"\r\n", spacedArchive) == DescribeResult(2)); + assert(Headline(1, L"ERROR: only a note\r\n", spacedArchive) == L"ERROR: only a note"); const std::wstring longLine = L"ERROR: Cannot open output file : " + std::wstring(400, L'x'); - const std::wstring headline = Headline(2, longLine); + const std::wstring headline = Headline(2, longLine, spacedArchive); assert(headline.size() == kHeadlineLimit && headline.back() == kEllipsis); // The report carries the result, both paths, and 7-Zip's output verbatim. @@ -62,15 +69,30 @@ int wmain() { assert(Contains(report, L"\r\n7-Zip output:\r\n" + Trim(locked) + L"\r\n")); assert(Contains(Compose(2, L"a", L"b", L" \r\n", L"t", L"w"), L"7-Zip output:\r\n(none)\r\n")); - // The excerpt is bounded by lines and characters and tells how much the saved report still holds. + // The excerpt shows the result and 7-Zip's own lines, bounded by lines and characters, and counts what it left out. std::wstring manyErrors; for (int i = 0; i < 40; ++i) manyErrors += L"ERROR: Cannot open output file : Access is denied. : C:\\Apps\\file" + std::to_wstring(i) + L".dll\r\n"; const std::wstring excerpt = Excerpt(Compose(2, L"a", L"b", manyErrors, L"t", L"w")); - assert(Lines(excerpt).size() == kExcerptLines + 1); + const std::vector excerptLines = Lines(excerpt); + assert(excerptLines.size() == kExcerptLines + 1); + assert(excerptLines[0] == L"Result: 7-Zip exit code 2 (fatal error)"); + assert(excerptLines[1].rfind(L"ERROR: Cannot open output file", 0) == 0); assert(excerpt.size() <= kExcerptChars + 64); - assert(Contains(excerpt, L" (" + std::to_wstring(48 - kExcerptLines) + L" more lines in the saved report)")); - assert(Excerpt(L"one\r\ntwo") == L"one\r\ntwo"); - assert(Excerpt(std::wstring(2000, L'x') + L"\r\nnext").size() < kExcerptLineLimit + 64); + assert(Contains(excerpt, L" (" + std::to_wstring(41 - kExcerptLines) + L" more lines in the saved report)")); + assert(!Contains(excerpt, L"Archive: ")); + assert(Excerpt(Compose(2, L"a", L"b", L"one\r\ntwo", L"t", L"w")) == L"Result: 7-Zip exit code 2 (fatal error)\r\none\r\ntwo"); + assert(Excerpt(Compose(2, L"a", L"b", std::wstring(2000, L'x'), L"t", L"w")).size() < 64 + kExcerptLineLimit + 64); + + // A cut inside a multi-byte sequence is trimmed back to a code point boundary. + std::string partial("abc\xE6\x96\x87\xE4\xBB"); + TrimPartialUtf8(partial); + assert(partial == "abc\xE6\x96\x87"); + std::string complete("abc\xE6\x96\x87"); + TrimPartialUtf8(complete); + assert(complete == "abc\xE6\x96\x87"); + std::string ascii("abc"); + TrimPartialUtf8(ascii); + assert(ascii == "abc"); // 7-Zip output arrives as UTF-8; anything else falls back to the system code page instead of vanishing. assert(Decode("Access denied: \xE6\x96\x87\xE4\xBB\xB6") == L"Access denied: \x6587\x4EF6"); From 13fe312e154a5b855a3f56c3e3ff357e1db1c9e1 Mon Sep 17 00:00:00 2001 From: lsdsjy <1356263+lsdsjy@users.noreply.github.com> Date: Tue, 22 Sep 2026 15:26:39 +0800 Subject: [PATCH 11/29] test(desktop): fix login theme CI fixtures --- apps/desktop/tests/preload.e2e.ts | 49 ++++++++++++++++++- .../tests/account.spec.ts | 16 +++--- 2 files changed, 58 insertions(+), 7 deletions(-) diff --git a/apps/desktop/tests/preload.e2e.ts b/apps/desktop/tests/preload.e2e.ts index 1926d811ee..1022b3a8b8 100644 --- a/apps/desktop/tests/preload.e2e.ts +++ b/apps/desktop/tests/preload.e2e.ts @@ -6,26 +6,73 @@ import { describe, expect, it, vi } from 'vitest' const preload = (name: string): string => fileURLToPath(new URL(`../lib/${name}.cjs`, import.meta.url)) +/** + * Browser globals a sandboxed Electron preload sees. A preload runs while the + * document is still loading, so the theme preload defers its first read to + * `DOMContentLoaded` and observes later `html[data-ds-theme-source]` changes. + * @returns context globals plus the root attribute transitions the Web UI performs. + */ +function browserEnvironment() { + const attributes = new Map() + const listeners = new Map void>>() + const observers: Array<() => void> = [] + const document = { + readyState: 'loading', + documentElement: { + dataset: {} as Record, + getAttribute: (name: string): string | null => attributes.get(name) ?? null, + setAttribute: (name: string, value: string): void => { attributes.set(name, value) }, + }, + } + const window = { + addEventListener: (type: string, listener: () => void): void => { + listeners.set(type, [...listeners.get(type) ?? [], listener]) + }, + } + class SandboxMutationObserver { + constructor(callback: () => void) { observers.push(callback) } + observe(): void {} + } + return { + globals: { document, window, MutationObserver: SandboxMutationObserver }, + /** Writes the theme root attribute and settles the document, as the theme bootstrap does before DOMContentLoaded. */ + loadTheme(value: string): void { + attributes.set('data-ds-theme-source', value) + for (const listener of listeners.get('DOMContentLoaded') ?? []) listener() + }, + /** Applies a later theme preference change through the observer the preload registered. */ + changeTheme(value: string): void { + attributes.set('data-ds-theme-source', value) + for (const observer of observers) observer() + }, + } +} + describe.skipIf(!existsSync(preload('preload-app')))('built sandboxed Desktop preloads', () => { it.each(['preload-app', 'preload-welcome'])('%s loads without filesystem module access', (name) => { const exposed = new Map>() const invoke = vi.fn(() => Promise.resolve({ languages: ['en-US'], preference: 'zh' })) const send = vi.fn() + const browser = browserEnvironment() const electron = { contextBridge: { exposeInMainWorld: (key: string, value: Record) => { exposed.set(key, value) } }, ipcRenderer: { invoke, send, on: vi.fn(), off: vi.fn() }, } runInNewContext(readFileSync(preload(name), 'utf8'), { + ...browser.globals, require: (id: string) => { if (id !== 'electron') throw new Error(`sandbox cannot load ${id}`) return electron }, process: { argv: ['electron', '--dsh-welcome-locale=en'] }, location: new URL('dsh-app://app/'), - document: { documentElement: { dataset: {} } }, exports: {}, }) if (name === 'preload-app') { + browser.loadTheme('dark') + expect(send).toHaveBeenCalledWith('dsh-desktop:native-theme-set', 'dark') + browser.changeTheme('light') + expect(send).toHaveBeenCalledWith('dsh-desktop:native-theme-set', 'light') const bridge = exposed.get('__DSH_LOCALE__') as { read(): unknown; onChange(locale: string): void } bridge.read() expect(invoke).toHaveBeenCalledWith('dsh-desktop:locale-bootstrap') diff --git a/packages/credentials/deepseek-account-platform/tests/account.spec.ts b/packages/credentials/deepseek-account-platform/tests/account.spec.ts index f1b22c47b0..e71e0d7b94 100644 --- a/packages/credentials/deepseek-account-platform/tests/account.spec.ts +++ b/packages/credentials/deepseek-account-platform/tests/account.spec.ts @@ -483,12 +483,16 @@ it('adds private deployment cookies to every Platform request without exposing t expect(JSON.stringify(await f.account.getState())).not.toContain('test_gate') await f.account.signOut() await expect.poll(f.logoutCount).toBe(1) - expect(f.receivedHeaders.map(item => item.path)).toEqual([ - '/auth-api/v0/dsh/auth_init', '/auth-api/v0/dsh/auth_exchange', - '/auth-api/v0/users/current', '/api/v0/users/get_user_summary', '/auth-api/v0/users/logout', - ]) - expect(f.receivedHeaders.every(item => item.cookie === 'test_gate=synthetic')).toBe(true) - expect(f.receivedHeaders.slice(2).every(item => item.authorization === 'dsh_mock_test')).toBe(true) + const headers = f.receivedHeaders + const paths = headers.map(item => item.path) + // The profile and wallet queries are independent requests, so their arrival order is scheduler-dependent. + expect(paths.slice(0, 2)).toEqual(['/auth-api/v0/dsh/auth_init', '/auth-api/v0/dsh/auth_exchange']) + expect(paths.slice(2, -1).sort()).toEqual(['/api/v0/users/get_user_summary', '/auth-api/v0/users/current']) + expect(paths.at(-1)).toBe('/auth-api/v0/users/logout') + expect(headers.every(item => item.cookie === 'test_gate=synthetic')).toBe(true) + const grantedPaths = new Set(['/auth-api/v0/users/current', '/api/v0/users/get_user_summary', '/auth-api/v0/users/logout']) + expect(headers.filter(item => grantedPaths.has(item.path ?? '')).every(item => item.authorization === 'dsh_mock_test')).toBe(true) + expect(headers.filter(item => !grantedPaths.has(item.path ?? '')).every(item => item.authorization === undefined)).toBe(true) }) it('rejects reserved, duplicate and malformed deployment headers without disclosing values', () => { From b6775f6d4f55eaa0bcac36318cd7dfc98d70195c Mon Sep 17 00:00:00 2001 From: turtle1999 Date: Tue, 22 Sep 2026 15:29:23 +0800 Subject: [PATCH 12/29] fix(tool-jobs): wake an idle owner for every completion by default `maxConsecutiveWakes` no longer defaults to 3. Unset, every background job completion wakes its idle owner; the cap is opt-in. With the default cap, a session chaining background commands and one-shot subagents exhausted the budget after three wakes. The fourth notice was injected into the next-step inbox without waking the owner, the client showed nothing, and the session stalled until the user typed something (dsh-external/issues#641). Closes dsh-external/issues#641 --- ...b-completion-wakes-an-idle-owner.i18n.yaml | 4 +-- ...ound-job-completion-wakes-an-idle-owner.md | 2 ++ ...d-job-completion-wakes-an-idle-owner.zh.md | 2 ++ docs/config-catalog.i18n.yaml | 4 +-- docs/config-catalog.md | 8 +++-- docs/config-catalog.zh.md | 8 +++-- packages/jobs/tool-jobs/README.i18n.yaml | 4 +-- packages/jobs/tool-jobs/README.md | 12 ++++---- packages/jobs/tool-jobs/README.zh.md | 12 ++++---- packages/jobs/tool-jobs/src/index.ts | 29 ++++++++++--------- .../jobs/tool-jobs/tests/tool-jobs.spec.ts | 19 ++++++++++-- 11 files changed, 64 insertions(+), 40 deletions(-) diff --git a/.agents/notes/implemented/feature/2026-08-11-background-job-completion-wakes-an-idle-owner.i18n.yaml b/.agents/notes/implemented/feature/2026-08-11-background-job-completion-wakes-an-idle-owner.i18n.yaml index 0c51d4b42e..a38790ad6e 100644 --- a/.agents/notes/implemented/feature/2026-08-11-background-job-completion-wakes-an-idle-owner.i18n.yaml +++ b/.agents/notes/implemented/feature/2026-08-11-background-job-completion-wakes-an-idle-owner.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-11-background-job-completion-wakes-an-idle-owner.md -2026-08-11-background-job-completion-wakes-an-idle-owner.md: b8a10a2150ead02036cb97506a25c3a51202adcf -2026-08-11-background-job-completion-wakes-an-idle-owner.zh.md: adc0770cd00adeb3b13c95dcc386464493dcd943 +2026-08-11-background-job-completion-wakes-an-idle-owner.md: 0844948eaa8e58e9d22667eb0962865a17969c07 +2026-08-11-background-job-completion-wakes-an-idle-owner.zh.md: d09454d17b8f1b579305cc1e98540d5ecb2f2d4f diff --git a/.agents/notes/implemented/feature/2026-08-11-background-job-completion-wakes-an-idle-owner.md b/.agents/notes/implemented/feature/2026-08-11-background-job-completion-wakes-an-idle-owner.md index b8a10a2150..0844948eaa 100644 --- a/.agents/notes/implemented/feature/2026-08-11-background-job-completion-wakes-an-idle-owner.md +++ b/.agents/notes/implemented/feature/2026-08-11-background-job-completion-wakes-an-idle-owner.md @@ -4,6 +4,8 @@ Status: implemented Update: the `reported` bit and `onJobDone` this note relies on left the registry with the [jobs seam consolidation](../architecture/2026-09-03-jobs-seam-consolidation.md): `dsh-tool-jobs` now keeps the delivery ledger (a wait or an accepted `job_kill` claims the task) and skips teardown settlements by their `settled` cause, so the wake-or-inject decision below stands while the mechanism it names is the tool's ledger, not a registry flag. +Update: `maxConsecutiveWakes` no longer defaults to 3; unset, every idle completion wakes its owner. The accepted risk below — a spent budget is restored only by user input — was reported as a bug ([dsh-external/issues#641](https://github.com/dsh-external/issues/issues/641)): a session mixing background commands and one-shot subagents exhausted the budget after three wakes, the fourth notice parked silently in the next-step inbox with nothing visible in the client, and the model's "you are notified when a job finishes" promise turned false exactly when the user was away. An invisible stall costs more than an unbounded chain of model requests the user can watch and stop, so the cap is opt-in. The self-exciting rationale for the field stands for deployments that set it. + English | [中文](2026-08-11-background-job-completion-wakes-an-idle-owner.zh.md) ## Problem diff --git a/.agents/notes/implemented/feature/2026-08-11-background-job-completion-wakes-an-idle-owner.zh.md b/.agents/notes/implemented/feature/2026-08-11-background-job-completion-wakes-an-idle-owner.zh.md index adc0770cd0..d09454d17b 100644 --- a/.agents/notes/implemented/feature/2026-08-11-background-job-completion-wakes-an-idle-owner.zh.md +++ b/.agents/notes/implemented/feature/2026-08-11-background-job-completion-wakes-an-idle-owner.zh.md @@ -4,6 +4,8 @@ Status: implemented Update:本文依赖的 `reported` 位与 `onJobDone` 已随 [jobs seam 收敛](../architecture/2026-09-03-jobs-seam-consolidation.zh.md)离开注册表:`dsh-tool-jobs` 现在持有投递台账(等待或被接受的 `job_kill` 认领任务),并按 `settled` 事件的 cause 跳过 teardown 结算,因此下文唤醒或注入的决策仍然成立,只是它提到的机制是工具的台账而非注册表标志。 +Update:`maxConsecutiveWakes` 不再默认为 3;未设置时每次空闲完成都会唤醒所有者。下文"已花掉的预算只由用户输入恢复"这条接受的风险被报告为缺陷([dsh-external/issues#641](https://github.com/dsh-external/issues/issues/641)):一个会话混用后台命令与一次性子代理,三次唤醒后预算耗尽,第四条通知静默停在 next-step inbox 里,客户端毫无显示,而模型得到的"任务完成会通知你"承诺恰好在用户离开时失效。不可见的停摆比一条用户能看到并能停止的、无上限的模型请求链代价更高,因此上限改为可选。自激链的理由对设置了该字段的部署依然成立。 + [English](2026-08-11-background-job-completion-wakes-an-idle-owner.md) | 中文 ## 问题 diff --git a/docs/config-catalog.i18n.yaml b/docs/config-catalog.i18n.yaml index 22a29bf6ac..5b3de07b40 100644 --- a/docs/config-catalog.i18n.yaml +++ b/docs/config-catalog.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/config-catalog.md -config-catalog.md: f86f02fbec949c0212c3c038f47d1fdf50d239fe -config-catalog.zh.md: d56d5bdef41e76ce7a41e3d582a1a8afde18766b +config-catalog.md: a9616098f2e5adfb7061bec0dc8d66c7600f91e3 +config-catalog.zh.md: d53d3a93923c45e04820c10204b8380feb2d2da2 diff --git a/docs/config-catalog.md b/docs/config-catalog.md index f86f02fbec..a9616098f2 100644 --- a/docs/config-catalog.md +++ b/docs/config-catalog.md @@ -3405,9 +3405,11 @@ export interface Config { completionDelivery?: CompletionDelivery /** * Turns one owner may have opened by completion wakes before the next - * notice degrades to injection, reset by any user-authored input (default 3). - * Bounds the self-exciting chain where a woken turn starts the job whose - * completion wakes it again. + * notice degrades to injection, reset by any user-authored input. Absent by + * default: every idle completion wakes its owner. Set it to bound the + * self-exciting chain where a woken turn starts the job whose completion + * wakes it again, at the cost of notices past the cap waiting silently for + * the next user input. */ maxConsecutiveWakes?: number } diff --git a/docs/config-catalog.zh.md b/docs/config-catalog.zh.md index d56d5bdef4..d53d3a9392 100644 --- a/docs/config-catalog.zh.md +++ b/docs/config-catalog.zh.md @@ -3407,9 +3407,11 @@ export interface Config { completionDelivery?: CompletionDelivery /** * Turns one owner may have opened by completion wakes before the next - * notice degrades to injection, reset by any user-authored input (default 3). - * Bounds the self-exciting chain where a woken turn starts the job whose - * completion wakes it again. + * notice degrades to injection, reset by any user-authored input. Absent by + * default: every idle completion wakes its owner. Set it to bound the + * self-exciting chain where a woken turn starts the job whose completion + * wakes it again, at the cost of notices past the cap waiting silently for + * the next user input. */ maxConsecutiveWakes?: number } diff --git a/packages/jobs/tool-jobs/README.i18n.yaml b/packages/jobs/tool-jobs/README.i18n.yaml index f6b8dc12ed..d76b088fdc 100644 --- a/packages/jobs/tool-jobs/README.i18n.yaml +++ b/packages/jobs/tool-jobs/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/jobs/tool-jobs/README.md -README.md: 38cf89961d3bbf13d803bef206cbe843726f31ab -README.zh.md: 9a6c1c01103f03c5e9915094714bcecadf473042 +README.md: 2836f10e160ae3ecfe9a2df7f6b82a88b4ddf33f +README.zh.md: b5b702ab5f8ca4c72545f3e46899a3f01624eb42 diff --git a/packages/jobs/tool-jobs/README.md b/packages/jobs/tool-jobs/README.md index 38cf89961d..2836f10e16 100644 --- a/packages/jobs/tool-jobs/README.md +++ b/packages/jobs/tool-jobs/README.md @@ -9,7 +9,7 @@ English | [中文](README.zh.md) ## Summary -Use `dsh-tool-jobs` to inspect and control background commands, PTY work, and subagents through `job_output`, `job_list`, and `job_kill`. Reads can wait within a configured timeout, list results identify each job's kind and status, and cancellation settles only after the work stops. When owned work finishes, the agent receives an in-session notice: busy agents receive it in their next step, while idle agents may be woken by a bounded follow-up turn. Configuration controls wait limits, completion delivery, and consecutive wakeups. Stream output is consumed by one reader, and pending notices do not survive owner disposal. +Use `dsh-tool-jobs` to inspect and control background commands, PTY work, and subagents through `job_output`, `job_list`, and `job_kill`. Reads can wait within a configured timeout, list results identify each job's kind and status, and cancellation settles only after the work stops. When owned work finishes, the agent receives an in-session notice: busy agents receive it in their next step, while idle agents are woken by a follow-up turn. Configuration controls wait limits, completion delivery, and an optional cap on consecutive wakeups. Stream output is consumed by one reader, and pending notices do not survive owner disposal. ## Table of Contents @@ -39,7 +39,7 @@ The three tools return `{ text, job }`, `PublicJobSnapshot[]`, and `{ outcome: ' When a job finishes, the owning agent receives `background job (:
diff --git a/packages/client/ui-settings-account/src/client/AccountOnboarding.tsx b/packages/client/ui-settings-account/src/client/AccountOnboarding.tsx index 8dfcb08c48..e07c81c6db 100644 --- a/packages/client/ui-settings-account/src/client/AccountOnboarding.tsx +++ b/packages/client/ui-settings-account/src/client/AccountOnboarding.tsx @@ -6,12 +6,13 @@ import type { AccountSectionInjected } from './AccountSection.tsx' import { SignInDialog } from './SignInDialog.tsx' /** @param props - onboarding completion, account state and actions. @returns account dialog while signed out. */ -export function AccountOnboarding({ complete, useApiKey, useAccount, setOnboarding, showLogin, start, cancel, t }: +export function AccountOnboarding({ complete, useApiKey, useAccount, useTheme, setOnboarding, showLogin, start, cancel, t }: PropsRuntime<'settings.models.sign-in'> & PropsLocale<'settings.account'> & InjectFace) { const account = useAccount(value => value) + const colorScheme = useTheme(snapshot => snapshot.active.colorScheme) useEffect(() => { setOnboarding(true); return () => { setOnboarding(false) } }, [setOnboarding]) useEffect(() => { if (account.view?.status === 'credential-stored') complete() }, [account.view?.status, complete]) if (!account.view || account.view.status === 'credential-stored') return null - return { showLogin(false); complete() }} useApiKey={() => { showLogin(false); useApiKey() }} /> } diff --git a/packages/client/ui-settings-account/src/client/AccountSection.tsx b/packages/client/ui-settings-account/src/client/AccountSection.tsx index 89616b9cc8..1dccd18f84 100644 --- a/packages/client/ui-settings-account/src/client/AccountSection.tsx +++ b/packages/client/ui-settings-account/src/client/AccountSection.tsx @@ -4,9 +4,11 @@ import { useEffect, useState } from 'react' import { Button, IconRightUpOutlineRegular } from '@deepseek-ai/dsh-client-ui-primitives' import type { AccountDetails, AccountView, SignInAttemptId } from '@deepseek-ai/dsh-deepseek-account/types' import type { PropsRuntime, PropsLocale, InjectFace, HostObservable } from '@deepseek-ai/dsh-client-ui-slots' +import type { ThemeSnapshot } from '@deepseek-ai/dsh-client-ui-theme/client' import { PlatformOverlay, type PlatformBridge } from './PlatformOverlay.tsx' import { formatBalance } from './formatBalance.ts' import { AccountAvatar } from './AccountAvatar.tsx' +import { authorizeUrlWithTheme } from './authorize-url.ts' import css from './AccountSection.module.css' /** Safe account snapshot shared by the settings page and launcher. */ @@ -30,8 +32,12 @@ export interface AccountSectionInjected { /** Desktop-only commands; absent in ordinary browsers. */ platform?: PlatformBridge - /** Host-owned account stream observed through framework hooks. */ - hooks: { account: HostObservable } + /** Host-owned account stream and theme snapshots observed through framework hooks. */ + hooks: { + account: HostObservable + /** Palette the Platform login pages follow. */ + theme: HostObservable + } /** @returns after account details are refreshed; concurrent refreshes share a request. */ refresh: () => Promise /** Open the external support questionnaire with the current account and environment. */ @@ -51,8 +57,9 @@ export interface AccountSectionInjected { export type AccountSectionProps = PropsRuntime<'settings.section'> & PropsLocale<'settings.account'> & InjectFace /** @param props - localized actions and account subscription. @returns account settings UI. */ -export function AccountSection({ t, useAccount, start, cancel, refresh, platform }: AccountSectionProps) { +export function AccountSection({ t, useAccount, useTheme, start, cancel, refresh, platform }: AccountSectionProps) { const { view: state, details, failed: streamFailed } = useAccount(value => value) + const colorScheme = useTheme(snapshot => snapshot.active.colorScheme) const [platformPage, setPlatformPage] = useState<'usage' | 'top-up'>() const [failed, setFailed] = useState(false) const [busy, setBusy] = useState(false) @@ -107,7 +114,8 @@ export function AccountSection({ t, useAccount, start, cancel, refresh, platform }
{active &&
- {attempt.authorizeUrl && + {attempt.authorizeUrl && {t('open')} }
-
└ +{added} -{removed} · {labels.files(files)}
) } diff --git a/packages/client/ui-primitives/src/markdown/CodeBlock.module.css b/packages/client/ui-primitives/src/markdown/CodeBlock.module.css index 49bcfe33a7..fa76358887 100644 --- a/packages/client/ui-primitives/src/markdown/CodeBlock.module.css +++ b/packages/client/ui-primitives/src/markdown/CodeBlock.module.css @@ -105,7 +105,7 @@ } .card :where(pre) { - padding: 6px 18px 16px; + padding: 6px 22px 20px; word-break: normal; overflow-wrap: anywhere; } diff --git a/packages/client/ui-primitives/src/markdown/CodeBlock.tsx b/packages/client/ui-primitives/src/markdown/CodeBlock.tsx index 8eb85821b9..51d175393d 100644 --- a/packages/client/ui-primitives/src/markdown/CodeBlock.tsx +++ b/packages/client/ui-primitives/src/markdown/CodeBlock.tsx @@ -36,7 +36,7 @@ export interface CodeBlockProps { copyLabel: string /** Copy-button label during the post-copy confirmation window. */ copiedLabel: string - /** Enable the shared card toolbar and spacing; omit for owner-styled source or compact views. */ + /** Enable the shared card toolbar and spacing; omit for custom toolbar layouts. */ toolbarLabels?: CodeToolbarLabels | undefined /** With toolbarLabels, use the owner's wrapping preference and omit the toolbar's local wrap action. */ wrap?: boolean | undefined diff --git a/packages/client/ui-primitives/src/markdown/MarkdownText.module.css b/packages/client/ui-primitives/src/markdown/MarkdownText.module.css index db318ac6eb..e3c5b31953 100644 --- a/packages/client/ui-primitives/src/markdown/MarkdownText.module.css +++ b/packages/client/ui-primitives/src/markdown/MarkdownText.module.css @@ -401,24 +401,6 @@ z-index: auto; } -.compact [data-code-block-banner] { - padding: 4px 8px; - font: inherit; -} - -.compact [data-code-block-banner] > :first-child { - font-size: inherit; - line-height: inherit; - color: inherit; -} - -.compact pre { - margin: 4px 0; - padding: 8px; - font-size: inherit; - line-height: inherit; -} - /* Shiki writes token colors inline; compact code uses the surrounding text color. */ .compact pre, .compact pre :is(code, span) { diff --git a/packages/client/ui-primitives/src/markdown/MarkdownText.tsx b/packages/client/ui-primitives/src/markdown/MarkdownText.tsx index 25b9a00172..ab2c0b380a 100644 --- a/packages/client/ui-primitives/src/markdown/MarkdownText.tsx +++ b/packages/client/ui-primitives/src/markdown/MarkdownText.tsx @@ -172,7 +172,7 @@ class StreamingRenderer { * absolute HTTP(S) images render directly. */ export const MarkdownText = memo(function MarkdownText({ - text, streaming = false, labels: providedLabels, fileMentions, pathImages, variant = 'body', + text, streaming = false, labels, fileMentions, pathImages, variant = 'body', }: { text: string streaming?: boolean @@ -181,9 +181,6 @@ export const MarkdownText = memo(function MarkdownText({ pathImages?: MarkdownPathImages | undefined variant?: 'body' | 'compact' }) { - const labels = useMemo(() => variant === 'compact' - ? { ...providedLabels, code: { ...providedLabels.code, toolbarLabels: undefined } } - : providedLabels, [providedLabels, variant]) const streamRef = useRef(null) const streamLabelsRef = useRef(labels) const children = useMemo(() => { diff --git a/packages/client/ui-primitives/src/markdown/render.tsx b/packages/client/ui-primitives/src/markdown/render.tsx index a7bb8a2365..84a9c2857a 100644 --- a/packages/client/ui-primitives/src/markdown/render.tsx +++ b/packages/client/ui-primitives/src/markdown/render.tsx @@ -37,7 +37,7 @@ export interface MarkdownCodeLabels { copyLabel: string /** Copy-button label during the post-copy confirmation window. */ copiedLabel: string - /** Shared card controls; omitted in compact and owner-styled source views. */ + /** Shared card controls; omitted for custom toolbar layouts. */ toolbarLabels?: CodeToolbarLabels | undefined } diff --git a/packages/client/ui-primitives/tests/code-card-controls.client.spec.tsx b/packages/client/ui-primitives/tests/code-card-controls.client.spec.tsx index e4b152650f..62d448f499 100644 --- a/packages/client/ui-primitives/tests/code-card-controls.client.spec.tsx +++ b/packages/client/ui-primitives/tests/code-card-controls.client.spec.tsx @@ -78,11 +78,13 @@ describe('code-card controls', () => { } }) - it('preserves compact Markdown and owner-styled source controls', () => { + it('shows compact Markdown icon actions and preserves custom source controls', () => { const view = render() - expect(screen.queryByRole('button', { name: 'Wrap lines' })).toBeNull() - expect(screen.queryByRole('button', { name: 'Do not wrap lines' })).toBeNull() - expect(screen.getByRole('button', { name: 'Copy' }).textContent).toBe('Copy') + const wrap = screen.getByRole('button', { name: 'Wrap lines' }) + expect(wrap.getAttribute('aria-pressed')).toBe('true') + fireEvent.click(wrap) + expect(wrap.getAttribute('aria-pressed')).toBe('false') + expect(screen.getByRole('button', { name: 'Copy' }).textContent).toBe('') view.rerender() expect(screen.getByRole('button', { name: 'Copy' }).textContent).toBe('Copy') }) diff --git a/packages/client/ui-primitives/tests/diff-block.client.spec.tsx b/packages/client/ui-primitives/tests/diff-block.client.spec.tsx index 391fbfda51..2aaa72501b 100644 --- a/packages/client/ui-primitives/tests/diff-block.client.spec.tsx +++ b/packages/client/ui-primitives/tests/diff-block.client.spec.tsx @@ -75,18 +75,15 @@ describe('DiffBlock structure', () => { }) it('treats a trailing newline as a terminator, not an extra blank line', () => { - // A create whose newText ends in a newline is one added line, not two, and - // the footer counts one — the phantom `+ ` empty line the naive split drew. const { container } = render() expect(changeRows(container)).toEqual(['hello']) - expect(screen.getByText('└ +1 -0 · 1 file')).toBeTruthy() }) it('renders a full deletion as removed-only with no phantom added line', () => { // newText '' is zero added lines: an empty string must contribute nothing. const { container } = render() expect(container.querySelectorAll('[class*="_add_"]').length).toBe(0) - expect(screen.getByText('└ +0 -2 · 1 file')).toBeTruthy() + expect(changeRows(container)).toEqual(['a', 'b']) }) it('keeps a genuine interior blank line', () => { @@ -105,7 +102,6 @@ describe('DiffBlock local changes', () => { const total = count === 128 ? count : count + 1 render() expect(diffTotals(diffs)).toEqual({ added: total, removed: total }) - expect(screen.getByText(`└ +${total} -${total} · 1 file`)).toBeTruthy() await act(async () => { fireEvent.click(screen.getByRole('button', { name: '复制' })) }) expect(writeText).toHaveBeenCalledWith(count === 128 ? ['large.txt', ' shared context', ...oldLines.slice(1).map(line => `- ${line}`), ...newLines.slice(1).map(line => `+ ${line}`)].join('\n') @@ -132,7 +128,6 @@ describe('DiffBlock local changes', () => { render() expect(screen.getAllByText('start')).toHaveLength(1) expect(screen.getAllByText('end')).toHaveLength(1) - expect(screen.getByText('└ +1 -1 · 1 file')).toBeTruthy() expect(diffTotals(diffs)).toEqual({ added: 1, removed: 1 }) await act(async () => { fireEvent.click(screen.getByRole('button', { name: '复制' })) }) expect(writeText).toHaveBeenCalledWith('settings.ts\n start\n- mode = 1\n+ mode = 2\n end') @@ -150,7 +145,6 @@ describe('DiffBlock local changes', () => { 'item 40', 'changed 40', 'item 41', 'item 42', 'item 43', ]) expect(changeRows(container)).toEqual(['item 10', 'changed 10', 'item 40', 'changed 40']) - expect(screen.getByText('└ +2 -2 · 1 file')).toBeTruthy() }) it.each([ @@ -163,26 +157,10 @@ describe('DiffBlock local changes', () => { ['a\n\nb', 'a\nb', 0, 1], ])('counts ordered changes in %j → %j', (oldText, newText, added, removed) => { const diffs = [{ path: 'a.txt', oldText, newText }] - render() + const { container } = render() expect(diffTotals(diffs)).toEqual({ added, removed }) - expect(screen.getByText(`└ +${added} -${removed} · 1 file`)).toBeTruthy() - }) -}) - -describe('DiffBlock footer', () => { - it('counts added and removed lines and one file', () => { - const diffs: DiffHunk[] = [{ path: 'a.ts', oldText: 'a\nb', newText: 'c' }] - render() - expect(screen.getByText('└ +1 -2 · 1 file')).toBeTruthy() - }) - - it('pluralizes the distinct-file count', () => { - const diffs: DiffHunk[] = [ - { path: 'a.ts', oldText: null, newText: 'x' }, - { path: 'b.ts', oldText: null, newText: 'y' }, - ] - render() - expect(screen.getByText('└ +2 -0 · 2 files')).toBeTruthy() + expect(container.querySelectorAll('[class*="_add_"]')).toHaveLength(added) + expect(container.querySelectorAll('[class*="_del_"]')).toHaveLength(removed) }) }) diff --git a/packages/client/ui-primitives/tests/labels.client.ts b/packages/client/ui-primitives/tests/labels.client.ts index 80b8cb7305..4d5ae803ad 100644 --- a/packages/client/ui-primitives/tests/labels.client.ts +++ b/packages/client/ui-primitives/tests/labels.client.ts @@ -18,7 +18,6 @@ export const diffBlockLabels: DiffBlockLabels = { copy: '复制', copied: '复制成功', collapseAria: '收起差异', expandAria: hidden => `展开其余 ${hidden} 行差异`, collapse: '收起', expand: hidden => `… 其余 ${hidden} 行`, - files: count => `${count} ${count === 1 ? 'file' : 'files'}`, } export const readBlockLabels: ReadBlockLabels = { diff --git a/packages/client/ui-sidebar-documentpreview/README.i18n.yaml b/packages/client/ui-sidebar-documentpreview/README.i18n.yaml index c2720b1ea6..b175a9411b 100644 --- a/packages/client/ui-sidebar-documentpreview/README.i18n.yaml +++ b/packages/client/ui-sidebar-documentpreview/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-sidebar-documentpreview/README.md -README.md: d818feaa2cc6bff2f8400ef122e8496df6e45cfc -README.zh.md: e881f4a844708eee17945ec5ac15e17e85baa6fd +README.md: 30d3a10470682a649ea382f8d2bb07ff104f388f +README.zh.md: cabfb262e8e20ecdf7a281ca5187aaa6c050bcce diff --git a/packages/client/ui-sidebar-documentpreview/README.md b/packages/client/ui-sidebar-documentpreview/README.md index d818feaa2c..30d3a10470 100644 --- a/packages/client/ui-sidebar-documentpreview/README.md +++ b/packages/client/ui-sidebar-documentpreview/README.md @@ -61,7 +61,7 @@ PNG, JPEG, GIF, WebP, BMP, ICO, and SVG render through Blob URLs in an `` s Shared copy comes from `sidebarDocumentPreview`; each builtin renderer owns its localized labels. PDF and converted Office previews use a graphite background in light mode and a matte-black background in dark mode, with subtle page shadows and original document colors. PDF and image previews share a floating control with **Fit width**, 25%, 50%, 100%, 150%, and 200% choices plus 25% incremental zoom across the 25%–400% fixed range. Fit width is the default and tracks pane resizing; 100% means the PDF's 96-DPI page size or the image's intrinsic CSS-pixel size. On fine pointers, the control starts hidden, slides up when the pointer enters the bottom 72 CSS pixels, and slides down after a 420 ms leave delay; hover, keyboard focus, an open menu, and an active gesture keep it visible, while devices without hover keep it visible continuously. Chromium maps a macOS trackpad pinch to the same live, pointer-anchored path as Ctrl+wheel; the control displays the gesture percentage, and the settled value survives body remounts until the tab closes. HTML previews do not expose zoom controls. -Initial reads, additional pages, and HTML/PDF/image preparation share the ongoing `StateDot` loader, which exposes its label to assistive technology and respects reduced-motion preferences; every wait before content exists centres the loader in the pane, so opening a file shows one indicator in one position until the body appears. Loaded pages stay visible while another page loads. The PDF body loads its package-local `client.pdf.js` chunk only when a PDF preview mounts; PDF.js, its Worker source, and embedded support data stay out of the startup `client.js`. PDF pages fill the pane's width edge to edge as one vertical sequence and render lazily near the viewport; an unrendered page holds its place as a quiet 3:4 placeholder block. PDF.js’s official TextLayerBuilder manages selection boundaries and normalized copying over an aligned text layer. Its companion styles keep blank line breaks unhighlighted; alignment accounts for PDF page units, page rotation, and viewport resizing, and page disposal cancels both layers. Image-only PDFs contain no selectable text. Code previews show a secondary-colored language label and a copy icon with a tooltip; wrapping remains in the document toolbar. They show source line numbers by default without including them in copied text; plain text uses the same font size and line height as code. Code sits on the pane's own background rather than the chat card's fill; its banner is adjacent to a full-height inner scrollport, so both scrollbars begin below the copy control. +Initial reads, additional pages, and HTML/PDF/image preparation share the ongoing `StateDot` loader, which exposes its label to assistive technology and respects reduced-motion preferences; every wait before content exists centres the loader in the pane, so opening a file shows one indicator in one position until the body appears. Loaded pages stay visible while another page loads. The PDF body loads its package-local `client.pdf.js` chunk only when a PDF preview mounts; PDF.js, its Worker source, and embedded support data stay out of the startup `client.js`. PDF pages fill the pane's width edge to edge as one vertical sequence and render lazily near the viewport; an unrendered page holds its place as a quiet 3:4 placeholder block. PDF.js’s official TextLayerBuilder manages selection boundaries and normalized copying over an aligned text layer. Its companion styles keep blank line breaks unhighlighted; alignment accounts for PDF page units, page rotation, and viewport resizing, and page disposal cancels both layers. Image-only PDFs contain no selectable text. Code previews show a tertiary-colored language label and a copy icon with a tooltip; wrapping remains in the document toolbar. They show source line numbers by default without including them in copied text; plain text uses the same font size and line height as code. Code sits on the pane's own background rather than the chat card's fill; its banner is adjacent to a full-height inner scrollport, so both scrollbars begin below the copy control. ## Excel preview diff --git a/packages/client/ui-sidebar-documentpreview/README.zh.md b/packages/client/ui-sidebar-documentpreview/README.zh.md index e881f4a844..cabfb262e8 100644 --- a/packages/client/ui-sidebar-documentpreview/README.zh.md +++ b/packages/client/ui-sidebar-documentpreview/README.zh.md @@ -61,7 +61,7 @@ PNG、JPEG、GIF、WebP、BMP、ICO 和 SVG 通过 Blob URL 在 `` 静态 共享文案来自 `sidebarDocumentPreview`;各内置渲染器拥有自己的本地化标签。PDF 与转换后的 Office 预览在浅色模式下使用石墨灰底色,在深色模式下使用哑黑底色,页面带有轻微阴影并保留文档原色。PDF 与图片预览共用浮动控件,提供**适应宽度**、25%、50%、100%、150% 和 200% 选项,并在 25%–400% 固定范围内按 25% 逐级缩放。适应宽度是默认模式并跟随面板尺寸;100% 表示 PDF 的 96 DPI 页面尺寸或图片的固有 CSS 像素尺寸。在精细指针设备上,控件初始隐藏;指针进入底部 72 个 CSS 像素时向上滑入,离开 420 ms 后向下退出;控件悬停、键盘焦点、菜单展开和手势进行期间保持显示,无 hover 的设备则始终显示。Chromium 将 macOS 触控板捏合映射到与 Ctrl+滚轮相同的实时指针锚定路径;控件同步显示手势比例,静止后的值在正文重新挂载后继续保留,直至 tab 关闭。HTML 预览不显示缩放控件。 -首次读取、追加页及 HTML/PDF/图片准备共用 ongoing `StateDot` loading,其标签暴露给辅助技术,并遵循减少动态效果偏好;内容出现前的每个等待都把 loading 居中在面板中,打开文件到正文出现始终是同一位置的一个标记。下一页加载期间保留已显示的内容。PDF 正文仅在 PDF 预览挂载时加载包内 `client.pdf.js` chunk;PDF.js、Worker 源码和内嵌支持数据不会进入启动 `client.js`。PDF 页面贴边占满面板宽度,组成一个纵向连续序列并在接近视口时惰性渲染;未渲染的页以安静的 3:4 占位块保持位置。PDF.js 官方 TextLayerBuilder 在与画面重合的文字层上管理选区边界和复制文本规范化。配套样式不高亮空白换行;对齐同时考虑 PDF 页面单位、页面旋转与视口宽度变化,页面释放时取消两层渲染。纯图片 PDF 不包含可选取的文字。代码预览使用 secondary 色的语言名称和带提示的复制图标;换行仍由文档工具栏控制。默认显示源码行号,但复制文本不包含行号;纯文本与代码使用相同字号和行高。代码直接坐在分栏自身的背景上,而不是会话卡片的填充色;复制条与占满剩余高度的内部滚动区相邻,因此横纵滚动条都从复制控件下方开始。 +首次读取、追加页及 HTML/PDF/图片准备共用 ongoing `StateDot` loading,其标签暴露给辅助技术,并遵循减少动态效果偏好;内容出现前的每个等待都把 loading 居中在面板中,打开文件到正文出现始终是同一位置的一个标记。下一页加载期间保留已显示的内容。PDF 正文仅在 PDF 预览挂载时加载包内 `client.pdf.js` chunk;PDF.js、Worker 源码和内嵌支持数据不会进入启动 `client.js`。PDF 页面贴边占满面板宽度,组成一个纵向连续序列并在接近视口时惰性渲染;未渲染的页以安静的 3:4 占位块保持位置。PDF.js 官方 TextLayerBuilder 在与画面重合的文字层上管理选区边界和复制文本规范化。配套样式不高亮空白换行;对齐同时考虑 PDF 页面单位、页面旋转与视口宽度变化,页面释放时取消两层渲染。纯图片 PDF 不包含可选取的文字。代码预览使用 tertiary 色的语言名称和带提示的复制图标;换行仍由文档工具栏控制。默认显示源码行号,但复制文本不包含行号;纯文本与代码使用相同字号和行高。代码直接坐在分栏自身的背景上,而不是会话卡片的填充色;复制条与占满剩余高度的内部滚动区相邻,因此横纵滚动条都从复制控件下方开始。 ## Excel 预览 diff --git a/packages/client/ui-tool/README.i18n.yaml b/packages/client/ui-tool/README.i18n.yaml index 45be7c0b8f..b5dd281e0e 100644 --- a/packages/client/ui-tool/README.i18n.yaml +++ b/packages/client/ui-tool/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-tool/README.md -README.md: e26a277028d41420c4796b4678a2d6897d592872 -README.zh.md: 63d34c640571b0b3e363f6968221d15eea70ad49 +README.md: 622dbd89c93f8a21bece72f2267613a4fa81b4d6 +README.zh.md: c3fec14cb7a5d2e2448743204b59dcac73380849 diff --git a/packages/client/ui-tool/README.md b/packages/client/ui-tool/README.md index e26a277028..622dbd89c9 100644 --- a/packages/client/ui-tool/README.md +++ b/packages/client/ui-tool/README.md @@ -68,7 +68,7 @@ Tool owner props forward Chat's stable `useDisclosure` Hook through root and nes Every card is read in place in the call tree; there is no second, full-height presentation of a selected call. Row renderers share one pure card model for each terminal, read, diff, search, and web card, and the image card's gallery renders through the tool-owned `tool.call.images` slot. These models validate raw call arguments, result content, failure state, persisted metadata, PTC dispatch `parentCallId`, and Session path facts. Unsupported or malformed inputs use flattened Tool result text. A file-path summary opens the file through the owner's `openFile`, which the chat view routes to the right Sidebar's text preview; `inspect` opens the trajectory view and is absent when that View is unavailable; cards then omit Inspect. Card-specific limits and fallback rules for the terminal, diff, read, search, and web cards remain in [the ui-primitives README](../ui-primitives/README.md); the image card's model in this package carries its own fallback rules. -Chat diff cards keep nine rows before folding, enough for a file header, one removed/added pair, and three context lines on either side. The collapsed row and expanded footer share the primitive's exact or coarse-replacement counts. +Chat diff cards keep nine rows before folding, enough for a file header, one removed/added pair, and three context lines on either side. The tool row shows the primitive's exact or coarse-replacement counts; the expanded card contains the diff body without a totals footer. An Auto denial takes precedence over keyed specialized views. Its generic row preserves the call identity, omits raw arguments, and normalizes the stored reason only for display: trim surrounding whitespace and collapse line separators to spaces, with localized fallback for an empty result. Session and SDK error details keep the original reason. diff --git a/packages/client/ui-tool/README.zh.md b/packages/client/ui-tool/README.zh.md index 63d34c6405..c3fec14cb7 100644 --- a/packages/client/ui-tool/README.zh.md +++ b/packages/client/ui-tool/README.zh.md @@ -68,7 +68,7 @@ Tool 所有者属性将 Chat 注入的稳定 `useDisclosure` 钩子传给根调 每张卡片都直接在调用树中查看;选中调用后不会再显示第二个全高视图。行 renderer 为 terminal、read、diff、search 和 web 卡片各复用同一个纯 card model,image 卡片的图库经由工具自有 `tool.call.images` slot 渲染。这些 model 校验原始调用参数、结果内容、失败状态、持久 metadata、PTC dispatch 的 `parentCallId` 与会话路径信息。不受支持或格式错误的输入使用压平的工具结果文本。文件路径摘要经属主的 `openFile` 打开文件,chat 视图把它路由到右侧 Sidebar 的文本预览;`inspect` 打开轨迹视图;该视图不可用时不提供此回调,卡片随之隐藏 Inspect。terminal、diff、read、search 与 web 卡片的上限与 fallback 规则仍由 [ui-primitives README](../ui-primitives/README.zh.md) 负责;image 卡片的 fallback 规则由本包内的 card model 自行承载。 -Chat diff 卡片在折叠前保留九行,足以容纳文件标题、一对删除与新增行及两侧各三行上下文。折叠工具行与展开卡片底部采用原语一致的精确或粗粒度替换统计。 +Chat diff 卡片在折叠前保留九行,足以容纳文件标题、一对删除与新增行及两侧各三行上下文。工具行显示原语提供的精确或粗粒度替换统计;展开卡片包含差异正文,不显示底部统计。 Auto 拒绝优先于按工具名选择的专门视图。其通用行保留调用身份、省略原始参数,并且只在显示时归一化存储的理由:去除首尾空白,把行分隔符折叠为空格,结果为空时使用本地化通用理由。Session 与 SDK 错误详情保留原始理由。 diff --git a/packages/client/ui-tool/src/client/tool/components/ToolRow.tsx b/packages/client/ui-tool/src/client/tool/components/ToolRow.tsx index 308624227d..228b6e9a94 100644 --- a/packages/client/ui-tool/src/client/tool/components/ToolRow.tsx +++ b/packages/client/ui-tool/src/client/tool/components/ToolRow.tsx @@ -171,9 +171,8 @@ export const ToolRow = memo(function ToolRow({ // amber while retaining the business icon and hidden state announcement. const failureLine = state === 'error' ? errorSummary ?? normalSummary : null const summaryText = failureLine ?? normalSummary - // A diff row's collapsed line carries the card's +/- totals (the same - // numbers the expanded footer prints) so the change size reads without - // expanding; an explicit summarySuffix (none today on diff rows) wins. + // The tool row keeps the diff's +/- totals visible while its body is collapsed. + // An explicit summarySuffix overrides the diff totals. const diffStat = useMemo(() => { if (diffBody === null) return null const { added, removed } = diffTotals(diffBody.card.diffs) diff --git a/packages/client/ui-tool/src/client/tool/models/primitive-labels.ts b/packages/client/ui-tool/src/client/tool/models/primitive-labels.ts index af1e13679b..4aa7477f4c 100644 --- a/packages/client/ui-tool/src/client/tool/models/primitive-labels.ts +++ b/packages/client/ui-tool/src/client/tool/models/primitive-labels.ts @@ -47,7 +47,6 @@ export function diffBlockLabels(t: T): DiffBlockLabels { expandAria: count => t('diff.expandAria', { count }), collapse: t('collapse'), expand: count => t('diff.expandRest', { count }), - files: count => t(count === 1 ? 'diff.files.one' : 'diff.files.other', { count }), } } diff --git a/packages/client/ui-tool/tests/diff-card.client.spec.tsx b/packages/client/ui-tool/tests/diff-card.client.spec.tsx index cbb4d46d0f..7be88bb9d6 100644 --- a/packages/client/ui-tool/tests/diff-card.client.spec.tsx +++ b/packages/client/ui-tool/tests/diff-card.client.spec.tsx @@ -246,9 +246,9 @@ describe('FileMutationRow diff card', () => { }), 'write')} />) // The collapsed row already carries the card's +/- totals beside the path. expect(view.getByText('+1 -0')).toBeTruthy() - // The footer counts live inside the collapsed diff card. toggleRow(view) - expect(view.getByText('└ +1 -0 · 1 个文件')).toBeTruthy() + expect(view.getAllByText('+1 -0')).toHaveLength(1) + expect(view.getByText('hello fixture')).toBeTruthy() }) it('reflects the run state on its leading slot', () => { diff --git a/packages/client/ui-tool/tests/tool-row.client.spec.tsx b/packages/client/ui-tool/tests/tool-row.client.spec.tsx index 050f8cc42b..723f2eb359 100644 --- a/packages/client/ui-tool/tests/tool-row.client.spec.tsx +++ b/packages/client/ui-tool/tests/tool-row.client.spec.tsx @@ -301,7 +301,7 @@ describe('ToolRow', () => { expect(view.getByText('List files')).toBeTruthy() }) - it('excludes shared context from collapsed edit totals and the expanded card', () => { + it('shows totals once and shared context once when an edit expands', () => { const view = render( { expect(view.getByText('+1 -1')).toBeTruthy() expect(view.container.querySelector('[data-diff]')).toBeNull() fireEvent.click(view.getByRole('button')) - expect(view.getByText(/└ \+1 -1/)).toBeTruthy() + expect(view.getAllByText('+1 -1')).toHaveLength(1) expect(view.getAllByText('start')).toHaveLength(1) expect(view.getAllByText('end')).toHaveLength(1) expect(view.getByText('old', { exact: true })).toBeTruthy() diff --git a/snapshots/web/diff-bounded/ui.expected.md b/snapshots/web/diff-bounded/ui.expected.md index 1883ed4a1c..09cf4e6d4d 100644 --- a/snapshots/web/diff-bounded/ui.expected.md +++ b/snapshots/web/diff-bounded/ui.expected.md @@ -7,5 +7,5 @@ - button "Copy" - text: large.txt - shared heading - old setting 0 - old setting 1 - old setting 2 - button "Expand 252 more diff lines": … 252 more lines -- text: + new setting 125 + new setting 126 + new setting 127 + new setting 128 └ +130 -130 · 1 file +- text: + new setting 125 + new setting 126 + new setting 127 + new setting 128 - button "Inspect" diff --git a/snapshots/web/diff-context/ui.expected.md b/snapshots/web/diff-context/ui.expected.md index 44e1810526..72bb5f0d61 100644 --- a/snapshots/web/diff-context/ui.expected.md +++ b/snapshots/web/diff-context/ui.expected.md @@ -5,5 +5,5 @@ - text: Code block - button "Wrap lines" - button "Copy" -- text: config.txt - mode=DEBUG + mode=RELEASE level=info └ +1 -1 · 1 file +- text: config.txt - mode=DEBUG + mode=RELEASE level=info - button "Inspect" From 3b6a5399e8fe7b87682a0a93a401494813f0fe68 Mon Sep 17 00:00:00 2001 From: lsdsjy <1356263+lsdsjy@users.noreply.github.com> Date: Tue, 22 Sep 2026 15:49:20 +0800 Subject: [PATCH 15/29] docs(desktop): clarify login theme ownership --- apps/desktop/src/preload-theme.ts | 11 ++++++----- .../client/ui-layout/src/client/theme-presenter.ts | 10 ++++++---- packages/client/ui-settings-account/README.i18n.yaml | 4 ++-- packages/client/ui-settings-account/README.md | 2 +- packages/client/ui-settings-account/README.zh.md | 2 +- .../ui-settings-account/src/client/AccountSection.tsx | 2 +- 6 files changed, 17 insertions(+), 14 deletions(-) diff --git a/apps/desktop/src/preload-theme.ts b/apps/desktop/src/preload-theme.ts index 19d390b490..5091984fdb 100644 --- a/apps/desktop/src/preload-theme.ts +++ b/apps/desktop/src/preload-theme.ts @@ -8,11 +8,12 @@ const THEME_SOURCE_ATTRIBUTE = 'data-ds-theme-source' /** * Watches `html[data-ds-theme-source]` and forwards each value to the main - * process, which sets `nativeTheme.themeSource`. The macOS sidebar vibrancy - * material then follows the app's theme preference instead of the OS - * appearance while `system` keeps following the OS; the main process reads - * the same value back as `shouldUseDarkColors` when it needs the resolved - * palette for a Platform login link. + * process, which sets `nativeTheme.themeSource`. Native chrome and renderer + * `prefers-color-scheme` queries on every platform then follow the app's + * theme preference instead of the OS appearance while `system` keeps + * following the OS; the macOS sidebar vibrancy material is one such consumer. + * The main process reads the same value back as `shouldUseDarkColors` when a + * Platform login link needs the resolved palette. */ export function syncNativeTheme(): void { let sent: string | undefined diff --git a/packages/client/ui-layout/src/client/theme-presenter.ts b/packages/client/ui-layout/src/client/theme-presenter.ts index 608eb08bdb..be305142bc 100644 --- a/packages/client/ui-layout/src/client/theme-presenter.ts +++ b/packages/client/ui-layout/src/client/theme-presenter.ts @@ -16,10 +16,12 @@ export const DARK_ATTRIBUTE = 'data-ds-dark-theme' /** * Root attribute publishing the theme source (`light`, `dark`, or `system`) - * for host shells that mirror it into native window chrome (the Electron - * preload forwards it to `nativeTheme.themeSource` so macOS vibrancy follows - * the app theme). `system` only when the preference is `system`; a fixed - * preference (including registered theme ids) publishes its resolved scheme. + * for host shells that mirror it into the native theme (the Electron preload + * forwards it to `nativeTheme.themeSource`, so native chrome, renderer + * `prefers-color-scheme` queries, and Platform login links follow the app + * palette on every platform). `system` only when the preference is `system`; + * a fixed preference (including registered theme ids) publishes its resolved + * scheme. */ export const THEME_SOURCE_ATTRIBUTE = 'data-ds-theme-source' diff --git a/packages/client/ui-settings-account/README.i18n.yaml b/packages/client/ui-settings-account/README.i18n.yaml index 0dbd02cfdc..7cf3c896f6 100644 --- a/packages/client/ui-settings-account/README.i18n.yaml +++ b/packages/client/ui-settings-account/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-settings-account/README.md -README.md: 016d1161214cf5723de6d5d63dc54542b8382571 -README.zh.md: 56ff93217bf97126878a0c7d5fed889a5e3f56f2 +README.md: 27682d9fa145723019573d492bbc1627ed43d1be +README.zh.md: 0fd64077f980482a31774d91fa62d349b0a6616f diff --git a/packages/client/ui-settings-account/README.md b/packages/client/ui-settings-account/README.md index 016d116121..27682d9fa1 100644 --- a/packages/client/ui-settings-account/README.md +++ b/packages/client/ui-settings-account/README.md @@ -46,7 +46,7 @@ The Account section appears first in Settings only while signed in; it is hidden The [credentials subsystem](../../../docs/subsystems/credentials.md) owns storage APIs; the [architecture](../../../docs/architecture.md) explains application composition. -Account login uses a dismissible dialog before the model onboarding credential editor. The dialog uses a compact, right-aligned action row with the primary action last. The sidebar displays the profile name, falling back to the server-masked phone number or email when the name is absent; it stays blank while the profile is loading. Dialog copy and the sidebar account label are not text-selectable; the copy-link button remains available and restores its label two seconds after each successful copy. Clipboard failures show Copy failed on the link for two seconds without interrupting sign-in. Waiting shows a copyable authorization link and a loading indicator; timeout and failure require an explicit retry. The dialog's Copy sign-in link and the Settings Open link append the resolved Desktop palette as `theme=light` or `theme=dark` from the live theme snapshot, so both routes reach the Platform page in the current application theme without touching the stored preference. Sign-in failures render in that dialog; the launcher's inline failure line reports only a failed sign-out. Closing a waiting dialog cancels its Host attempt. The sidebar can reopen the same API-key editor through the settings coordinator. +Account login uses a dismissible dialog before the model onboarding credential editor. The dialog uses a compact, right-aligned action row with the primary action last. The sidebar displays the profile name, falling back to the server-masked phone number or email when the name is absent; it stays blank while the profile is loading. Dialog copy and the sidebar account label are not text-selectable; the copy-link button remains available and restores its label two seconds after each successful copy. Clipboard failures show Copy failed on the link for two seconds without interrupting sign-in. Waiting shows a copyable authorization link and a loading indicator; timeout and failure require an explicit retry. The dialog's Copy sign-in link and the Settings Open link append the resolved Desktop palette as `theme=light` or `theme=dark` from the live theme snapshot, so both routes reach the Platform page in the current application theme without changing the theme preference Platform has saved. Sign-in failures render in that dialog; the launcher's inline failure line reports only a failed sign-out. Closing a waiting dialog cancels its Host attempt. The sidebar can reopen the same API-key editor through the settings coordinator. A terminal account-state stream failure appears in the sign-in dialog or Account settings. Plugin unload suppresses late failure reports. diff --git a/packages/client/ui-settings-account/README.zh.md b/packages/client/ui-settings-account/README.zh.md index 56ff93217b..0fd64077f9 100644 --- a/packages/client/ui-settings-account/README.zh.md +++ b/packages/client/ui-settings-account/README.zh.md @@ -46,7 +46,7 @@ Desktop 的用量和充值操作在 48px 返回栏下方打开隔离的原生 Pl [凭证子系统](../../../docs/subsystems/credentials.zh.md)定义存储接口;[架构](../../../docs/architecture.zh.md)说明应用组合。 -账号登录在模型引导的凭证编辑器之前显示可关闭的弹窗。弹窗底部采用紧凑的右对齐横排操作,主操作位于末尾。侧边栏优先显示昵称,缺少昵称时显示服务端返回的脱敏手机号或邮箱;资料加载期间保持留空。 弹窗文字和侧边栏账号状态文字不可选中,复制登录链接按钮始终可用,并在每次复制成功两秒后恢复原文案。剪贴板失败时,链接原位显示“复制失败”两秒,不中断登录。等待状态提供可复制的授权链接和加载图标;超时和失败均须用户手动重试。弹窗的“复制登录链接”和设置页的“打开”链接会从当前主题快照读取 Desktop 生效配色,追加 `theme=light` 或 `theme=dark`,使两条路径都以当前应用主题打开 Platform 页面,且不写入已保存的主题偏好。登录失败在该弹窗内呈现;侧边栏入口的内联失败提示仅用于退出登录失败。关闭等待弹窗会取消对应 Host 登录流程。侧边栏通过设置协调器重新打开同一个 API Key 编辑器。 +账号登录在模型引导的凭证编辑器之前显示可关闭的弹窗。弹窗底部采用紧凑的右对齐横排操作,主操作位于末尾。侧边栏优先显示昵称,缺少昵称时显示服务端返回的脱敏手机号或邮箱;资料加载期间保持留空。 弹窗文字和侧边栏账号状态文字不可选中,复制登录链接按钮始终可用,并在每次复制成功两秒后恢复原文案。剪贴板失败时,链接原位显示“复制失败”两秒,不中断登录。等待状态提供可复制的授权链接和加载图标;超时和失败均须用户手动重试。弹窗的“复制登录链接”和设置页的“打开”链接会从当前主题快照读取 Desktop 生效配色,追加 `theme=light` 或 `theme=dark`,使两条路径都以当前应用主题打开 Platform 页面,且不改变 Platform 已保存的主题偏好。登录失败在该弹窗内呈现;侧边栏入口的内联失败提示仅用于退出登录失败。关闭等待弹窗会取消对应 Host 登录流程。侧边栏通过设置协调器重新打开同一个 API Key 编辑器。 账户状态流的终止错误会显示在登录对话框或账户设置中。插件卸载后不再报告延迟到达的错误。 diff --git a/packages/client/ui-settings-account/src/client/AccountSection.tsx b/packages/client/ui-settings-account/src/client/AccountSection.tsx index 1dccd18f84..d5e4f5d82a 100644 --- a/packages/client/ui-settings-account/src/client/AccountSection.tsx +++ b/packages/client/ui-settings-account/src/client/AccountSection.tsx @@ -32,7 +32,7 @@ export interface AccountSectionInjected { /** Desktop-only commands; absent in ordinary browsers. */ platform?: PlatformBridge - /** Host-owned account stream and theme snapshots observed through framework hooks. */ + /** Account stream owned by the Host and theme snapshots published by the renderer, observed through framework hooks. */ hooks: { account: HostObservable /** Palette the Platform login pages follow. */ From 785a92ab03b0acfa215810d3cd3cf2290afdb8d7 Mon Sep 17 00:00:00 2001 From: lsdsjy <1356263+lsdsjy@users.noreply.github.com> Date: Tue, 22 Sep 2026 15:49:30 +0800 Subject: [PATCH 16/29] fix(client): rename the contact menu entry to Feedback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The account menu entry that opens the questionnaire is now labeled Feedback in English and 意见反馈 in Chinese. The menu action, contact form URL and its configuration options keep their existing names. Expected menu snapshots and the bilingual README record the new copy. --- packages/client/ui-settings-account/README.i18n.yaml | 4 ++-- packages/client/ui-settings-account/README.md | 2 +- packages/client/ui-settings-account/README.zh.md | 2 +- packages/client/ui-settings-account/src/client/locales.ts | 4 ++-- .../client/ui-settings-account/tests/expected/menu-en.txt | 2 +- .../client/ui-settings-account/tests/expected/menu-zh.txt | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/client/ui-settings-account/README.i18n.yaml b/packages/client/ui-settings-account/README.i18n.yaml index 67f94258b5..e971ba4553 100644 --- a/packages/client/ui-settings-account/README.i18n.yaml +++ b/packages/client/ui-settings-account/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-settings-account/README.md -README.md: 30d41fb49262619fd34f1bcd1abfec49d1248438 -README.zh.md: 1916bb2bb37704e5ecc22589620add82ce74780f +README.md: d06a13e877c13dd0a6695a73c44dcf10d2178c6c +README.zh.md: d010a0f6878b194df33f894b3b9b45610356dd45 diff --git a/packages/client/ui-settings-account/README.md b/packages/client/ui-settings-account/README.md index 30d41fb492..d06a13e877 100644 --- a/packages/client/ui-settings-account/README.md +++ b/packages/client/ui-settings-account/README.md @@ -28,7 +28,7 @@ Balances use Platform Web currency formatting: two decimal places and digit grou Desktop usage and top-up actions open an isolated native Platform view below a 48px return bar. Back destroys the view and preserves the Account settings page. Browser clients retain external links. Loading failures retain the return action and show a centered localized error with Retry. Retry reloads the same destination; renderer commands never receive the account token. -Contact us opens the Feishu questionnaire in the system browser on Desktop or a new browser tab on Web. It supplies the available build version, UI locale and physical screen resolution as prefill_* parameters, with hide_*=1 for every context field; the account UID, tokens and contact details are excluded. Configure contactFormUrl on the ui-settings-account plugin to select another HTTPS form. contactSource defaults to empty until the questionnaire supports a Harness source option; OS and device fields remain unfilled, matching the Web implementation. +The account menu's Feedback entry opens the Feishu questionnaire in the system browser on Desktop or a new browser tab on Web. It supplies the available build version, UI locale and physical screen resolution as prefill_* parameters, with hide_*=1 for every context field; the account UID, tokens and contact details are excluded. Configure contactFormUrl on the ui-settings-account plugin to select another HTTPS form. contactSource defaults to empty until the questionnaire supports a Harness source option; OS and device fields remain unfilled, matching the Web implementation. The sidebar account menu uses the shared Menu surface, backdrop blur, spacing, and row typography; feature styles only size its launcher. diff --git a/packages/client/ui-settings-account/README.zh.md b/packages/client/ui-settings-account/README.zh.md index 1916bb2bb3..d010a0f687 100644 --- a/packages/client/ui-settings-account/README.zh.md +++ b/packages/client/ui-settings-account/README.zh.md @@ -28,7 +28,7 @@ kind: "package-reference" Desktop 的用量和充值操作在 48px 返回栏下方打开隔离的原生 Platform 视图。返回操作销毁视图并保留 Account 设置页。浏览器客户端继续使用外链。加载失败时保留返回操作,居中显示本地化错误提示和“重试”按钮。重试重新加载同一目标页面;渲染进程命令不接收账号 token。 -“联系我们”在 Desktop 的系统浏览器或 Web 的新标签页打开飞书问卷。链接通过 prefill_* 参数填写已有的构建版本、界面语言和屏幕物理分辨率,并为所有上下文字段设置 hide_*=1;不传账号 UID、token 或联系方式。可在 ui-settings-account 插件配置 contactFormUrl,切换到另一个 HTTPS 问卷。问卷支持 Harness 来源选项前,contactSource 默认为空;OS 和设备字段沿用 Web 实现,保持未填写。 +账号菜单的“意见反馈”入口在 Desktop 的系统浏览器或 Web 的新标签页打开飞书问卷。链接通过 prefill_* 参数填写已有的构建版本、界面语言和屏幕物理分辨率,并为所有上下文字段设置 hide_*=1;不传账号 UID、token 或联系方式。可在 ui-settings-account 插件配置 contactFormUrl,切换到另一个 HTTPS 问卷。问卷支持 Harness 来源选项前,contactSource 默认为空;OS 和设备字段沿用 Web 实现,保持未填写。 侧边栏账号菜单使用公共 Menu 的表面、背景模糊、间距和菜单项排版;功能样式仅设置入口布局。 diff --git a/packages/client/ui-settings-account/src/client/locales.ts b/packages/client/ui-settings-account/src/client/locales.ts index 58ca7fb7ba..2e4b40474d 100644 --- a/packages/client/ui-settings-account/src/client/locales.ts +++ b/packages/client/ui-settings-account/src/client/locales.ts @@ -8,7 +8,7 @@ export const en = { failureTitle: 'Could not sign in', platformFailed: 'Could not complete the operation. Try again.', platformRetry: 'Retry', loading: 'Loading…', backToHarness: 'Back to DeepSeek Harness', - settings: 'Settings', contactUs: 'Contact us', menu: 'Account menu', + settings: 'Settings', contactUs: 'Feedback', menu: 'Account menu', nav: 'Account', signedIn: 'Signed in to DeepSeek', signedOut: 'Not signed in', signIn: 'Sign in', signOut: 'Sign out', cancel: 'Cancel', open: 'Open browser', initializing: 'Starting sign in…', waiting: 'Continue in your browser', @@ -33,7 +33,7 @@ export const zh: Record = { failureTitle: '登录失败', platformFailed: '操作未完成,请重试', platformRetry: '重试', loading: '加载中…', backToHarness: '返回 DeepSeek Harness', - settings: '设置', contactUs: '联系我们', menu: '账号菜单', + settings: '设置', contactUs: '意见反馈', menu: '账号菜单', nav: '账号与余额', signedIn: '已登录 DeepSeek', signedOut: '尚未登录', signIn: '登录', signOut: '退出登录', cancel: '取消', open: '打开浏览器', initializing: '正在发起登录…', waiting: '请在浏览器中继续', diff --git a/packages/client/ui-settings-account/tests/expected/menu-en.txt b/packages/client/ui-settings-account/tests/expected/menu-en.txt index dd5eac1f91..1addd6d26a 100644 --- a/packages/client/ui-settings-account/tests/expected/menu-en.txt +++ b/packages/client/ui-settings-account/tests/expected/menu-en.txt @@ -1 +1 @@ -SettingsContact usSign out +SettingsFeedbackSign out diff --git a/packages/client/ui-settings-account/tests/expected/menu-zh.txt b/packages/client/ui-settings-account/tests/expected/menu-zh.txt index a96ac28fe7..be4f55f3b6 100644 --- a/packages/client/ui-settings-account/tests/expected/menu-zh.txt +++ b/packages/client/ui-settings-account/tests/expected/menu-zh.txt @@ -1 +1 @@ -设置联系我们退出登录 +设置意见反馈退出登录 From 34a0a8e81d180b12bbbdca120d0c103da74d04a8 Mon Sep 17 00:00:00 2001 From: Yudong Han Date: Tue, 22 Sep 2026 16:04:13 +0800 Subject: [PATCH 17/29] fix(web): preserve Excel previews across OPC paths and XML encodings (#4872) * fix(web): resolve XLSX part relationships and namespace aliases * fix(web): keep Excel browser scenario in the host test program * fix(excel): preserve XML encodings and relocated workbook parts * fix(excel): exclude installed launchers from dependency patch * fix(excel): restore Strict and case-equivalent workbook previews --- THIRD_PARTY_NOTICES.md | 1 + apps/web/tests/excel-opc.e2e.ts | 92 ++ apps/web/tsconfig.json | 1 + .../README.i18n.yaml | 4 +- .../ui-sidebar-documentpreview/README.md | 2 + .../ui-sidebar-documentpreview/README.zh.md | 2 + .../src/client/excel/xlsx-archive.ts | 81 +- .../tests/excel-opc-fixture.ts | 14 + .../tests/excel-opc.client.spec.ts | 100 +++ .../tests/excel-opening-fixture.ts | 36 + .../tests/excel-opening.client.spec.ts | 85 ++ .../tests/excel-xml-fixture.ts | 14 + .../tests/excel-xml.client.spec.ts | 112 +++ .../tests/fixtures/excel-opc/combined.xlsx | Bin 0 -> 8781 bytes .../tests/fixtures/excel-opc/comments.xlsx | Bin 0 -> 6261 bytes .../tests/fixtures/excel-opc/part-name.xlsx | Bin 0 -> 4898 bytes .../tests/fixtures/excel-opc/prefix.xlsx | Bin 0 -> 4907 bytes .../tests/fixtures/excel-opc/relative.xlsx | Bin 0 -> 5325 bytes .../tests/fixtures/excel-opc/table.xlsx | Bin 0 -> 5575 bytes .../tests/fixtures/excel-xml/cdata.xlsx | Bin 0 -> 11224 bytes .../tests/fixtures/excel-xml/parts-path.xlsx | Bin 0 -> 11332 bytes .../tests/fixtures/excel-xml/rich.xlsx | Bin 0 -> 11184 bytes .../fixtures/excel-xml/strings-path.xlsx | Bin 0 -> 11183 bytes .../tests/fixtures/excel-xml/styles-path.xlsx | Bin 0 -> 11196 bytes .../fixtures/excel-xml/utf16-metadata.xlsx | Bin 0 -> 11456 bytes .../tests/fixtures/excel-xml/utf16-sheet.xlsx | Bin 0 -> 11552 bytes .../fixtures/excel-xml/workbook-path.xlsx | Bin 0 -> 11172 bytes .../tests/fuzz/README.i18n.yaml | 6 + .../tests/fuzz/README.md | 46 + .../tests/fuzz/README.zh.md | 46 + .../tests/fuzz/excel-worker.client.ts | 29 + .../tests/fuzz/generate.py | 351 ++++++++ .../tests/fuzz/run.client.ts | 177 ++++ patches/exceljs@4.4.0.patch | 806 ++++++++++++++++++ pnpm-lock.yaml | 5 +- pnpm-workspace.yaml | 1 + snapshots/web/excel-opc/excel.expected.md | 22 + snapshots/web/excel-opc/snapshot.yml | 9 + tsconfig.host.json | 1 + 39 files changed, 2025 insertions(+), 18 deletions(-) create mode 100644 apps/web/tests/excel-opc.e2e.ts create mode 100644 packages/client/ui-sidebar-documentpreview/tests/excel-opc-fixture.ts create mode 100644 packages/client/ui-sidebar-documentpreview/tests/excel-opc.client.spec.ts create mode 100644 packages/client/ui-sidebar-documentpreview/tests/excel-opening-fixture.ts create mode 100644 packages/client/ui-sidebar-documentpreview/tests/excel-opening.client.spec.ts create mode 100644 packages/client/ui-sidebar-documentpreview/tests/excel-xml-fixture.ts create mode 100644 packages/client/ui-sidebar-documentpreview/tests/excel-xml.client.spec.ts create mode 100644 packages/client/ui-sidebar-documentpreview/tests/fixtures/excel-opc/combined.xlsx create mode 100644 packages/client/ui-sidebar-documentpreview/tests/fixtures/excel-opc/comments.xlsx create mode 100644 packages/client/ui-sidebar-documentpreview/tests/fixtures/excel-opc/part-name.xlsx create mode 100644 packages/client/ui-sidebar-documentpreview/tests/fixtures/excel-opc/prefix.xlsx create mode 100644 packages/client/ui-sidebar-documentpreview/tests/fixtures/excel-opc/relative.xlsx create mode 100644 packages/client/ui-sidebar-documentpreview/tests/fixtures/excel-opc/table.xlsx create mode 100644 packages/client/ui-sidebar-documentpreview/tests/fixtures/excel-xml/cdata.xlsx create mode 100644 packages/client/ui-sidebar-documentpreview/tests/fixtures/excel-xml/parts-path.xlsx create mode 100644 packages/client/ui-sidebar-documentpreview/tests/fixtures/excel-xml/rich.xlsx create mode 100644 packages/client/ui-sidebar-documentpreview/tests/fixtures/excel-xml/strings-path.xlsx create mode 100644 packages/client/ui-sidebar-documentpreview/tests/fixtures/excel-xml/styles-path.xlsx create mode 100644 packages/client/ui-sidebar-documentpreview/tests/fixtures/excel-xml/utf16-metadata.xlsx create mode 100644 packages/client/ui-sidebar-documentpreview/tests/fixtures/excel-xml/utf16-sheet.xlsx create mode 100644 packages/client/ui-sidebar-documentpreview/tests/fixtures/excel-xml/workbook-path.xlsx create mode 100644 packages/client/ui-sidebar-documentpreview/tests/fuzz/README.i18n.yaml create mode 100644 packages/client/ui-sidebar-documentpreview/tests/fuzz/README.md create mode 100644 packages/client/ui-sidebar-documentpreview/tests/fuzz/README.zh.md create mode 100644 packages/client/ui-sidebar-documentpreview/tests/fuzz/excel-worker.client.ts create mode 100644 packages/client/ui-sidebar-documentpreview/tests/fuzz/generate.py create mode 100644 packages/client/ui-sidebar-documentpreview/tests/fuzz/run.client.ts create mode 100644 patches/exceljs@4.4.0.patch create mode 100644 snapshots/web/excel-opc/excel.expected.md create mode 100644 snapshots/web/excel-opc/snapshot.yml diff --git a/THIRD_PARTY_NOTICES.md b/THIRD_PARTY_NOTICES.md index 5567a0c681..862299b9a2 100644 --- a/THIRD_PARTY_NOTICES.md +++ b/THIRD_PARTY_NOTICES.md @@ -143,6 +143,7 @@ pnpm applies local patches to the following packages at install time, so shipped - `@fortune-sheet/core@1.0.4` — [`patches/@fortune-sheet__core@1.0.4.patch`](patches/@fortune-sheet__core@1.0.4.patch) - `@fortune-sheet/react@1.0.4` — [`patches/@fortune-sheet__react@1.0.4.patch`](patches/@fortune-sheet__react@1.0.4.patch) - `@yao-pkg/pkg@6.21.0` — [`patches/@yao-pkg__pkg@6.21.0.patch`](patches/@yao-pkg__pkg@6.21.0.patch) +- `exceljs@4.4.0` — [`patches/exceljs@4.4.0.patch`](patches/exceljs@4.4.0.patch) - `node-pty@1.2.0-beta.15` — [`patches/node-pty@1.2.0-beta.15.patch`](patches/node-pty@1.2.0-beta.15.patch) ## Official Claude Code platform payloads diff --git a/apps/web/tests/excel-opc.e2e.ts b/apps/web/tests/excel-opc.e2e.ts new file mode 100644 index 0000000000..a3a49e3248 --- /dev/null +++ b/apps/web/tests/excel-opc.e2e.ts @@ -0,0 +1,92 @@ +/** Independent-writer XLSX previews through a replayed Session and the shipped browser Worker. */ +import { writeFile } from 'node:fs/promises' +import { join } from 'node:path' +import { fileURLToPath } from 'node:url' +import { chromium, type Browser, type Page } from 'playwright' +import { afterAll, beforeAll, describe, expect, it } from 'vitest' +import { excelOpeningCases, excelOpeningFixture } from '../../../packages/client/ui-sidebar-documentpreview/tests/excel-opening-fixture.ts' +import { excelOpcCases, excelOpcFixture } from '../../../packages/client/ui-sidebar-documentpreview/tests/excel-opc-fixture.ts' +import { excelXmlCases, excelXmlFixture } from '../../../packages/client/ui-sidebar-documentpreview/tests/excel-xml-fixture.ts' +import { assertFixtureInventory, compareOrRefreshGolden, launchWebScaffold, watchConsole, webSnapshotMode, type WebScaffold } from './scaffold.ts' +import { connectFreshWorkspace, newEnglishPage } from './support.ts' + +const snapshotDirectory = fileURLToPath(new URL('../../../snapshots/web/excel-opc', import.meta.url)) +const mode = webSnapshotMode() + +describe.skipIf(mode === 'record')('web e2e: independent-writer Excel previews', () => { + let scaffold: WebScaffold + let browser: Browser + let page: Page + let consoleErrors: ReturnType + + beforeAll(async () => { + scaffold = await launchWebScaffold({ + developerTools: false, + replayFixture: fileURLToPath(new URL('../../../snapshots/web/lifecycle-chrome/session.v3.jsonl', import.meta.url)), + compareReplaySession: false, + }) + browser = await chromium.launch() + page = await newEnglishPage(browser) + consoleErrors = watchConsole(page) + await page.goto(scaffold.authenticatedUrl, { waitUntil: 'load' }) + await connectFreshWorkspace(page, scaffold.workspaceCwd) + }) + + afterAll(async () => { + try { await browser?.close() } finally { await scaffold?.close() } + }) + + it('opens comments, Tables and equivalent OPC encodings without hiding cell data', async () => { + const settled = scaffold.whenTurnSettled() + const input = page.locator('[data-composer-input]').first() + await input.fill('Reply with the single word LIGHTHOUSE and stop.') + await input.press('Enter') + const sessionId = await settled + await page.getByText('LIGHTHOUSE', { exact: true }).waitFor() + const cwd = scaffold.ctx.agents.get(sessionId)?.session.header.cwd + if (cwd === undefined) throw new Error('Excel preview Session has no workspace') + for (const name of excelOpcCases) await writeFile(join(cwd, `${name}.xlsx`), await excelOpcFixture(name)) + for (const name of excelOpeningCases) await writeFile(join(cwd, `${name}.xlsx`), await excelOpeningFixture(name)) + for (const name of excelXmlCases) await writeFile(join(cwd, `${name}.xlsx`), await excelXmlFixture(name)) + + const column = page.locator('[data-rightbar-col]') + await page.locator('[data-sidebar-right-expand]').click() + await column.locator('[data-sidebar-right-guide-entry="files"]').click() + await column.locator('[data-files-state="tree"]').waitFor() + await column.locator('[data-files-reload]').click() + const files = column.locator('[data-dockkit-tab]').filter({ has: page.getByText('Files', { exact: true }) }) + const preview = column.locator('[data-textpreview-url]') + const excel = preview.locator('[data-excel-preview]') + const sheets = excel.locator('.luckysheet-sheets-item-name') + const notice = excel.locator('[data-excel-unsupported-notice]') + const rows = ['# Independent-writer Excel previews', ''] + await page.context().grantPermissions(['clipboard-read', 'clipboard-write'], { origin: new URL(page.url()).origin }) + for (const name of [...excelOpcCases, ...excelOpeningCases, ...excelXmlCases]) { + await files.click() + await column.locator('[data-files-entry="file"]').getByRole('button', { name: `${name}.xlsx`, exact: true }).click() + await expect.poll(async () => (await preview.getAttribute('data-textpreview-url'))?.endsWith(`/${name}.xlsx`)).toBe(true) + await sheets.getByText('数据', { exact: true }).waitFor() + await excel.locator('.fortune-sheet-overlay').click({ position: { x: 70, y: 30 } }) + await expect.poll(() => excel.locator('.fortune-fx-input').innerText()).toBe('Item') + await page.keyboard.press('ControlOrMeta+C') + await expect.poll(() => page.evaluate(() => navigator.clipboard.readText())).toMatch(/^Item\r?\n$/) + const rich = excelXmlCases.some(candidate => candidate === name) + const opening = excelOpeningCases.some(candidate => candidate === name) + expect(await notice.count()).toBe(name === 'combined' || rich || opening ? 1 : 0) + if (name === 'combined' || rich || opening) { + const features = rich ? 'charts, images, shapes, conditional formatting' + : name === 'orphan-drawing' ? 'conditional formatting' : 'charts, conditional formatting' + expect(await notice.innerText()).toBe(`This preview does not support ${features} in this workbook. Open it in a system application for the full experience.`) + } + rows.push(`- ${name}.xlsx: 数据 opened; Item copied`) + } + expect(await sheets.getByText('隐藏页', { exact: true }).isVisible()).toBe(false) + const warning = await notice.innerText() + expect(warning).toBe('This preview does not support charts, images, shapes, conditional formatting in this workbook. Open it in a system application for the full experience.') + rows.push('- Relocated workbook: hidden sheet omitted', `- Relocated workbook notice: ${warning}`) + expect(consoleErrors.pageErrors).toEqual([]) + expect(consoleErrors.warnings).toEqual([]) + await compareOrRefreshGolden(join(snapshotDirectory, 'excel.expected.md'), rows.join('\n'), mode) + await assertFixtureInventory(snapshotDirectory, ['excel.expected.md']) + }) +}) diff --git a/apps/web/tsconfig.json b/apps/web/tsconfig.json index 3c7faf36b5..70c0f7c748 100644 --- a/apps/web/tsconfig.json +++ b/apps/web/tsconfig.json @@ -53,6 +53,7 @@ "tests/details-session-lifecycle.e2e.ts", "tests/sessionless-header.e2e.ts", "tests/document-preview.e2e.ts", + "tests/excel-opc.e2e.ts", "tests/office-fixture.ts", "tests/sidebar-browser.e2e.ts", "tests/plugin-config.e2e.ts", diff --git a/packages/client/ui-sidebar-documentpreview/README.i18n.yaml b/packages/client/ui-sidebar-documentpreview/README.i18n.yaml index fff166bb64..0978246a14 100644 --- a/packages/client/ui-sidebar-documentpreview/README.i18n.yaml +++ b/packages/client/ui-sidebar-documentpreview/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-sidebar-documentpreview/README.md -README.md: 554aae41691148602b6fe563d802d0215adf2035 -README.zh.md: f7503f901311649adf161b8dcad07e73267d83d2 +README.md: 224957fec45fd4d2849df677b9cada62d01d18cd +README.zh.md: 18fe9e94617291d85fd3db7bf1c7bcc347f6ec73 diff --git a/packages/client/ui-sidebar-documentpreview/README.md b/packages/client/ui-sidebar-documentpreview/README.md index 554aae4169..224957fec4 100644 --- a/packages/client/ui-sidebar-documentpreview/README.md +++ b/packages/client/ui-sidebar-documentpreview/README.md @@ -84,6 +84,8 @@ The lazy Excel chunk bundles FortuneSheet, ExcelJS for XLSX, SheetJS CE for XLS, The read-only formula bar displays formulas and cell text literally. Copying preserves an HTML table with escaped cell contents, including saved formula results. The [FortuneSheet patch rationale](../../../.agents/notes/implemented/feature/2026-09-16-browser-excel-preview.md) explains the requirements for retaining these behaviors and worksheet selection when upgrading the dependency. +The pinned [ExcelJS patch](../../../patches/exceljs@4.4.0.patch) resolves the workbook, styles, shared strings, worksheets, comments, Tables, and VML through package relationships, including absolute and relative targets and ASCII case-equivalent part names, and recognizes SpreadsheetML and VML names by namespace URI. Strict OOXML SpreadsheetML and relationship URIs map to the same supported preview features; this is not full Strict conformance. XML parts accept UTF-8 and either byte order of UTF-16; CDATA contributes literal text. Drawing and conditional-format notices follow relationships regardless of part directories. Unreferenced `xl/drawings/*.xml` parts and their relationship files are also omitted, without adding notices; comment VML remains. Missing referenced parts and ambiguous case-equivalent ZIP entries fail the preview. Comments and Table metadata survive parsing but have no dedicated preview controls. The patch covers the Node sources and `dist/exceljs.js`; its browser entry selects that patched bundle. Dependency upgrades must preserve both entry paths and pass the [independent-writer regressions and fuzz diagnostics](tests/fuzz/README.md). + ## Office preview diff --git a/packages/client/ui-sidebar-documentpreview/README.zh.md b/packages/client/ui-sidebar-documentpreview/README.zh.md index f7503f9013..18fe9e9461 100644 --- a/packages/client/ui-sidebar-documentpreview/README.zh.md +++ b/packages/client/ui-sidebar-documentpreview/README.zh.md @@ -84,6 +84,8 @@ CSV 和 TSV 默认使用表格查看器,也可选择纯文本。两者分别 只读公式栏按字面显示公式和单元格文本。复制时保留 HTML 表格,并转义单元格内容,包括已保存的公式结果。[FortuneSheet 补丁决策](../../../.agents/notes/implemented/feature/2026-09-16-browser-excel-preview.zh.md)说明升级依赖时保留这些行为与工作表选区的要求。 +固定版本的 [ExcelJS 补丁](../../../patches/exceljs@4.4.0.patch)通过包内关系解析工作簿、样式、共享字符串、工作表、批注、Table 和 VML,支持绝对及相对目标,以及 ASCII 大小写等价的部件名,并按命名空间 URI 识别 SpreadsheetML 和 VML 名称。Strict OOXML 的 SpreadsheetML 和关系 URI 映射到相同的已支持预览功能;这不代表完整支持 Strict 标准。XML 部件支持 UTF-8 及两种字节序的 UTF-16;CDATA 按字面文本读取。绘图和条件格式提示按关系查找内容,不依赖部件目录。未被引用的 `xl/drawings/*.xml` 部件及其关系文件也会被移除,但不会产生提示;批注 VML 保持不变。缺失引用部件或存在大小写等价的歧义 ZIP 条目会使预览失败。解析保留批注和 Table 元数据,但预览器没有专门展示它们的控件。补丁同时覆盖 Node 源码和 `dist/exceljs.js`,浏览器入口选择已修补的 bundle。升级依赖时必须保留两个入口的行为,并通过[独立写入器回归测试和 fuzz 诊断](tests/fuzz/README.zh.md)。 + ## Office 预览 diff --git a/packages/client/ui-sidebar-documentpreview/src/client/excel/xlsx-archive.ts b/packages/client/ui-sidebar-documentpreview/src/client/excel/xlsx-archive.ts index be6ed4a52a..b8e5d3b7c7 100644 --- a/packages/client/ui-sidebar-documentpreview/src/client/excel/xlsx-archive.ts +++ b/packages/client/ui-sidebar-documentpreview/src/client/excel/xlsx-archive.ts @@ -1,5 +1,5 @@ /** XLSX preview copies without DrawingML parts; worksheet XML and source bytes remain untouched. */ -import { strFromU8, unzipSync, zipSync, type Unzipped } from 'fflate' +import { unzipSync, zipSync, type Unzipped } from 'fflate' import { XMLParser } from 'fast-xml-parser' import type { ExcelUnsupportedFeature } from './model.ts' @@ -8,13 +8,21 @@ export class XlsxPreviewArchive { /** Detected workbook content that the preview does not display. */ readonly unsupportedFeatures = new Set() private readonly files: Unzipped + private readonly parts = new Map() /** * Read an archive without modifying the borrowed source buffer. * @param bytes - Complete XLSX source bytes. + * @throws When ZIP entries have ASCII case-equivalent names. */ constructor(private readonly bytes: Uint8Array) { this.files = unzipSync(bytes) + for (const [path, bytes] of Object.entries(this.files)) { + if (path.endsWith('/')) continue + const key = partKey(path) + if (this.parts.has(key)) throw new Error(`Ambiguous XLSX part: ${path}`) + this.parts.set(key, bytes) + } } /** @@ -23,18 +31,36 @@ export class XlsxPreviewArchive { */ withoutDrawings(): Uint8Array { const entries = Object.entries(this.files) - const retained = entries.filter(([path, bytes]) => { - if (/^xl\/worksheets\/[^/]+\.xml$/.test(path)) { - this.inspectContent(bytes) - return true - } - if (/^xl\/drawings\/[^/]+\.xml$/.test(path)) { - this.inspectContent(bytes) - } else if (!/^xl\/drawings\/_rels\/[^/]+\.xml\.rels$/.test(path)) { - return true - } - return false - }) + const omitted = new Set() + for (const [path, bytes] of entries) { + // ExcelJS also discovers unreferenced drawings in its conventional directory. + if (/^xl\/drawings\/(?:[^/]+\.xml|_rels\/[^/]+\.xml\.rels)$/i.test(path)) omitted.add(partKey(path)) + const match = /^(.*\/)?_rels\/([^/]+)\.rels$/i.exec(path) + if (match === null) continue + const owner = `${match[1] ?? ''}${match[2]}` + new XMLParser({ + removeNSPrefix: true, ignoreAttributes: false, attributeNamePrefix: '', parseAttributeValue: false, + updateTag: (tag: string, _path, attributes: Record) => { + const type = typeof attributes.Type === 'string' + ? attributes.Type.replace(/^http:\/\/purl\.oclc\.org\/ooxml\/officeDocument\/relationships\//, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/') : undefined + if (tag !== 'Relationship' || attributes.TargetMode === 'External') return tag + const drawing = type === 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing' + if (!drawing && type !== 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet') return tag + if (typeof attributes.Target !== 'string') throw new Error('Missing XLSX relationship target') + const target = resolvePart(owner, attributes.Target) + const content = this.parts.get(partKey(target)) + if (content === undefined) throw new Error(`Missing XLSX part: ${target}`) + this.inspectContent(content) + if (drawing) { + omitted.add(partKey(target)) + const split = target.lastIndexOf('/') + omitted.add(partKey(`${target.slice(0, split + 1)}_rels/${target.slice(split + 1)}.rels`)) + } + return tag + }, + }).parse(decodeXml(bytes)) + } + const retained = entries.filter(([path]) => !omitted.has(partKey(path))) return retained.length === entries.length ? this.bytes : new Uint8Array(zipSync(Object.fromEntries(retained), { level: 0 })) } @@ -52,6 +78,33 @@ export class XlsxPreviewArchive { if (tag === 'sheetData') return false return tag }, - }).parse(strFromU8(bytes)) + }).parse(decodeXml(bytes)) } } + +/** OPC compares part names using ASCII case equivalence, leaving ZIP names intact. */ +function partKey(path: string): string { + return path.replace(/[A-Z]/g, character => character.toLowerCase()) +} + +/** Decode the mandatory XML encodings without rewriting the archived bytes. */ +function decodeXml(bytes: Uint8Array): string { + const encoding = (bytes[0] === 0xff && bytes[1] === 0xfe) || (bytes[0] === 0x3c && bytes[1] === 0) + ? 'utf-16le' + : (bytes[0] === 0xfe && bytes[1] === 0xff) || (bytes[0] === 0 && bytes[1] === 0x3c) + ? 'utf-16be' : 'utf-8' + return new TextDecoder(encoding, { fatal: true }).decode(bytes) +} + +/** Resolve internal relationship targets without accepting traversal above the package root. */ +function resolvePart(owner: string, target: string): string { + const parts = target.startsWith('/') ? [] : owner.split('/').slice(0, -1) + for (const segment of target.split('/')) { + if (segment === '' || segment === '.') continue + if (segment === '..') { + if (parts.length === 0) throw new Error('XLSX relationship escapes package') + parts.pop() + } else parts.push(segment) + } + return parts.join('/') +} diff --git a/packages/client/ui-sidebar-documentpreview/tests/excel-opc-fixture.ts b/packages/client/ui-sidebar-documentpreview/tests/excel-opc-fixture.ts new file mode 100644 index 0000000000..d54869680d --- /dev/null +++ b/packages/client/ui-sidebar-documentpreview/tests/excel-opc-fixture.ts @@ -0,0 +1,14 @@ +/** Independent-writer XLSX files shared by parser and shipped-browser regressions. */ +import { readFile } from 'node:fs/promises' + +/** Five isolated failures and one workbook combining their features. */ +export const excelOpcCases = ['comments', 'table', 'prefix', 'part-name', 'relative', 'combined'] as const + +/** + * Read an Openpyxl or XlsxWriter fixture without regenerating it with the parser under test. + * @param name - Retained fixture name. + * @returns Complete XLSX bytes owned by the caller. + */ +export async function excelOpcFixture(name: typeof excelOpcCases[number]): Promise> { + return new Uint8Array(await readFile(new URL(`./fixtures/excel-opc/${name}.xlsx`, import.meta.url))) +} diff --git a/packages/client/ui-sidebar-documentpreview/tests/excel-opc.client.spec.ts b/packages/client/ui-sidebar-documentpreview/tests/excel-opc.client.spec.ts new file mode 100644 index 0000000000..476bb4bac9 --- /dev/null +++ b/packages/client/ui-sidebar-documentpreview/tests/excel-opc.client.spec.ts @@ -0,0 +1,100 @@ +/** OPC part resolution and namespace aliases preserve independent-writer workbook contents. */ +import { createRequire } from 'node:module' +import ExcelJS from 'exceljs' +import { strFromU8, strToU8, unzipSync, zipSync } from 'fflate' +import { describe, expect, it } from 'vitest' +import { Config } from '../src/config.ts' +import { convertExcel } from '../src/client/excel/convert.ts' +import { XlsxPreviewArchive } from '../src/client/excel/xlsx-archive.ts' +import { excelOpcCases, excelOpcFixture } from './excel-opc-fixture.ts' +import { excelFixture, excelHtmlFixture } from './excel-fixture.ts' + +const require = createRequire(import.meta.url) +const browserExcel = require('exceljs/dist/exceljs.js') as typeof ExcelJS +const limits = Config({}).excel +const relsPath = 'xl/worksheets/_rels/budget.xml.rels' + +describe.each([['Node', ExcelJS], ['browser bundle', browserExcel]] as const)('%s ExcelJS entry', (_name, parser) => { + it.each(excelOpcCases)('opens %s without changing source bytes', async (name) => { + const source = await excelOpcFixture(name) + const before = source.slice() + const archive = new XlsxPreviewArchive(source) + const input = archive.withoutDrawings() + const workbook = new parser.Workbook() + await workbook.xlsx.load(input.buffer, { ignoreNodes: ['drawing'] }) + const sheet = workbook.getWorksheet('数据')! + expect(sheet.getCell('A1').value).toBe('Item') + expect(sheet.getCell('B2').value).toBe(42) + if (name === 'comments' || name === 'combined') { + expect(sheet.getCell('B2').note).toBe('生成的批注') + } + if (name === 'table' || name === 'combined') { + expect(sheet.getTable('DataTable')).toMatchObject({ table: { name: 'DataTable', tableRef: 'A1:B3' } }) + } + expect(source).toEqual(before) + }) + + it('binds comment VML independently of relationship order and ZIP entry order', async () => { + const source = await excelOpcFixture('combined') + const files = unzipSync(new XlsxPreviewArchive(source).withoutDrawings()) + const comments = 'xl/comments/comment1.xml' + files[comments] = strToU8(strFromU8(files[comments]!).replace('', '').replace('', '')) + const vml = 'xl/drawings/commentsDrawing1.vml' + files[vml] = strToU8(strFromU8(files[vml]!).replace('insetmode="auto"', 'insetmode="custom"')) + const xml = strFromU8(files[relsPath]!) + const relations = xml.match(/]*\/>/g)! + files[relsPath] = strToU8(xml.replace(relations.join(''), [...relations].reverse().join(''))) + const workbook = new parser.Workbook() + await workbook.xlsx.load(new Uint8Array(zipSync(Object.fromEntries(Object.entries(files).reverse()))).buffer, { ignoreNodes: ['drawing'] }) + expect(workbook.getWorksheet('数据')!.getCell('B2').note).toMatchObject({ + texts: [{ text: '生成的批注', font: { bold: true } }], margins: { insetmode: 'custom' }, + }) + }) +}) + +it('retains styles, formulas, hidden sheets and notices in the combined workbook', async () => { + const source = await excelOpcFixture('combined') + const result = await convertExcel(source, 'xlsx', limits) + const sheet = result.sheets[0]! + expect(result.sheets.map(sheet => [sheet.name, sheet.hide])).toEqual([['数据', 0], ['隐藏页', 1]]) + expect(sheet.celldata!.find(cell => cell.r === 1 && cell.c === 1)!.v).toMatchObject({ v: 42, bl: 1, fc: '#112233', bg: '#FFFF00' }) + expect(sheet.celldata!.find(cell => cell.r === 4 && cell.c === 0)!.v?.v).toBe(' & 中文😀\n tail ') + expect(sheet.celldata!.find(cell => cell.r === 5 && cell.c === 0)!.v?.f).toBe('=SUM(B2:B3)') + expect(sheet.config).toMatchObject({ merge: { '29_7': { r: 29, c: 7, rs: 1, cs: 3 } }, rowhidden: { 2: 0 }, colhidden: { 1: 0 } }) + expect(sheet.frozen).toMatchObject({ type: 'rangeBoth', range: { row_focus: 0, column_focus: 0 } }) + expect(result.unsupportedFeatures).toEqual(['charts', 'conditionalFormatting']) + const workbook = new ExcelJS.Workbook() + await workbook.xlsx.load(new XlsxPreviewArchive(source).withoutDrawings().buffer, { ignoreNodes: ['drawing'] }) + expect(workbook.getWorksheet('数据')!.getCell('A2').hyperlink).toBe('https://example.com/?a=1&b=2') +}) + +it.each([excelFixture, excelHtmlFixture])('preserves cells and attributes under equivalent namespace aliases', async (fixture) => { + const source = await fixture() + const files = unzipSync(source) + for (const [path, bytes] of Object.entries(files)) { + if (!/^xl\/worksheets\/[^/]+\.xml$/.test(path)) continue + files[path] = strToU8(strFromU8(bytes) + .replace('xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"', 'xmlns:s="http://schemas.openxmlformats.org/spreadsheetml/2006/main"') + .replace(/<(\/?)([A-Za-z_][\w.-]*)(?=[\s/>])/g, '<$1s:$2') + .replaceAll('xmlns:r=', 'xmlns:link=').replaceAll(' r:id=', ' link:id=')) + } + expect(await convertExcel(new Uint8Array(zipSync(files)), 'xlsx', limits)).toEqual(await convertExcel(source, 'xlsx', limits)) +}) + +it.each(['part', 'relationship', 'escape', 'external'] as const)('rejects a missing or invalid worksheet %s instead of dropping the sheet', async (defect) => { + const files = unzipSync(await excelFixture()) + if (defect === 'part') delete files['xl/worksheets/sheet2.xml'] + else { + const path = 'xl/_rels/workbook.xml.rels' + const xml = strFromU8(files[path]!) + files[path] = strToU8(defect === 'relationship' ? xml.replace(/]*Target="worksheets\/sheet2.xml"[^>]*\/>/, '') + : xml.replace('Target="worksheets/sheet2.xml"', defect === 'escape' ? 'Target="../../sheet2.xml"' : 'Target="https://example.com/sheet2.xml" TargetMode="External"')) + } + await expect(convertExcel(new Uint8Array(zipSync(files)), 'xlsx', limits)).rejects.toMatchObject({ code: 'invalid' }) +}) + +it.each(['xl/comments/comment1.xml', 'xl/tables/table1.xml', 'xl/drawings/commentsDrawing1.vml'])('rejects missing referenced metadata %s', async (path) => { + const files = unzipSync(await excelOpcFixture('combined')) + Reflect.deleteProperty(files, path) + await expect(convertExcel(new Uint8Array(zipSync(files)), 'xlsx', limits)).rejects.toMatchObject({ code: 'invalid' }) +}) diff --git a/packages/client/ui-sidebar-documentpreview/tests/excel-opening-fixture.ts b/packages/client/ui-sidebar-documentpreview/tests/excel-opening-fixture.ts new file mode 100644 index 0000000000..e9a4953ff3 --- /dev/null +++ b/packages/client/ui-sidebar-documentpreview/tests/excel-opening-fixture.ts @@ -0,0 +1,36 @@ +/** Opening regressions derived from the independent-writer combined workbook. */ +import { strFromU8, strToU8, unzipSync, zipSync } from 'fflate' +import { excelOpcFixture } from './excel-opc-fixture.ts' + +/** Supported URI aliases, ASCII case-equivalent part names and orphan DrawingML. */ +export const excelOpeningCases = ['strict', 'case-root', 'case-parts', 'orphan-drawing'] as const + +/** + * Change only the package property under test in an independent-writer workbook. + * @param name - Opening regression to construct. + * @returns Complete XLSX bytes owned by the caller. + */ +export async function excelOpeningFixture(name: typeof excelOpeningCases[number]): Promise> { + const files = unzipSync(await excelOpcFixture('combined')) + const result: Record = {} + for (const [path, bytes] of Object.entries(files)) { + let xml = /\.(xml|rels|vml)$/.test(path) ? strFromU8(bytes) : undefined + let target = path + if (xml !== undefined) { + if (name === 'strict') { + xml = xml.replaceAll('http://schemas.openxmlformats.org/spreadsheetml/2006/main', 'http://purl.oclc.org/ooxml/spreadsheetml/main') + .replaceAll('http://schemas.openxmlformats.org/officeDocument/2006/relationships', 'http://purl.oclc.org/ooxml/officeDocument/relationships') + } else if (name === 'case-root' && path === '_rels/.rels') { + xml = xml.replace('Target="xl/workbook.xml"', 'Target="XL/WORKBOOK.XML"') + } else if (name === 'case-parts') { + if (!path.startsWith('docProps/') && !path.startsWith('xl/theme/')) target = path.toUpperCase() + if (path.endsWith('.rels')) xml = xml.replace(/Target="([^"]+)"/g, (attribute, value: string) => value.includes('://') ? attribute : `Target="${value.toLowerCase()}"`) + } else if (name === 'orphan-drawing') { + if (path.endsWith('.rels')) xml = xml.replace(/]*Type="[^"]*\/drawing"[^>]*\/>/g, '') + if (path.startsWith('xl/worksheets/')) xml = xml.replace(/<(?:\w+:)?drawing\b[^>]*\/>/g, '') + } + } + result[target] = xml === undefined ? bytes : strToU8(xml) + } + return new Uint8Array(zipSync(result)) +} diff --git a/packages/client/ui-sidebar-documentpreview/tests/excel-opening.client.spec.ts b/packages/client/ui-sidebar-documentpreview/tests/excel-opening.client.spec.ts new file mode 100644 index 0000000000..e25c12e936 --- /dev/null +++ b/packages/client/ui-sidebar-documentpreview/tests/excel-opening.client.spec.ts @@ -0,0 +1,85 @@ +/** URI and part-name aliases and orphan drawings preserve usable workbook previews. */ +import assert from 'node:assert/strict' +import { createRequire } from 'node:module' +import ExcelJS from 'exceljs' +import { strFromU8, strToU8, unzipSync, zipSync } from 'fflate' +import { describe, expect, it } from 'vitest' +import { Config } from '../src/config.ts' +import { convertExcel } from '../src/client/excel/convert.ts' +import { XlsxPreviewArchive } from '../src/client/excel/xlsx-archive.ts' +import { excelOpeningCases, excelOpeningFixture } from './excel-opening-fixture.ts' +import { excelOpcFixture } from './excel-opc-fixture.ts' + +const require = createRequire(import.meta.url) +const browserExcel = require('exceljs/dist/exceljs.js') as typeof ExcelJS +const limits = Config({}).excel + +describe.each([['Node', ExcelJS], ['browser bundle', browserExcel]] as const)('%s opening regressions', (_name, parser) => { + it.each(excelOpeningCases)('opens %s with cells, styles, comments, Tables and hyperlinks', async (name) => { + const source = await excelOpeningFixture(name) + const original = source.slice() + const retained = new XlsxPreviewArchive(source).withoutDrawings() + const workbook = new parser.Workbook() + await workbook.xlsx.load(retained.buffer, { ignoreNodes: ['drawing'] }) + const sheet = workbook.getWorksheet('数据') + assert.ok(sheet) + expect(sheet.getCell('A1').value).toBe('Item') + expect(sheet.getCell('B2').value).toBe(42) + expect(sheet.getCell('B2').font).toMatchObject({ bold: true, color: { argb: 'FF112233' } }) + expect(sheet.getCell('B2').note).toBe('生成的批注') + expect(sheet.getTable('DataTable')).toMatchObject({ table: { tableRef: 'A1:B3' } }) + expect(sheet.getCell('A2').hyperlink).toBe('https://example.com/?a=1&b=2') + expect(workbook.getWorksheet('隐藏页')?.state).toBe('hidden') + const originalParts = unzipSync(source) + for (const [path, bytes] of Object.entries(unzipSync(retained))) expect(bytes, path).toEqual(originalParts[path]) + expect(source).toEqual(original) + }) + + it.each(['xl/workbook.xml', '_rels/.rels'])('rejects ambiguous ASCII case-equivalent entries for %s', async (path) => { + const files = unzipSync(await excelOpcFixture('combined')) + const bytes = files[path] + assert.ok(bytes) + files[path.toUpperCase()] = bytes + const source = new Uint8Array(zipSync(files)) + await expect(new parser.Workbook().xlsx.load(source.buffer)).rejects.toThrow(/Ambiguous.*part/i) + }) +}) + +it.each(excelOpeningCases)('preserves the complete preview and referenced-content notices for %s', async (name) => { + const expected = await convertExcel(await excelOpcFixture('combined'), 'xlsx', limits) + if (name === 'orphan-drawing') expected.unsupportedFeatures = ['conditionalFormatting'] + expect(await convertExcel(await excelOpeningFixture(name), 'xlsx', limits)).toEqual(expected) +}) + +it('omits orphan DrawingML and its relationships while retaining comment VML', async () => { + const source = await excelOpeningFixture('orphan-drawing') + const original = unzipSync(source) + expect(original['xl/drawings/drawing1.xml']).toBeDefined() + expect(original['xl/drawings/_rels/drawing1.xml.rels']).toBeDefined() + const archive = new XlsxPreviewArchive(source) + const retained = unzipSync(archive.withoutDrawings()) + expect(retained['xl/drawings/drawing1.xml']).toBeUndefined() + expect(retained['xl/drawings/_rels/drawing1.xml.rels']).toBeUndefined() + expect(retained['xl/drawings/commentsDrawing1.vml']).toEqual(original['xl/drawings/commentsDrawing1.vml']) + expect([...archive.unsupportedFeatures]).toEqual(['conditionalFormatting']) +}) + +it('rejects ambiguous part names before filtering can hide either entry', async () => { + const files = unzipSync(await excelOpcFixture('combined')) + const drawing = files['xl/drawings/drawing1.xml'] + assert.ok(drawing) + files['XL/DRAWINGS/DRAWING1.XML'] = drawing + await expect(convertExcel(new Uint8Array(zipSync(files)), 'xlsx', limits)).rejects.toMatchObject({ code: 'invalid' }) +}) + +it('does not fold non-ASCII characters when resolving part names', async () => { + const files = unzipSync(await excelOpcFixture('combined')) + const path = 'xl/_rels/workbook.xml.rels' + const rels = files[path] + const sheet = files['xl/worksheets/budget.xml'] + assert.ok(rels) + assert.ok(sheet) + files[path] = strToU8(strFromU8(rels).replace('worksheets/budget.xml', 'worksheets/Ä.xml')) + files['xl/worksheets/ä.xml'] = sheet + await expect(convertExcel(new Uint8Array(zipSync(files)), 'xlsx', limits)).rejects.toMatchObject({ code: 'invalid' }) +}) diff --git a/packages/client/ui-sidebar-documentpreview/tests/excel-xml-fixture.ts b/packages/client/ui-sidebar-documentpreview/tests/excel-xml-fixture.ts new file mode 100644 index 0000000000..f1f743d677 --- /dev/null +++ b/packages/client/ui-sidebar-documentpreview/tests/excel-xml-fixture.ts @@ -0,0 +1,14 @@ +/** Equivalent XML encodings and package layouts produced with XlsxWriter. */ +import { readFile } from 'node:fs/promises' + +/** Baseline and equivalent workbooks covering XML text and relocated core parts. */ +export const excelXmlCases = ['rich', 'utf16-sheet', 'utf16-metadata', 'workbook-path', 'styles-path', 'strings-path', 'cdata', 'parts-path'] as const + +/** + * Read committed independent-writer bytes for parser and browser tests. + * @param name - Retained fixture name. + * @returns Complete XLSX bytes owned by the caller. + */ +export async function excelXmlFixture(name: typeof excelXmlCases[number]): Promise> { + return new Uint8Array(await readFile(new URL(`./fixtures/excel-xml/${name}.xlsx`, import.meta.url))) +} diff --git a/packages/client/ui-sidebar-documentpreview/tests/excel-xml.client.spec.ts b/packages/client/ui-sidebar-documentpreview/tests/excel-xml.client.spec.ts new file mode 100644 index 0000000000..fb3c5e3c54 --- /dev/null +++ b/packages/client/ui-sidebar-documentpreview/tests/excel-xml.client.spec.ts @@ -0,0 +1,112 @@ +/** XML decoding and OPC discovery preserve cells, metadata and preview notices. */ +import { createRequire } from 'node:module' +import ExcelJS from 'exceljs' +import { strFromU8, strToU8, unzipSync, zipSync } from 'fflate' +import { describe, expect, it } from 'vitest' +import { Config } from '../src/config.ts' +import { convertExcel } from '../src/client/excel/convert.ts' +import { XlsxPreviewArchive } from '../src/client/excel/xlsx-archive.ts' +import { excelXmlCases, excelXmlFixture } from './excel-xml-fixture.ts' + +const require = createRequire(import.meta.url) +const browserExcel = require('exceljs/dist/exceljs.js') as typeof ExcelJS +const limits = Config({}).excel + +describe.each([['Node', ExcelJS], ['browser bundle', browserExcel]] as const)('%s XML reader', (_name, parser) => { + it.each(excelXmlCases)('preserves comments and Tables in %s', async (name) => { + const source = await excelXmlFixture(name) + const original = source.slice() + const archive = new XlsxPreviewArchive(source) + const retained = archive.withoutDrawings() + const workbook = new parser.Workbook() + await workbook.xlsx.load(retained.buffer, { ignoreNodes: ['drawing'] }) + const sheet = workbook.getWorksheet('数据')! + expect(sheet.getCell('A5').value).toBe(' & 中文😀\n tail ') + expect(sheet.getCell('A6').value).toEqual({ formula: 'SUM(B2:B3)', result: 57 }) + expect(sheet.getCell('B2').note).toMatchObject({ texts: [{ text: '生成的批注' }] }) + expect(sheet.getTable('Table1')).toMatchObject({ table: { name: 'Table1', tableRef: 'A1:B3' } }) + expect(sheet.getCell('B2').font).toMatchObject({ bold: true, color: { argb: 'FF112233' } }) + expect(workbook.getWorksheet('隐藏页')!.state).toBe('hidden') + const originalParts = unzipSync(source) + for (const [path, bytes] of Object.entries(unzipSync(retained))) expect(bytes, path).toEqual(originalParts[path]) + expect(source).toEqual(original) + }) +}) + +it.each(excelXmlCases)('preserves the complete preview for %s', async (name) => { + const expected = await convertExcel(await excelXmlFixture('rich'), 'xlsx', limits) + expect(await convertExcel(await excelXmlFixture(name), 'xlsx', limits)).toEqual(expected) + expect(expected.unsupportedFeatures).toEqual(['charts', 'images', 'shapes', 'conditionalFormatting']) + const sheet = expected.sheets[0]! + expect(sheet.celldata!.find(cell => cell.r === 1 && cell.c === 1)!.v).toMatchObject({ v: 42, bl: 1, fc: '#112233', bg: '#FFFF00' }) + expect(sheet.config).toMatchObject({ merge: { '29_7': { r: 29, c: 7, rs: 1, cs: 3 } }, rowhidden: { 2: 0 }, colhidden: { 1: 0 } }) + expect(sheet.frozen).toMatchObject({ type: 'rangeBoth', range: { row_focus: 0, column_focus: 0 } }) +}) + +it.each(['utf-16le', 'utf-16be'] as const)('decodes %s parts and relationships with and without a BOM', async (encoding) => { + const source = await excelXmlFixture('rich') + const expected = await convertExcel(source, 'xlsx', limits) + for (const bom of [false, true]) { + const files = unzipSync(source) + for (const [path, bytes] of Object.entries(files)) { + if (!/\.(xml|rels|vml)$/.test(path)) continue + const xml = strFromU8(bytes).replace(/encoding="UTF-8"/i, 'encoding="UTF-16"') + const encoded = Buffer.from(`${bom ? '\uFEFF' : ''}${xml}`, 'utf16le') + if (encoding === 'utf-16be') encoded.swap16() + files[path] = encoded + } + expect(await convertExcel(new Uint8Array(zipSync(files)), 'xlsx', limits)).toEqual(expected) + } +}) + +it.each(['xl/workbook.xml', 'xl/styles.xml', 'xl/sharedStrings.xml', '_rels/.rels', 'xl/_rels/workbook.xml.rels'])('rejects missing core part %s', async (path) => { + const files = unzipSync(await excelXmlFixture('rich')) + Reflect.deleteProperty(files, path) + await expect(convertExcel(new Uint8Array(zipSync(files)), 'xlsx', limits)).rejects.toMatchObject({ code: 'invalid' }) +}) + +it('ignores unrelated binary parts without trying to decode them as XML', async () => { + const source = await excelXmlFixture('rich') + const files = unzipSync(source) + files['xl/vbaProject.bin'] = Uint8Array.of(0xff, 0x80, 0x81) + expect(await convertExcel(new Uint8Array(zipSync(files)), 'xlsx', limits)).toEqual(await convertExcel(source, 'xlsx', limits)) +}) + +it('preserves text split across escaped text and CDATA segments', async () => { + const source = await excelXmlFixture('rich') + const files = unzipSync(source) + const path = 'xl/sharedStrings.xml' + files[path] = strToU8(strFromU8(files[path]!).replace('Item', 'Iem')) + expect(await convertExcel(new Uint8Array(zipSync(files)), 'xlsx', limits)).toEqual(await convertExcel(source, 'xlsx', limits)) +}) + +it('finds a drawing owned by a part at the package root', () => { + const archive = new XlsxPreviewArchive(new Uint8Array(zipSync({ + '_rels/root.xml.rels': strToU8(''), + 'drawing.xml': strToU8(''), + '_rels/drawing.xml.rels': strToU8(''), + }))) + expect(Object.keys(unzipSync(archive.withoutDrawings()))).toEqual(['_rels/root.xml.rels']) + expect([...archive.unsupportedFeatures]).toEqual(['charts']) +}) + +it('rejects a worksheet relationship with no target', async () => { + const files = unzipSync(await excelXmlFixture('rich')) + const path = 'xl/_rels/workbook.xml.rels' + files[path] = strToU8(strFromU8(files[path]!).replace('Target="worksheets/sheet1.xml"', '')) + await expect(convertExcel(new Uint8Array(zipSync(files)), 'xlsx', limits)).rejects.toMatchObject({ code: 'invalid' }) +}) + +it.each(['missing', 'external', 'duplicate'] as const)('rejects a %s officeDocument relationship', async (defect) => { + const files = unzipSync(await excelXmlFixture('rich')) + const xml = strFromU8(files['_rels/.rels']!) + const relation = xml.match(/]*officeDocument"[^>]*\/>/)![0] + files['_rels/.rels'] = strToU8(xml.replace(relation, defect === 'missing' ? '' : defect === 'duplicate' ? relation + relation : relation.replace('/>', ' TargetMode="External"/>'))) + await expect(convertExcel(new Uint8Array(zipSync(files)), 'xlsx', limits)).rejects.toMatchObject({ code: 'invalid' }) +}) + +it('rejects malformed UTF-16 without replacing invalid code units', async () => { + const files = unzipSync(await excelXmlFixture('rich')) + files['xl/worksheets/sheet1.xml'] = Uint8Array.of(0xff, 0xfe, 0x3c) + await expect(convertExcel(new Uint8Array(zipSync(files)), 'xlsx', limits)).rejects.toMatchObject({ code: 'invalid' }) +}) diff --git a/packages/client/ui-sidebar-documentpreview/tests/fixtures/excel-opc/combined.xlsx b/packages/client/ui-sidebar-documentpreview/tests/fixtures/excel-opc/combined.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..e3d02cd12786c27ead0c2d091a099226b5092d25 GIT binary patch literal 8781 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 literal 0 HcmV?d00001 diff --git a/packages/client/ui-sidebar-documentpreview/tests/fixtures/excel-opc/comments.xlsx b/packages/client/ui-sidebar-documentpreview/tests/fixtures/excel-opc/comments.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..53b90c36e559d8dd099a2c018f0338152bb07fa5 GIT binary patch literal 6261 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 F{{v~bj}`y` literal 0 HcmV?d00001 diff --git a/packages/client/ui-sidebar-documentpreview/tests/fixtures/excel-opc/part-name.xlsx b/packages/client/ui-sidebar-documentpreview/tests/fixtures/excel-opc/part-name.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..b8a3bc7a97ad15c5ecfb34ecd15fca61f7c989e2 GIT binary patch literal 4898 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 Ma6AwHJkJ392VbR0$p8QV literal 0 HcmV?d00001 diff --git a/packages/client/ui-sidebar-documentpreview/tests/fixtures/excel-opc/prefix.xlsx b/packages/client/ui-sidebar-documentpreview/tests/fixtures/excel-opc/prefix.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..f3ae57754c7bbbae4257ff031d6f0430c747b1a8 GIT binary patch literal 4907 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 KPyIaD0Q?7EjZI1b literal 0 HcmV?d00001 diff --git a/packages/client/ui-sidebar-documentpreview/tests/fixtures/excel-opc/relative.xlsx b/packages/client/ui-sidebar-documentpreview/tests/fixtures/excel-opc/relative.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..4a3ada5581329d3048d80d4c67ad78b582fe0744 GIT binary patch literal 5325 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 literal 0 HcmV?d00001 diff --git a/packages/client/ui-sidebar-documentpreview/tests/fixtures/excel-opc/table.xlsx b/packages/client/ui-sidebar-documentpreview/tests/fixtures/excel-opc/table.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..4b37ab4051b5426a8e99281c2ecc4da6ffc31c16 GIT binary patch literal 5575 zcmaJ_1z3~syBG%r|DL zZmw{sE8NP^-yP~@A?WAg{3;pg+96ERV^!2oU1uZvLs(zXZaluz@>;E6d}c@tDW98S z2`=JRxm~z+`6u+g_6gV`kO|v*%xtlWNStk16r&UfN}kTloD=coX8TyMuRKH&FUSJ=F^G zmsitbTA1Epyh(`-01#t#D^IAimyqDEYfe&=Yo{=YQb_m5Tw(l=Y|&!SEgGCdETe*} z6F}S;aL(Jx$s&&gVtRjhIp8!4Ole&TQ6F1McS?R6W;)u4rBToE6gHHoQt^qOMIvfM z>E@K3YLzL!f|4Npy@ogTG$me$yV2(3IYshQLVC(>p_MW^9x5;mZ85UV!I2Qr{T&hs z@Uj*t#f-rZwS49?uQ{B5-Iyj5{2o=nTol6Gi%vkTRoY#z4KQ0h^l&sJdNOUt5$9oB zdnOV7{_2llz~6?d_1@A*!5BD*S>%{y?`8+_baVF-vT=9+rJY;ITf`Xc;LX3i?bDDE z!-62YDIb&DiWKyYsONEcbhNRKqv-1I-^W-W`1m?!eL8qcaLGkXw3k$A40NP0(4QZZ zzx1F&WF{=`HN#Z|E6bJ60+;d72oVyg4+{-dYo7$w9K4aKD!$b+`kb8$#^N%sxme4l znTW_&0yq?6DYd23_;Al-4F;$Ua=-Swo!H~P#c!tl+XR)H*iDC+zs`p_D~f-bVCUuu z{bfUUQoB}{FnOdE*wc**wiceBH4wvv+aA6kz+ThRUQDWqm}!uVZ?OPxs0d~p?hHyM z7)e*CJ=F__uNJnui%kU+m^TSX_pC}OLDXwSlX*lCUxRmzdfi+7i*=@3KRfs7i>a-j(nQgPrjSG%b2g)<8{BdEtD%9A}5CW)v7E(0VWrK-3(7RG#nemRpC~P)l#rMj}|qEi>FSx%m)a#dVGe%P}Q^Mq@)L*W?c$O~Vp}7rFwaynHZn+wC$5xtRb)kPd zY4^JE|g zWlc%=T%9HrMa^nEM5O9v<#sH$DKzl3&-pqAUf84-vI@j|JASZxw7J?|YUre8odWK3 zMR{yQh&_N{bJ5KyJ11LJFx$I(o-~`w+l#TuUF&OaR%>jLDTFoX7wjpyZ^L^^8Z4eX z-#2>rQ6soIGK$GHP9M;qp8rYg$*TH;mE)1>iSNC5Qy;26Wf2g@+rlZSch5^2R*&;$ zs&(5;&!M4CIv+#G#$vg+O#KOuirzd`j39eF4bCekNwdoe>di5zA@-p|Y>&iEn%syN z-f+6IpUY}px^dEZs8$;YIfG(1eC7|KjAw#NZh+>!5hn=1`GD`_|;{abt0ZGJ>ZjOJ`G zFW9dHjd{V~Hnte;{n=Z7HVpVtGgux(Yz0~F`=eIHYC>Hmn? z+D9;}zALQUkRPwWZIkC6mk6l11L#n5Q<|6RH}!tU|yVC>*nLe^$FhvW|NG*wE=^mwdv{y0v-vmy%wvBgF&sac@s@x zM3F9XY3EmyEL2#^Hp)(0{wISZU4Hdnb)KgRq#gT zM?VL&3vthlu=-j`FPP6%ZN{T@UDgN+<9KI(`@}~fZ`E&*52TW=C*5k!lEdL&J01e7 zudGV>@B9?BU5$)R-uAQpEHpLN(jYWDe^->9LRpx;q;m5eQIU>iohb~^DHZgd64*H% z9!sF@M>Q~JK5xb#1RDERJ2hkU2y}i>8lmCu zgOYKZHPMAAY64MGS(zN;A)i2W*Lq%D|0G=8g<*bi%TKC)U?kR^31?ovCATAI*ZD0% znXtAH_R)R>AdA1Xe27$IN#mjhH8lA$jT`3bEqxAGHi9fQnlqPSdTDLrMF98?04 zXmnx`hbVI6km$RvoCB*-YLx{Nxs)5{32K=^8wa8F)LlX2rSEF4k0-0KgY)_XnwKb~ z>NH73DHREFBGa89OxOrQk<|RigW8^Qih0VQhBkt}x%lY)GPg|myZOeNlaCI_)fg7C zy}o)4J0Ig0sSTs=v`!bM8B=4W(anj!l;H0k^GkWR^(tGAnG!gdOpK=-na0iuER_zv zr9pYdS2TH+jZ)f77GgirN_+~d0hPcx2Uo=y+SMuY(6LQLv@I!Qfd(6ISn0`pDW8*fZ>>J5oz=Vp1;gOu@SE$6%uO z&{!fFMUtf?=C?z!2^4QxBBiu4*9$z1aZYnBJ2l%^!w2r2HU>wIiaGN?*;oHWtF?5M zvqW)CR2;uB(}eKNBO|B0mr>#hFIYs0aJQOR6qW=0h$K^cS|JtT53tUMCnY<|4#M9_ zhX@8Ci#D2eJk{(?kG7lb{_|qs-oT65GGY+eNr)Z^l75V2FZB#sG6w7+u#4_Ow#Qmn)mN z8|BQF)++Pi3jD}JIjfc0L1Ho022bs8^~r5@oKjl5uRpl!vJ8;OI>;q4*ZV$amN-UR z_$+~ngbmVE8yQsEuDCSkOv^~+rYANLp>8L*bsnyD`!Os?f5vGFO26x}GBG@Sywa{; zRk$IS%G?{hUBLD;KQbNJsT$?~z$)D#r3WHT<>Fk<&ac*B-8jC*Pc?6EE$|%wVWmFy z_U${?B4#~T_!0^Nb>hIQ?kj2LR*S<)i&MqWI@d}bUwW78x1~E^>68v-{j<>5?RS`w zcg(h{+MMKTsdbTOCa?PPNGNn^h=Ce*$+X2<1v~TxZ7Y15U3aA3g2n2AX>_fNUwb`t z4H|(y^;fY)n_8qx1E3-f#oKcNB!v8C(I&u!TNdl1D_PkU0oQ$w(tO*kw@=;Qt6yD~ zU9sA=P^}0?&nzCfK9kkZ$@cH2z=DIZK`BglG_;~ike^8jc$8R!$?tD&Vu#xoGlixf z5x?0cY2u+CdZi#80_J}hscSjH0i=qlBEe;&^<3Q8c;@6AH-5w)=JLo;)P9tM3!w&qH`Lym0O+6P-<*RoE=rV!|vd6K|S zWu`^;d=!e>_<^iRcy@7SyW&<)scc^rzkby-DMI2OYP>^|e@|*I3Y^IxHX2(l9Z%$@ zJgT&;IQ5Ct5lt%2l!$97l2L!7a7mX)Zu)G4w5p@)$(Qxmx0k9n9#bg00w#NcFcsX@ zKN<9&#c900vTmm^`H9vNenNe?mLVxE?{i>yOu_7oJ*wR4LE&C~#90_xT$L0LqsD*wyL-Ao9#2yhw#WVL{vmGVr!>&yNwY;sL<(pqC9E%{f z6%l*Ddq;-}4UPHy?1zY%jy;P#y`FbaPoVg7l)3>avg+|<{A8YU1&M}uk*vzO3}RV^T1_!OF5yZZ32+SW=45*zx+iSqmMRjW zabS~wmDUHy^%>L#b}+l=M8k-UkE@OY>ZM?5Zz5oKIgzn>`B;?3a?)Y9vh#=Nz$}j6 z&3#m=xx+V04i3X&uame_NvXk_Ool*F=k4SwJ?^2560rF7hNaJ(KUX3&7mT8%=0pz+ zYsATeEV8#H8@5^Hd`QnN@*`Xd%yp7u&B(_OdX^3{drwf;M|=4`4iErJ@N+^{EcWdTj`wcb^i01H*p95MP;)4Egx+!JI1A8^a^tx3bH)mf^M4yBD?4!Zi z_95~pM06J8oPErbZ7bAyAfTMr>>VXd&g!#XR;76zD$^G(j0jX6HQ`7-)81Z`dG^}C zGAl$I3!Cb90sZe2F3bV{{)A#q{9or?mkBNpbN;{qfKV(W48=c2JC}i%ha(q2MNELY zJSw@2zC4$>Kx1Qc`akIZo>E+fUvAeg;Jlbo-~ZjbU*@^o5nu3J#r@55(H~!iUT$bE zpt1P>-rihhxZDw3FvMXF_h0&h%LJD*!Ue$~*>8e>=7-DR%Q5Z(EQOhMVV?dA{QpI~ m%Y>H$%>^M2X7cnm;YHYiXyamEj* literal 0 HcmV?d00001 diff --git a/packages/client/ui-sidebar-documentpreview/tests/fixtures/excel-xml/cdata.xlsx b/packages/client/ui-sidebar-documentpreview/tests/fixtures/excel-xml/cdata.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..4a15bb0319f8a2bae33734d91e092c67181cd018 GIT binary patch literal 11224 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%0Anf$o9 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 literal 0 HcmV?d00001 diff --git a/packages/client/ui-sidebar-documentpreview/tests/fixtures/excel-xml/strings-path.xlsx b/packages/client/ui-sidebar-documentpreview/tests/fixtures/excel-xml/strings-path.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..1eb7d265f4d897bf1b50e72f422a99703ad85396 GIT binary patch literal 11183 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 literal 0 HcmV?d00001 diff --git a/packages/client/ui-sidebar-documentpreview/tests/fixtures/excel-xml/styles-path.xlsx b/packages/client/ui-sidebar-documentpreview/tests/fixtures/excel-xml/styles-path.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..a9b4ebb24e09010cabd5bd6478d48931809781c5 GIT binary patch literal 11196 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 literal 0 HcmV?d00001 diff --git a/packages/client/ui-sidebar-documentpreview/tests/fixtures/excel-xml/utf16-metadata.xlsx b/packages/client/ui-sidebar-documentpreview/tests/fixtures/excel-xml/utf16-metadata.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..92d76dd873017057a4e1706b59e7cf54d04968c1 GIT binary patch literal 11456 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 PLY_AeA5lgB>+XL5L`LRS literal 0 HcmV?d00001 diff --git a/packages/client/ui-sidebar-documentpreview/tests/fixtures/excel-xml/utf16-sheet.xlsx b/packages/client/ui-sidebar-documentpreview/tests/fixtures/excel-xml/utf16-sheet.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..342d632e02e3ebf5675b2d35121f17e355238b1b GIT binary patch literal 11552 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 --report baseline.json` reads that revision's `xlsx.ts` from Git and disables notice comparisons. It still uses the current dependency versions and shared conversion helpers; it cannot reproduce an unpatched ExcelJS baseline after installing the patch. Retain reports from the original dependency state or run that revision in a separate checkout. The temporary baseline module is removed after its worker exits. This compares source parsing, not FortuneSheet browser rendering or the shipped Web profile. + +## Retained regressions + +The [OPC fixtures](../fixtures/excel-opc/) contain five isolated failures copied from the seed 4863 corpus and a combined Openpyxl workbook. Openpyxl 3.1.5 produces comments, Tables, namespace-prefix and part-name cases; XlsxWriter 3.2.9 produces the relative-target case. The combined workbook adds chart, conditional formatting, frozen headings, hidden rows/columns/sheet, a merge, styles, a hyperlink, literal XML-looking text, and a formula, then applies `sheet-prefix` and `sheet-filename` mutations. Openpyxl independently validates the saved inputs. Unit and browser tests read these committed bytes without Python. + +The [XML fixtures](../fixtures/excel-xml/) retain one XlsxWriter 3.2.9 workbook and seven equivalent encodings: UTF-16 worksheet or metadata XML, relocated workbook/styles/shared strings, CDATA text, and relocated worksheet/drawing directories. Each retains a formula cache, Unicode and XML-looking text, comment, Table, styles, merge, frozen headings, hidden content, and all four notice categories. When upgrading ExcelJS, compare the complete preview and comment/Table metadata through both Node and browser entries, then run `apps/web/tests/excel-opc.e2e.ts` against the built Worker. Keep original corpus reports; save replay results under a new `--report` name and inspect ZIP directory integrity separately from independent-reader acceptance. + +The [opening fixtures](../excel-opening-fixture.ts) derive Strict URI aliases, root-target and part-name case variants, and orphan DrawingML from the combined Openpyxl file. These transformations retain cell data and run through both parser entries, full preview comparison, and the shipped browser Worker. Ambiguous ASCII case-equivalent entries are rejected; non-ASCII names remain distinct. + +Run the Node and browser-bundle parser regressions: + +```sh +pnpm exec vitest run packages/client/ui-sidebar-documentpreview/tests/excel-opening.client.spec.ts packages/client/ui-sidebar-documentpreview/tests/excel-opc.client.spec.ts packages/client/ui-sidebar-documentpreview/tests/excel-xml.client.spec.ts +``` + +Fuzz reports record each input's SHA-256, whether it opened, and the worktree status. `validOpened` and `validRejected` separate opening failures from value differences; strict exit status still rejects either defect. Known 1904 time/duration offsets and empty-string formula-cache differences remain diagnostic failures. Corrupt inputs accepted by the parser remain informational. + +Maintain the ExcelJS patch with `pnpm patch` and `pnpm patch-commit` against the published package. Installed dependency trees contain generated launchers that must not enter the patch. Validate patch application in a fresh `pnpm patch --edit-dir ` extraction before relying on tests against a cached installation. diff --git a/packages/client/ui-sidebar-documentpreview/tests/fuzz/README.zh.md b/packages/client/ui-sidebar-documentpreview/tests/fuzz/README.zh.md new file mode 100644 index 0000000000..608acf3d1e --- /dev/null +++ b/packages/client/ui-sidebar-documentpreview/tests/fuzz/README.zh.md @@ -0,0 +1,46 @@ +# XLSX 模糊测试诊断 + +[English](README.md) | 中文 + +使用 Openpyxl 和 XlsxWriter 生成表格文件,再将源码 XLSX 适配器的结果与独立记录的单元格值、公式和不支持内容类别比较。此诊断任务需要显式运行,会保留失败结果并以非零状态退出;它不属于默认单元测试集。 + +## 运行测试 + +安装工作区依赖,并准备装有 Openpyxl、XlsxWriter 和 Pillow 的 Python 解释器。在 PowerShell 中,将 `$excelFuzzPython` 设置为该解释器的可执行文件路径。从仓库根目录运行,并使用新的输出目录: + +```powershell +& $excelFuzzPython packages/client/ui-sidebar-documentpreview/tests/fuzz/generate.py .artifacts/excel-fuzz-new --seed 4863 --random-cases 400 +pnpm exec tsx packages/client/ui-sidebar-documentpreview/tests/fuzz/run.client.ts .artifacts/excel-fuzz-new +``` + +种子控制功能组合、数值和字节变异。ZIP 元数据保持固定;复现还依赖 `manifest.json` 记录的写入器版本。生成器先验证内部关系目标,并用 Openpyxl 重新读取预期单元格,再将工作簿归类为合法文件。被排除的候选保留在 `generatorErrors` 中;随机字节变异单独分类。 + +从已有样本集重跑选定用例: + +```sh +pnpm exec tsx packages/client/ui-sidebar-documentpreview/tests/fuzz/run.client.ts .artifacts/excel-fuzz-new --only openpyxl-table --report table.json +``` + +执行器为每个输入设置 10 秒的可终止 Worker 截止时间,并检查输入不变性、单元格值、公式缓存,以及提示顺序和唯一性。`--timeout-ms` 可修改该诊断时限。报告保留全部结果;`repros/` 包含功能组合较少的代表性失败文件,不声称输入已达到全局最小。被接受的损坏 ZIP 仅作为观察结果,需要单独检查。 + +## 对比旧适配器 + +`--baseline-ref --report baseline.json` 从 Git 读取该版本的 `xlsx.ts`,并禁用提示比较。它仍使用当前依赖版本和共用转换辅助函数,安装补丁后无法复现未修补 ExcelJS 的基线。须保留原依赖状态下的报告,或在独立检出目录中运行旧版本。Worker 退出后会删除临时基线模块。此对比检查源码解析,不覆盖 FortuneSheet 浏览器渲染或发布的 Web 配置。 + +## 保留的回归用例 + +[OPC fixture](../fixtures/excel-opc/) 包含从 seed 4863 语料复制的五类独立失败文件,以及一个组合 Openpyxl 工作簿。Openpyxl 3.1.5 生成批注、Table、命名空间前缀和部件名用例,XlsxWriter 3.2.9 生成相对目标用例。组合工作簿加入图表、条件格式、冻结表头、隐藏行/列/工作表、合并、样式、超链接、类似 XML 的字面文本和公式,再应用 `sheet-prefix` 与 `sheet-filename` 变异。Openpyxl 独立校验保存的输入。单元测试和浏览器测试读取已提交的字节,无需 Python。 + +[XML fixture](../fixtures/excel-xml/) 保留一个 XlsxWriter 3.2.9 工作簿及七种等价编码:UTF-16 工作表或元数据 XML、移动工作簿/样式/共享字符串部件、CDATA 文本,以及移动工作表/绘图目录。每个文件都保留公式缓存、Unicode 和类似 XML 的文本、批注、Table、样式、合并、冻结标题、隐藏内容和全部四类提示。升级 ExcelJS 时,应通过 Node 与浏览器入口比较完整预览及批注/Table 元数据,再对构建后的 Worker 运行 `apps/web/tests/excel-opc.e2e.ts`。保留原始语料报告;重放时使用新的 `--report` 文件名,并在独立读取器验证之外单独检查 ZIP 目录完整性。 + +[打开回归样例](../excel-opening-fixture.ts)基于 Openpyxl 组合文件派生 Strict URI 别名、根目标与部件名大小写变体,以及孤立 DrawingML。变换保留单元格数据,并通过两个解析入口、完整预览比较和实际发布的浏览器 Worker 验证。ASCII 大小写等价的歧义条目会被拒绝;非 ASCII 名称保持区分。 + +运行 Node 和浏览器 bundle 解析器回归测试: + +```sh +pnpm exec vitest run packages/client/ui-sidebar-documentpreview/tests/excel-opening.client.spec.ts packages/client/ui-sidebar-documentpreview/tests/excel-opc.client.spec.ts packages/client/ui-sidebar-documentpreview/tests/excel-xml.client.spec.ts +``` + +fuzz 报告记录每个输入的 SHA-256、能否打开以及工作区状态。`validOpened` 和 `validRejected` 将打开失败与值差异分开,严格退出状态仍会拒绝这两类缺陷。已知的 1904 时间/累计时长偏移和空字符串公式缓存差异仍作为诊断失败。解析器接受的损坏输入继续作为观察结果单列。 + +通过 `pnpm patch` 和 `pnpm patch-commit` 对发布包维护 ExcelJS 补丁。已安装的依赖树包含生成的启动脚本,不得混入补丁。在依赖缓存安装上的测试结果之前,先用 `pnpm patch --edit-dir ` 全新解包,验证补丁能够应用。 diff --git a/packages/client/ui-sidebar-documentpreview/tests/fuzz/excel-worker.client.ts b/packages/client/ui-sidebar-documentpreview/tests/fuzz/excel-worker.client.ts new file mode 100644 index 0000000000..b921e05e66 --- /dev/null +++ b/packages/client/ui-sidebar-documentpreview/tests/fuzz/excel-worker.client.ts @@ -0,0 +1,29 @@ +/** Test-only Client parser isolation; the parent owns deadlines and termination. */ +import { parentPort, workerData } from 'node:worker_threads' +import { convertExcel } from '../../src/client/excel/convert.ts' +import type { ExcelLimits, ExcelPreview } from '../../src/client/excel/model.ts' + +if (parentPort === null) throw new Error('The Excel fuzz worker requires a parent port') +const port = parentPort +const options = workerData as { source?: string } +const baseline = options.source === undefined ? undefined : await import(options.source) as { + convertXlsx: (bytes: Uint8Array, limits: ExcelLimits) => Promise +} +port.on('message', (bytes: Uint8Array) => { void parseWorkbook(bytes) }) + +async function parseWorkbook(bytes: Uint8Array): Promise { + const before = bytes.slice() + try { + const limits = { maxBytes: 20_000_000, maxCells: 1_000_000, timeoutMs: 10_000 } + const preview = baseline === undefined ? await convertExcel(bytes, 'xlsx', limits) : await baseline.convertXlsx(bytes, limits) + port.postMessage({ ok: true, preview, inputUnchanged: before.every((value, index) => value === bytes[index]) }) + } catch (error) { + const causes: string[] = [] + let current: unknown = error + while (current instanceof Error && causes.length < 8) { + causes.push(`${current.name}: ${current.message}`) + current = current.cause + } + port.postMessage({ ok: false, causes, inputUnchanged: before.every((value, index) => value === bytes[index]) }) + } +} diff --git a/packages/client/ui-sidebar-documentpreview/tests/fuzz/generate.py b/packages/client/ui-sidebar-documentpreview/tests/fuzz/generate.py new file mode 100644 index 0000000000..a9141ac552 --- /dev/null +++ b/packages/client/ui-sidebar-documentpreview/tests/fuzz/generate.py @@ -0,0 +1,351 @@ +"""Generate replayable XLSX cases using independent writers and equivalent ZIP/XML encodings.""" + +import argparse +import base64 +import copy +from datetime import datetime, time, timedelta +import io +import json +import math +from pathlib import Path +import posixpath +import random +import re +import warnings +import zipfile +from xml.etree import ElementTree as ET + +import openpyxl +from openpyxl.chart import BarChart, Reference +from openpyxl.comments import Comment +from openpyxl.drawing.image import Image +from openpyxl.formatting.rule import ColorScaleRule, DataBarRule, IconSetRule, FormulaRule +from openpyxl.styles import Font, PatternFill +from openpyxl.utils.datetime import CALENDAR_MAC_1904, to_excel +from openpyxl.worksheet.datavalidation import DataValidation +from openpyxl.worksheet.table import Table, TableStyleInfo +import xlsxwriter + +FEATURES = ['chart', 'image', 'comment', 'conditional', 'conditional-databar', 'conditional-iconset', 'conditional-expression', 'table', 'validation', 'hyperlink', + 'merge', 'freeze', 'hidden', 'header', 'epoch1904', 'styled'] +ERRORS = ['#NULL!', '#DIV/0!', '#VALUE!', '#REF!', '#NAME?', '#NUM!', '#N/A', + '#SPILL!', '#CALC!', '#GETTING_DATA'] +PNG = base64.b64decode('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=') +MAIN_NS = 'http://schemas.openxmlformats.org/spreadsheetml/2006/main' + + +def fixed_zip(files, compression=zipfile.ZIP_DEFLATED, reverse=False, comment=b''): + """Fix ZIP metadata so the same seed yields byte-identical files.""" + output = io.BytesIO() + with zipfile.ZipFile(output, 'w', compression=compression) as archive: + for name in sorted(files, reverse=reverse): + entry = zipfile.ZipInfo(name, date_time=(2020, 1, 1, 0, 0, 0)) + entry.compress_type = compression + content = files[name] + if name == 'docProps/core.xml': + # Openpyxl overwrites the modified time during save_workbook. + content = re.sub(rb'(]*>)[^<]*()', rb'\g<1>2020-01-01T00:00:00Z\g<2>', content) + archive.writestr(entry, content) + archive.comment = comment + return output.getvalue() + + +def unpack(data): + with zipfile.ZipFile(io.BytesIO(data)) as archive: + return {name: archive.read(name) for name in archive.namelist()} + + +def validate(data, cells): + """Check internal relationship targets and independently reload all oracle cells.""" + files = unpack(data) + for name, content in files.items(): + if name.endswith('.rels'): + folder = '' if name == '_rels/.rels' else name.split('/_rels/')[0] + for rel in ET.fromstring(content): + if rel.get('TargetMode') == 'External': + continue + target = rel.attrib['Target'] + target = posixpath.normpath(target.lstrip('/') if target.startswith('/') else posixpath.join(folder, target)) + if target not in files: + raise ValueError(f'Missing relationship target {name}: {target}') + with warnings.catch_warnings(): + warnings.simplefilter('ignore', UserWarning) + workbook = openpyxl.load_workbook(io.BytesIO(data), data_only=False) + for cell in cells: + actual = workbook[cell['sheet']].cell(cell['r'] + 1, cell['c'] + 1).value + expected = cell.get('formula', cell.get('source', cell.get('value'))) + if isinstance(expected, dict): + continue + equivalent_number = type(actual) in (int, float) and type(expected) in (int, float) and math.isclose(actual, expected, rel_tol=1e-12, abs_tol=1e-12) + if actual != expected and not equivalent_number: + raise ValueError(f'Writer changed {cell}: {actual!r}') + workbook.close() + + +def workbook_bytes(writer, features, values, case_seed): + """Keep expected values independent of the preview implementation.""" + output = io.BytesIO() + cells = [] + active = set(features) + if writer == 'openpyxl': + book = openpyxl.Workbook() + book.properties.created = book.properties.modified = datetime(2020, 1, 1) + if 'epoch1904' in active: + book.epoch = CALENDAR_MAC_1904 + sheet = book.active + sheet.title = '数据' + else: + book = xlsxwriter.Workbook(output, {'in_memory': True, 'date_1904': 'epoch1904' in active}) + book.set_properties({'created': datetime(2020, 1, 1)}) + sheet = book.add_worksheet('数据') + + for r, c, value, kind in values: + oracle = {'sheet': '数据', 'r': r, 'c': c} + if kind == 'formula': + formula, cached = value + oracle['formula'] = formula + oracle['value'] = None if writer == 'openpyxl' else cached + if writer == 'openpyxl': + sheet.cell(r + 1, c + 1, formula) + else: + sheet.write_formula(r, c, formula, None, cached) + elif kind == 'date': + oracle['source'] = {'iso': value.isoformat()} + oracle['value'] = to_excel(value) + if writer == 'openpyxl': + sheet.cell(r + 1, c + 1, value).number_format = 'yyyy-mm-dd hh:mm:ss' + else: + sheet.write_datetime(r, c, value, book.add_format({'num_format': 'yyyy-mm-dd hh:mm:ss'})) + elif kind == 'time': + oracle['source'] = {'iso': str(value)} + oracle['value'] = to_excel(value) + if writer == 'openpyxl': + sheet.cell(r + 1, c + 1, value).number_format = '[h]:mm:ss' if isinstance(value, timedelta) else 'hh:mm:ss' + else: + sheet.write_datetime(r, c, value, book.add_format({'num_format': '[h]:mm:ss'})) + elif kind == 'error': + oracle['value'] = value + if writer == 'openpyxl': + cell = sheet.cell(r + 1, c + 1, value) + cell.data_type = 'e' + else: + # XlsxWriter exposes Excel error caches through its formula writer. + sheet.write_formula(r, c, '=1/0', None, value) + oracle['formula'] = '=1/0' + else: + oracle['value'] = value + if writer == 'openpyxl': + sheet.cell(r + 1, c + 1, value) + elif isinstance(value, str): + sheet.write_string(r, c, value) + else: + sheet.write(r, c, value) + cells.append(oracle) + + if writer == 'openpyxl': + if 'chart' in active: + chart = BarChart() + chart.add_data(Reference(sheet, min_col=2, min_row=1, max_row=3), titles_from_data=True) + sheet.add_chart(chart, 'H2') + if 'image' in active: + sheet.add_image(Image(io.BytesIO(PNG)), 'H18') + if 'comment' in active: + sheet['B2'].comment = Comment('生成的批注', 'fuzz') + if 'conditional' in active: + sheet.conditional_formatting.add('B2:B3', ColorScaleRule(start_type='min', start_color='FF0000', end_type='max', end_color='00FF00')) + if 'conditional-databar' in active: + sheet.conditional_formatting.add('B2:B3', DataBarRule(start_type='min', end_type='max', color='FF336699')) + if 'conditional-iconset' in active: + sheet.conditional_formatting.add('B2:B3', IconSetRule('3TrafficLights1', 'percent', [0, 33, 67])) + if 'conditional-expression' in active: + sheet.conditional_formatting.add('B2:B3', FormulaRule(formula=['B2>20'], font=Font(bold=True))) + if 'table' in active: + table = Table(displayName='DataTable', ref='A1:B3') + table.tableStyleInfo = TableStyleInfo(name='TableStyleMedium2', showRowStripes=True) + sheet.add_table(table) + if 'validation' in active: + validation = DataValidation(type='list', formula1='"A,B,C"') + sheet.add_data_validation(validation) + validation.add('F1:F3') + if 'hyperlink' in active: + sheet['A2'].hyperlink = 'https://example.com/?a=1&b=2' + if 'merge' in active: + sheet.merge_cells('H30:J30') + if 'freeze' in active: + sheet.freeze_panes = 'B2' + if 'hidden' in active: + sheet.row_dimensions[3].hidden = True + sheet.column_dimensions['B'].hidden = True + book.create_sheet('隐藏页').sheet_state = 'hidden' + if 'header' in active: + sheet.oddHeader.center.text = 'Fuzz &P' + if 'styled' in active: + sheet['B2'].font = Font(bold=True, color='FF112233') + sheet['B2'].fill = PatternFill('solid', fgColor='FFFFFF00') + book.save(output) + else: + if 'chart' in active: + chart = book.add_chart({'type': 'column'}) + chart.add_series({'values': ['数据', 1, 1, 2, 1]}) + sheet.insert_chart('H2', chart) + if 'image' in active: + sheet.insert_image('H18', 'pixel.png', {'image_data': io.BytesIO(PNG)}) + if 'comment' in active: + sheet.write_comment('B2', '生成的批注') + if 'conditional' in active: + sheet.conditional_format('B2:B3', {'type': '2_color_scale'}) + if 'conditional-databar' in active: + sheet.conditional_format('B2:B3', {'type': 'data_bar', 'data_bar_2010': True}) + if 'conditional-iconset' in active: + sheet.conditional_format('B2:B3', {'type': 'icon_set', 'icon_style': '3_traffic_lights'}) + if 'conditional-expression' in active: + sheet.conditional_format('B2:B3', {'type': 'formula', 'criteria': '=B2>20', 'format': book.add_format({'bold': True})}) + if 'textbox' in active: + sheet.insert_textbox('H32', 'Text box ') + if 'table' in active: + sheet.add_table('A1:B3', {'columns': [{'header': 'Item'}, {'header': 'Amount'}]}) + if 'validation' in active: + sheet.data_validation('F1:F3', {'validate': 'list', 'source': ['A', 'B', 'C']}) + if 'hyperlink' in active: + sheet.write_url('A2', 'https://example.com/?a=1&b=2', string='A') + if 'merge' in active: + sheet.merge_range('H30:J30', '', book.add_format()) + if 'freeze' in active: + sheet.freeze_panes(1, 1) + if 'hidden' in active: + sheet.set_row(2, None, None, {'hidden': True}) + sheet.set_column('B:B', None, None, {'hidden': True}) + book.add_worksheet('隐藏页').hide() + if 'header' in active: + sheet.set_header('&CFuzz &P') + if 'styled' in active: + sheet.write('B2', 42, book.add_format({'bold': True, 'font_color': '#112233', 'bg_color': '#FFFF00'})) + book.close() + features = [key for feature, key in [('chart', 'charts'), ('image', 'images'), ('textbox', 'shapes')] if feature in active] + if any(feature.startswith('conditional') for feature in active): + features.append('conditionalFormatting') + return fixed_zip(unpack(output.getvalue())), cells, features + + +def mutate(data, mutation): + """Change encodings or OPC names without changing worksheet cell semantics.""" + files = unpack(data) + if mutation == 'zip-store': + return fixed_zip(files, zipfile.ZIP_STORED) + if mutation == 'zip-reverse-comment': + return fixed_zip(files, reverse=True, comment=b'Excel fuzz archive comment') + if mutation == 'sheet-prefix': + path = 'xl/worksheets/sheet1.xml' + xml = files[path].decode() + xml = xml.replace(f'xmlns="{MAIN_NS}"', f'xmlns:s="{MAIN_NS}"') + files[path] = re.sub(r'<(/?)([A-Za-z_][\w.-]*)(?=[\s/>])', r'<\1s:\2', xml).encode() + if mutation == 'sheet-filename': + old, new = 'xl/worksheets/sheet1.xml', 'xl/worksheets/budget.xml' + files[new] = files.pop(old) + rel = 'xl/worksheets/_rels/sheet1.xml.rels' + if rel in files: + files['xl/worksheets/_rels/budget.xml.rels'] = files.pop(rel) + for path in ['xl/_rels/workbook.xml.rels', '[Content_Types].xml']: + files[path] = files[path].replace(b'worksheets/sheet1.xml', b'worksheets/budget.xml') + if mutation == 'relationship-dot': + path = 'xl/_rels/workbook.xml.rels' + files[path] = files[path].replace(b'Target="worksheets/', b'Target="./worksheets/').replace(b'Target="/xl/worksheets/', b'Target="/xl/./worksheets/') + if mutation == 'relationship-absolute': + path = 'xl/_rels/workbook.xml.rels' + files[path] = files[path].replace(b'Target="worksheets/', b'Target="/xl/worksheets/') + if mutation in ['drawing-default', 'drawing-alternate']: + for path in list(files): + if re.fullmatch(r'xl/drawings/[^/]+\.xml', path): + xml = files[path].decode() + match = re.search(r'xmlns(?::([\w]+))?="http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing"', xml) + if match: + old = match.group(1) + new = '' if mutation == 'drawing-default' else 'draw' + xml = xml.replace(match.group(0), f'xmlns{":" + new if new else ""}="http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing"') + if old: + xml = re.sub(r'<(/?)' + re.escape(old) + ':', r'<\1' + (new + ':' if new else ''), xml) + elif new: + xml = re.sub(r'<(/?)([A-Za-z_][\w.-]*)(?=[\s/>])', r'<\1' + new + r':\2', xml) + files[path] = xml.encode() + return fixed_zip(files) + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('output', type=Path) + parser.add_argument('--seed', type=int, default=4863) + parser.add_argument('--random-cases', type=int, default=300, help='Cases per independent writer') + args = parser.parse_args() + args.output.mkdir(parents=True, exist_ok=False) + rng = random.Random(args.seed) + manifest = {'seed': args.seed, 'writers': {'openpyxl': openpyxl.__version__, 'xlsxwriter': xlsxwriter.__version__}, 'cases': [], 'generatorErrors': []} + base_values = [(0, 0, 'Item', 'value'), (0, 1, 'Amount', 'value'), (1, 0, 'A', 'value'), + (1, 1, 42, 'value'), (2, 0, 'B', 'value'), (2, 1, 15, 'value')] + directed = [([], base_values, 'plain')] + directed += [([feature], base_values, feature) for feature in FEATURES] + directed += [(['chart', feature], base_values, 'chart-' + feature) for feature in ['comment', 'image', 'conditional']] + directed += [([], base_values + [(4, 0, error, 'error')], 'error-' + str(index)) for index, error in enumerate(ERRORS)] + directed += [([], base_values + [(4, 0, ('=1+2', value), 'formula')], 'cache-' + str(index)) for index, value in enumerate([3, 0, False, True, '', '文本', '#DIV/0!'])] + directed += [([epoch] if epoch else [], base_values + [(4, 0, value, kind)], f'temporal-{epoch}-{index}') for epoch in ['', 'epoch1904'] for index, (value, kind) in enumerate([ + (datetime(2024, 2, 29, 12, 34, 56), 'date'), (time(12, 34, 56), 'time'), (timedelta(days=2, hours=3), 'time')])] + directed += [([], base_values + [(4, 0, value, 'value')], 'text-' + str(index)) for index, value in enumerate([' & 字符', '😀\n多行\t数据', '_x0041_', '_x000D_', '00123'])] + + def emit(data, cells, expected_features, writer, features, variant, valid=True): + index = len(manifest['cases']) + path = f'{index:05d}-{writer}-{variant}.xlsx' + if valid: + validate(data, cells) + (args.output / path).write_bytes(data) + manifest['cases'].append({'file': path, 'writer': writer, 'features': sorted(set(features)), 'variant': variant, + 'valid': valid, 'cells': cells, 'unsupportedFeatures': expected_features}) + + for writer in ['openpyxl', 'xlsxwriter']: + writer_directed = directed + ([(['textbox'], base_values, 'textbox')] if writer == 'xlsxwriter' else []) + for features, values, label in writer_directed: + try: + data, cells, expected = workbook_bytes(writer, features, values, args.seed) + emit(data, cells, expected, writer, features, label) + if label in ['plain', 'chart', 'image', 'comment', 'conditional', 'chart-comment']: + for mutation in ['zip-store', 'zip-reverse-comment', 'sheet-prefix', 'sheet-filename', 'relationship-dot', 'relationship-absolute', 'drawing-default', 'drawing-alternate']: + try: + emit(mutate(data, mutation), cells, expected, writer, features, label + '--' + mutation) + except Exception as error: + manifest['generatorErrors'].append({'writer': writer, 'case': label, 'mutation': mutation, 'error': str(error)}) + except Exception as error: + manifest['generatorErrors'].append({'writer': writer, 'case': label, 'error': str(error)}) + for index in range(args.random_cases): + features = [feature for feature in FEATURES + (['textbox'] if writer == 'xlsxwriter' else []) if rng.random() < 0.3] + values = copy.deepcopy(base_values) + for row in range(5, rng.randint(6, 14)): + value = rng.choice([rng.randint(-100000, 100000), rng.random() * 100, True, False, '中文😀', 'literal', '00123']) + values.append((row, rng.randrange(4), value, 'value')) + values += [(3, 3, rng.choice(ERRORS), 'error')] + try: + data, cells, expected = workbook_bytes(writer, features, values, args.seed + index) + mutation = rng.choice(['none', 'zip-store', 'zip-reverse-comment', 'drawing-default', 'drawing-alternate']) + emit(mutate(data, mutation), cells, expected, writer, features, f'random-{index}-{mutation}') + except Exception as error: + manifest['generatorErrors'].append({'writer': writer, 'case': index, 'error': str(error)}) + + plain = next(case for case in manifest['cases'] if case['variant'] == 'plain') + source = (args.output / plain['file']).read_bytes() + for index in range(128): + data = bytearray(source) + if index < 32: + data = data[:rng.randrange(1, len(data))] + else: + for _ in range(rng.randint(1, 5)): + data[rng.randrange(len(data))] ^= rng.randint(1, 255) + try: + validate(bytes(data), plain['cells']) + valid = True + except Exception: + valid = False + emit(bytes(data), plain['cells'], [], 'mutated', [], f'bytes-{index}', valid=valid) + + (args.output / 'manifest.json').write_text(json.dumps(manifest, ensure_ascii=False, indent=2) + '\n', encoding='utf-8') + print(json.dumps({'output': str(args.output), 'cases': len(manifest['cases']), 'valid': sum(case['valid'] for case in manifest['cases']), 'generatorErrors': len(manifest['generatorErrors'])})) + + +if __name__ == '__main__': + main() diff --git a/packages/client/ui-sidebar-documentpreview/tests/fuzz/run.client.ts b/packages/client/ui-sidebar-documentpreview/tests/fuzz/run.client.ts new file mode 100644 index 0000000000..7cf04e4274 --- /dev/null +++ b/packages/client/ui-sidebar-documentpreview/tests/fuzz/run.client.ts @@ -0,0 +1,177 @@ +/** Explicit XLSX fuzz campaign with per-input worker deadlines and retained failure evidence. */ +import { readFile, writeFile, mkdir, copyFile, mkdtemp, rm } from 'node:fs/promises' +import { execFileSync } from 'node:child_process' +import { resolve, join, relative, isAbsolute } from 'node:path' +import { parseArgs } from 'node:util' +import { Worker } from 'node:worker_threads' +import { fileURLToPath, pathToFileURL } from 'node:url' +import { createHash } from 'node:crypto' +import type { ExcelPreview } from '../../src/client/excel/model.ts' + +interface OracleCell { sheet: string; r: number; c: number; value: string | number | boolean | null; formula?: string } +interface Case { + file: string + writer: string + features: string[] + variant: string + valid: boolean + cells: OracleCell[] + unsupportedFeatures: string[] +} +interface Manifest { seed: number; writers: Record; cases: Case[]; generatorErrors: unknown[] } +type Reply = ({ ok: true; preview: ExcelPreview } | { ok: false; causes: string[] }) & { inputUnchanged?: boolean } +interface Outcome { + file: string + writer: string + features: string[] + variant: string + valid: boolean + status: string + detail: string + group: string + elapsedMs: number + opened: boolean + sha256: string +} + +const { values, positionals } = parseArgs({ + allowPositionals: true, + options: { only: { type: 'string' }, 'timeout-ms': { type: 'string', default: '10000' }, report: { type: 'string', default: 'results.json' }, 'baseline-ref': { type: 'string' } }, +}) +if (positionals.length !== 1) throw new Error('Usage: pnpm exec tsx packages/client/ui-sidebar-documentpreview/tests/fuzz/run.client.ts [--only substring]') +const directory = resolve(positionals[0]!) +const deadlineMs = Number(values['timeout-ms']) +if (!Number.isSafeInteger(deadlineMs) || deadlineMs <= 0) throw new Error('timeout-ms must be a positive integer') +const manifest = JSON.parse(await readFile(join(directory, 'manifest.json'), 'utf8')) as Manifest +const cases = manifest.cases.filter(test => values.only === undefined || test.file.includes(values.only)) +if (cases.length === 0) throw new Error('No cases selected') +const head = execFileSync('git', ['rev-parse', 'HEAD'], { encoding: 'utf8' }).trim() +const artifactRoot = fileURLToPath(new URL('../../.artifacts/', import.meta.url)) +let worker: Worker | undefined +let baselineDirectory: string | undefined +let source: string | undefined +let parserRef = head +if (values['baseline-ref'] !== undefined) { + parserRef = execFileSync('git', ['rev-parse', '--verify', `${values['baseline-ref']}^{commit}`], { encoding: 'utf8' }).trim() + const sourceRoot = new URL('../../src/client/excel/', import.meta.url).href + const baseline = execFileSync('git', ['show', `${parserRef}:packages/client/ui-sidebar-documentpreview/src/client/excel/xlsx.ts`], { encoding: 'utf8' }).replaceAll("from './", `from '${sourceRoot}`) + await mkdir(artifactRoot, { recursive: true }) + baselineDirectory = await mkdtemp(join(artifactRoot, 'excel-baseline-')) + const path = join(baselineDirectory, 'xlsx.ts') + await writeFile(path, baseline) + source = pathToFileURL(path).href +} + +async function parse(bytes: Uint8Array): Promise { + // Source conversion is the subject; a dedicated worker can be terminated even during synchronous ZIP/XML work. + worker ??= new Worker(new URL('./excel-worker.client.ts', import.meta.url), { execArgv: ['--import', 'tsx/esm'], workerData: { source }, resourceLimits: { maxOldGenerationSizeMb: 256 } }) + const current = worker + return new Promise((resolveReply) => { + const cleanup = (): void => { + clearTimeout(timer) + current.off('message', message) + current.off('error', error) + current.off('exit', exit) + } + const message = (reply: Reply): void => { cleanup(); resolveReply(reply) } + const error = (cause: Error): void => { + cleanup() + worker = undefined + void current.terminate().then(() => { resolveReply({ ok: false, causes: [`WorkerError: ${cause.message}`] }) }) + } + const exit = (code: number): void => { + cleanup() + worker = undefined + resolveReply({ ok: false, causes: [`WorkerExit: ${code}`] }) + } + const timer = setTimeout(() => { + cleanup() + worker = undefined + void current.terminate().then(() => { resolveReply({ ok: false, causes: [`Timeout: ${deadlineMs}ms`] }) }) + }, deadlineMs) + current.once('message', message) + current.once('error', error) + current.once('exit', exit) + current.postMessage(bytes, [bytes.buffer]) + }) +} + +function inspect(test: Case, reply: Reply): Pick { + if (reply.inputUnchanged === false) return { status: 'mutated-source', detail: 'Conversion mutated the borrowed input bytes', group: 'mutated-source' } + if (!reply.ok) { + const detail = reply.causes.join(' <- ') + const controlled = /^ExcelPreviewError: (invalid|tooLarge|timeout|encoding)$/.test(reply.causes[0] ?? '') + const status = test.valid ? 'rejected-valid' : controlled ? 'pass' : 'unclassified-error' + const variant = test.variant.includes('sheet-prefix') ? 'sheet-prefix' : test.variant.includes('sheet-filename') ? 'sheet-filename' : test.variant.includes('relationship-dot') ? 'relationship-dot' : 'content' + return { status, detail, group: `${status}:${variant}:${reply.causes.at(-1)}` } + } + if (!test.valid) return { status: 'accepted-corrupt', detail: 'Independent reader or ZIP relationship validation rejected this input; permissive acceptance requires inspection.', group: 'accepted-corrupt' } + for (const expected of test.cells) { + const sheet = reply.preview.sheets.find(sheet => sheet.name === expected.sheet) + const cell = sheet?.celldata?.find(cell => cell.r === expected.r && cell.c === expected.c)?.v + const actual = cell?.v ?? null + const same = typeof expected.value === 'number' && typeof actual === 'number' + ? Math.abs(actual - expected.value) <= Math.max(1, Math.abs(expected.value)) * 1e-12 + : actual === expected.value + if (!same || (expected.formula !== undefined && expected.formula !== cell?.f)) { + const detail = JSON.stringify({ expected, actual: cell ?? null }) + const category = expected.formula !== undefined ? 'formula-cache' : test.variant.startsWith('temporal') ? 'temporal' : 'value' + return { status: 'value-mismatch', detail, group: `value-mismatch:${category}:${JSON.stringify(expected.value)}:${JSON.stringify(actual)}` } + } + } + if (values['baseline-ref'] !== undefined) return { status: 'pass', detail: '', group: 'pass' } + const actual = reply.preview.unsupportedFeatures + if (new Set(actual).size !== actual.length || JSON.stringify(actual) !== JSON.stringify(test.unsupportedFeatures)) { + const detail = JSON.stringify({ expected: test.unsupportedFeatures, actual }) + return { status: 'notice-mismatch', detail, group: `notice-mismatch:${detail}` } + } + return { status: 'pass', detail: '', group: 'pass' } +} + +const outcomes: Outcome[] = [] +try { + for (const test of cases) { + const bytes = new Uint8Array(await readFile(join(directory, test.file))) + const sha256 = createHash('sha256').update(bytes).digest('hex') + const start = performance.now() + const reply = await parse(bytes) + outcomes.push({ + file: test.file, writer: test.writer, features: test.features, variant: test.variant, valid: test.valid, + ...inspect(test, reply), elapsedMs: Math.round(performance.now() - start), opened: reply.ok, sha256, + }) + if (outcomes.length % 100 === 0) console.log(JSON.stringify({ completed: outcomes.length, total: cases.length, findings: outcomes.filter(item => item.status !== 'pass').length })) + } +} finally { + await worker?.terminate() + if (baselineDirectory !== undefined) { + const child = relative(artifactRoot, baselineDirectory) + if (child === '' || child.startsWith('..') || isAbsolute(child)) throw new Error('Baseline cleanup escaped its artifact directory') + await rm(baselineDirectory, { recursive: true }) + } +} + +const counts: Record = {} +const groups = new Map() +for (const outcome of outcomes) { + counts[outcome.status] = (counts[outcome.status] ?? 0) + 1 + if (outcome.status !== 'pass') groups.set(outcome.group, [...(groups.get(outcome.group) ?? []), outcome]) +} +const representatives: { group: string; count: number; example: string; detail: string }[] = [] +await mkdir(join(directory, 'repros'), { recursive: true }) +for (const [group, members] of groups) { + const sorted = [...members].sort((a, b) => a.features.length - b.features.length + || Number(a.variant.includes('random')) - Number(b.variant.includes('random')) || a.file.localeCompare(b.file)) + const first = sorted[0]! + await copyFile(join(directory, first.file), join(directory, 'repros', first.file)) + representatives.push({ group, count: members.length, example: `repros/${first.file}`, detail: first.detail }) +} +const report = { + head, parserRef, seed: manifest.seed, writers: manifest.writers, selected: cases.length, counts, + worktreeStatus: execFileSync('git', ['status', '--short'], { encoding: 'utf8' }).trim(), + validOpened: outcomes.filter(outcome => outcome.valid && outcome.opened).length, + validRejected: outcomes.filter(outcome => outcome.valid && !outcome.opened).length, + generatorErrors: manifest.generatorErrors, representatives, outcomes, +} +await writeFile(join(directory, values.report), `${JSON.stringify(report, null, 2)}\n`) +console.log(JSON.stringify({ report: join(directory, values.report), head, selected: cases.length, counts, representatives }, null, 2)) +if (outcomes.some(outcome => outcome.status !== 'pass' && outcome.status !== 'accepted-corrupt')) process.exitCode = 1 diff --git a/patches/exceljs@4.4.0.patch b/patches/exceljs@4.4.0.patch new file mode 100644 index 0000000000..87ee0151b2 --- /dev/null +++ b/patches/exceljs@4.4.0.patch @@ -0,0 +1,806 @@ +diff --git a/dist/exceljs.js b/dist/exceljs.js +index ab2c9d6e576d8069d77d787b863dfe09c7659890..99213b8606d02b8948ce6ce44a5a7dcfc203d854 100644 +--- a/dist/exceljs.js ++++ b/dist/exceljs.js +@@ -4636,24 +4636,37 @@ module.exports = async function* (iterable) { + if (iterable.pipe && !iterable[Symbol.asyncIterator]) { + iterable = iterable.pipe(new PassThrough()); + } +- const saxesParser = new SaxesParser(); ++ const saxesParser = new SaxesParser({xmlns: true}); ++ // Xforms use canonical names; OOXML producers may choose different prefixes. ++ const prefixes = new Map([ ++ ['http://schemas.openxmlformats.org/spreadsheetml/2006/main', ''], ++ ['http://purl.oclc.org/ooxml/spreadsheetml/main', ''], ++ ['http://schemas.openxmlformats.org/package/2006/relationships', ''], ++ ['http://schemas.openxmlformats.org/officeDocument/2006/relationships', 'r'], ++ ['http://purl.oclc.org/ooxml/officeDocument/relationships', 'r'], ++ ['urn:schemas-microsoft-com:vml', 'v'], ++ ['urn:schemas-microsoft-com:office:office', 'o'], ++ ['urn:schemas-microsoft-com:office:excel', 'x'], ++ ]); ++ const canonicalName = node => { ++ const prefix = prefixes.get(node.uri); ++ return prefix === undefined ? node.name : prefix ? `${prefix}:${node.local}` : node.local; ++ }; + let error; + saxesParser.on('error', err => { + error = err; + }); + let events = []; +- saxesParser.on('opentag', value => events.push({ +- eventType: 'opentag', +- value +- })); +- saxesParser.on('text', value => events.push({ +- eventType: 'text', +- value +- })); +- saxesParser.on('closetag', value => events.push({ +- eventType: 'closetag', +- value +- })); ++ saxesParser.on('opentag', node => { ++ const attributes = Object.create(null); ++ Object.values(node.attributes).forEach(attribute => { ++ attributes[canonicalName(attribute)] = attribute.value; ++ }); ++ events.push({eventType: 'opentag', value: {...node, name: canonicalName(node), attributes}}); ++ }); ++ saxesParser.on('text', value => events.push({eventType: 'text', value})); ++ saxesParser.on('cdata', value => events.push({eventType: 'text', value})); ++ saxesParser.on('closetag', node => events.push({eventType: 'closetag', value: {...node, name: canonicalName(node)}})); + for await (const chunk of iterable) { + saxesParser.write(bufferToString(chunk)); + // saxesParser.write and saxesParser.on() are synchronous, +@@ -6477,12 +6490,11 @@ class WorkbookXform extends BaseXform { + let index = 0; + (model.sheets || []).forEach(sheet => { + const rel = rels[sheet.rId]; +- if (!rel) { +- return; ++ if (!rel) throw new Error(`Missing worksheet relationship: ${sheet.rId}`); ++ worksheet = model.worksheetHash[rel.Target]; ++ if (!worksheet && rel.Type === 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet') { ++ throw new Error(`Missing worksheet: ${rel.Target}`); + } +- // if rel.Target start with `[space]/xl/` or `/xl/` , then it will be replaced with `''` and spliced behind `xl/`, +- // otherwise it will be spliced directly behind `xl/`. i.g. +- worksheet = model.worksheetHash[`xl/${rel.Target.replace(/^(\s|\/xl\/)+/, '')}`]; + // If there are "chartsheets" in the file, rel.Target will + // come out as chartsheets/sheet1.xml or similar here, and + // that won't be in model.worksheetHash. +@@ -6635,6 +6647,11 @@ utils.inherits(CommentXform, BaseXform, { + ...node.attributes + }; + return true; ++ case 't': ++ this.plainText = true; ++ this.parser = this.richTextXform.textXform; ++ this.parser.parseOpen(node); ++ return true; + case 'r': + this.parser = this.richTextXform; + this.parser.parseOpen(node); +@@ -6649,6 +6666,12 @@ utils.inherits(CommentXform, BaseXform, { + } + }, + parseClose(name) { ++ if (this.plainText && name === 't') { ++ this.model.note.texts.push({text: this.parser.model}); ++ this.parser = undefined; ++ this.plainText = false; ++ return true; ++ } + switch (name) { + case 'comment': + return false; +@@ -12386,17 +12409,17 @@ class WorkSheetXform extends BaseXform { + // options.merges.reconcile(model.mergeCells, model.rows); + const rels = (model.relationships || []).reduce((h, rel) => { + h[rel.Id] = rel; +- if (rel.Type === RelType.Comments) { +- model.comments = options.comments[rel.Target].comments; +- } +- if (rel.Type === RelType.VmlDrawing && model.comments && model.comments.length) { +- const vmlComment = options.vmlDrawings[rel.Target].comments; +- model.comments.forEach((comment, index) => { +- comment.note = Object.assign({}, comment.note, vmlComment[index]); +- }); +- } + return h; + }, {}); ++ const commentRel = Object.values(rels).find(rel => rel.Type === RelType.Comments); ++ if (commentRel) model.comments = options.comments[commentRel.Target].comments; ++ const vmlRel = Object.values(rels).find(rel => rel.Type === RelType.VmlDrawing); ++ if (vmlRel && model.comments && model.comments.length) { ++ const vmlComments = options.vmlDrawings[vmlRel.Target].comments; ++ model.comments.forEach((comment, index) => { ++ comment.note = Object.assign({}, comment.note, vmlComments[index]); ++ }); ++ } + options.commentsMap = (model.comments || []).reduce((h, comment) => { + if (comment.ref) { + h[comment.ref] = comment; +@@ -15491,9 +15514,7 @@ const ZipStream = require('../utils/zip-stream'); + const StreamBuf = require('../utils/stream-buf'); + const utils = require('../utils/utils'); + const XmlStream = require('../utils/xml-stream'); +-const { +- bufferToString +-} = require('../utils/browser-buffer-decode'); ++ + const StylesXform = require('./xform/style/styles-xform'); + const CoreXform = require('./xform/core/core-xform'); + const SharedStringsXform = require('./xform/strings/shared-strings-xform'); +@@ -15621,6 +15642,31 @@ class XLSX { + delete model.drawingRels; + delete model.vmlDrawings; + } ++ // XML processors must accept UTF-8 and both byte orders of UTF-16. ++ async _readXmlEntry(entry) { ++ const bytes = await entry.async('uint8array'); ++ const encoding = (bytes[0] === 0xff && bytes[1] === 0xfe) || (bytes[0] === 0x3c && bytes[1] === 0) ++ ? 'utf-16le' ++ : (bytes[0] === 0xfe && bytes[1] === 0xff) || (bytes[0] === 0 && bytes[1] === 0x3c) ++ ? 'utf-16be' : 'utf-8'; ++ return new TextDecoder(encoding, {fatal: true}).decode(bytes); ++ } ++ ++ // Resolve an internal OPC target against its owning part, without filesystem access. ++ _resolvePart(owner, target) { ++ const parts = target.startsWith('/') ? [] : owner.split('/').slice(0, -1); ++ for (const segment of target.split('/')) { ++ if (!segment || segment === '.') continue; ++ if (segment === '..') { ++ if (!parts.length) throw new Error(`Relationship escapes package: ${target}`); ++ parts.pop(); ++ } else { ++ parts.push(segment); ++ } ++ } ++ return parts.join('/'); ++ } ++ + async _processWorksheetEntry(stream, model, sheetNo, options, path) { + const xform = new WorksheetXform(options); + const worksheet = await xform.parseStream(stream); +@@ -15631,18 +15677,14 @@ class XLSX { + async _processCommentEntry(stream, model, name) { + const xform = new CommentsXform(); + const comments = await xform.parseStream(stream); +- model.comments[`../${name}.xml`] = comments; ++ model.comments[name] = comments; + } + async _processTableEntry(stream, model, name) { + const xform = new TableXform(); + const table = await xform.parseStream(stream); +- model.tables[`../tables/${name}.xml`] = table; +- } +- async _processWorksheetRelsEntry(stream, model, sheetNo) { +- const xform = new RelationshipsXform(); +- const relationships = await xform.parseStream(stream); +- model.worksheetRels[sheetNo] = relationships; ++ model.tables[name] = table; + } ++ + async _processMediaEntry(entry, model, filename) { + const lastDot = filename.lastIndexOf('.'); + // if we can't determine extension, ignore it +@@ -15683,7 +15725,7 @@ class XLSX { + async _processVmlDrawingEntry(entry, model, name) { + const xform = new VmlNotesXform(); + const vmlDrawing = await xform.parseStream(entry); +- model.vmlDrawings[`../drawings/${name}.vml`] = vmlDrawing; ++ model.vmlDrawings[name] = vmlDrawing; + } + async _processThemeEntry(entry, model, name) { + await new Promise((resolve, reject) => { +@@ -15727,7 +15769,7 @@ class XLSX { + const model = { + worksheets: [], + worksheetHash: {}, +- worksheetRels: [], ++ worksheetRels: Object.create(null), + themes: {}, + media: [], + mediaIndex: {}, +@@ -15738,6 +15780,49 @@ class XLSX { + vmlDrawings: {} + }; + const zip = await JSZip.loadAsync(buffer); ++ const partKey = path => path.replace(/[A-Z]/g, character => character.toLowerCase()); ++ const partNames = new Map(); ++ for (const entry of Object.values(zip.files)) { ++ if (entry.dir) continue; ++ const key = partKey(entry.name); ++ if (partNames.has(key)) throw new Error(`Ambiguous workbook part: ${entry.name}`); ++ partNames.set(key, entry.name); ++ } ++ const partTypes = new Map(); ++ const relationships = new Map(); ++ const resolvedTypes = new Set([ ++ XLSX.RelType.OfficeDocument, XLSX.RelType.Styles, XLSX.RelType.SharedStrings, ++ XLSX.RelType.Worksheet, XLSX.RelType.Comments, XLSX.RelType.Table, XLSX.RelType.VmlDrawing, ++ ]); ++ // Relationship order and ZIP entry order do not determine part identity. ++ for (const entry of Object.values(zip.files)) { ++ const match = entry.name.match(/^(.*\/)?_rels\/([^/]+)\.rels$/i); ++ if (entry.dir || (!match && partKey(entry.name) !== '_rels/.rels')) continue; ++ const owner = match ? `${match[1] || ''}${match[2]}` : ''; ++ const rels = await this.parseRels([await this._readXmlEntry(entry)]); ++ if (!rels) throw new Error(`Invalid relationships: ${entry.name}`); ++ for (const rel of rels) { ++ rel.Type = rel.Type.replace(/^http:\/\/purl\.oclc\.org\/ooxml\/officeDocument\/relationships\//, ++ 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/'); ++ if (!resolvedTypes.has(rel.Type)) continue; ++ if (rel.TargetMode === 'External') throw new Error(`External workbook part: ${rel.Target}`); ++ const target = this._resolvePart(owner, rel.Target); ++ rel.Target = partNames.get(partKey(target)); ++ if (!rel.Target) throw new Error(`Missing workbook part: ${target}`); ++ const type = partTypes.get(rel.Target); ++ if (type && type !== rel.Type) throw new Error(`Conflicting workbook part: ${rel.Target}`); ++ partTypes.set(rel.Target, rel.Type); ++ } ++ relationships.set(partKey(owner), rels); ++ } ++ model.globalRels = relationships.get('') || []; ++ const officeDocuments = model.globalRels.filter(rel => rel.Type === XLSX.RelType.OfficeDocument); ++ if (officeDocuments.length !== 1) throw new Error('Expected one workbook relationship'); ++ model.workbookRels = relationships.get(partKey(officeDocuments[0].Target)); ++ if (!model.workbookRels) throw new Error('Missing workbook relationships'); ++ for (const [path, type] of partTypes) { ++ if (type === XLSX.RelType.Worksheet) model.worksheetRels[path] = relationships.get(partKey(path)); ++ } + for (const entry of Object.values(zip.files)) { + /* eslint-disable no-await-in-loop */ + if (!entry.dir) { +@@ -15745,10 +15830,9 @@ class XLSX { + if (entryName[0] === '/') { + entryName = entryName.substr(1); + } ++ if (!partTypes.has(entryName) && !/\.(xml|rels|vml)$/i.test(entryName) && !entryName.match(/xl\/media\//)) continue; + let stream; +- if (entryName.match(/xl\/media\//) || +- // themes are not parsed as stream +- entryName.match(/xl\/theme\/([a-zA-Z0-9]+)[.]xml/)) { ++ if (entryName.match(/xl\/media\//)) { + stream = new PassThrough(); + stream.write(await entry.async('nodebuffer')); + } else { +@@ -15757,46 +15841,48 @@ class XLSX { + writableObjectMode: true, + readableObjectMode: true + }); +- let content; +- // https://www.npmjs.com/package/process +- if (process.browser) { +- // running in browser, use TextDecoder if possible +- content = bufferToString(await entry.async('nodebuffer')); +- } else { +- // running in node.js +- content = await entry.async('string'); +- } ++ const content = await this._readXmlEntry(entry); + const chunkSize = 16 * 1024; + for (let i = 0; i < content.length; i += chunkSize) { + stream.write(content.substring(i, i + chunkSize)); + } + } + stream.end(); +- switch (entryName) { +- case '_rels/.rels': +- model.globalRels = await this.parseRels(stream); +- break; +- case 'xl/workbook.xml': +- { +- const workbook = await this.parseWorkbook(stream); +- model.sheets = workbook.sheets; +- model.definedNames = workbook.definedNames; +- model.views = workbook.views; +- model.properties = workbook.properties; +- model.calcProperties = workbook.calcProperties; +- break; +- } +- case 'xl/_rels/workbook.xml.rels': +- model.workbookRels = await this.parseRels(stream); +- break; +- case 'xl/sharedStrings.xml': ++ switch (partTypes.get(entryName)) { ++ case XLSX.RelType.OfficeDocument: { ++ const workbook = await this.parseWorkbook(stream); ++ model.sheets = workbook.sheets; ++ model.definedNames = workbook.definedNames; ++ model.views = workbook.views; ++ model.properties = workbook.properties; ++ model.calcProperties = workbook.calcProperties; ++ continue; ++ } ++ case XLSX.RelType.SharedStrings: + model.sharedStrings = new SharedStringsXform(); + await model.sharedStrings.parseStream(stream); +- break; +- case 'xl/styles.xml': ++ continue; ++ case XLSX.RelType.Styles: + model.styles = new StylesXform(); + await model.styles.parseStream(stream); ++ continue; ++ case XLSX.RelType.Worksheet: ++ await this._processWorksheetEntry(stream, model, entryName, options, entryName); ++ continue; ++ case XLSX.RelType.Comments: ++ await this._processCommentEntry(stream, model, entryName); ++ continue; ++ case XLSX.RelType.Table: ++ await this._processTableEntry(stream, model, entryName); ++ continue; ++ case XLSX.RelType.VmlDrawing: ++ await this._processVmlDrawingEntry(stream, model, entryName); ++ continue; ++ default: + break; ++ } ++ switch (entryName) { ++ + case 'docProps/app.xml': + { + const appXform = new AppXform(); +@@ -15814,17 +15900,7 @@ class XLSX { + } + default: + { +- let match = entryName.match(/xl\/worksheets\/sheet(\d+)[.]xml/); +- if (match) { +- await this._processWorksheetEntry(stream, model, match[1], options, entryName); +- break; +- } +- match = entryName.match(/xl\/worksheets\/_rels\/sheet(\d+)[.]xml.rels/); +- if (match) { +- await this._processWorksheetRelsEntry(stream, model, match[1]); +- break; +- } +- match = entryName.match(/xl\/theme\/([a-zA-Z0-9]+)[.]xml/); ++ let match = entryName.match(/xl\/theme\/([a-zA-Z0-9]+)[.]xml/); + if (match) { + await this._processThemeEntry(stream, model, match[1]); + break; +@@ -15839,26 +15915,14 @@ class XLSX { + await this._processDrawingEntry(stream, model, match[1]); + break; + } +- match = entryName.match(/xl\/(comments\d+)[.]xml/); +- if (match) { +- await this._processCommentEntry(stream, model, match[1]); +- break; +- } +- match = entryName.match(/xl\/tables\/(table\d+)[.]xml/); +- if (match) { +- await this._processTableEntry(stream, model, match[1]); +- break; +- } ++ ++ + match = entryName.match(/xl\/drawings\/_rels\/([a-zA-Z0-9]+)[.]xml[.]rels/); + if (match) { + await this._processDrawingRelsEntry(stream, model, match[1]); + break; + } +- match = entryName.match(/xl\/drawings\/(vmlDrawing\d+)[.]vml/); +- if (match) { +- await this._processVmlDrawingEntry(stream, model, match[1]); +- break; +- } ++ + } + } + } +diff --git a/lib/utils/parse-sax.js b/lib/utils/parse-sax.js +index 14c682a731b5e51f999859a03ce4dd4e0bfcbb26..65c0f2b7ddd5c4e0c3a283f74c37a2fd22728aad 100644 +--- a/lib/utils/parse-sax.js ++++ b/lib/utils/parse-sax.js +@@ -8,15 +8,37 @@ module.exports = async function* (iterable) { + if (iterable.pipe && !iterable[Symbol.asyncIterator]) { + iterable = iterable.pipe(new PassThrough()); + } +- const saxesParser = new SaxesParser(); ++ const saxesParser = new SaxesParser({xmlns: true}); ++ // Xforms use canonical names; OOXML producers may choose different prefixes. ++ const prefixes = new Map([ ++ ['http://schemas.openxmlformats.org/spreadsheetml/2006/main', ''], ++ ['http://purl.oclc.org/ooxml/spreadsheetml/main', ''], ++ ['http://schemas.openxmlformats.org/package/2006/relationships', ''], ++ ['http://schemas.openxmlformats.org/officeDocument/2006/relationships', 'r'], ++ ['http://purl.oclc.org/ooxml/officeDocument/relationships', 'r'], ++ ['urn:schemas-microsoft-com:vml', 'v'], ++ ['urn:schemas-microsoft-com:office:office', 'o'], ++ ['urn:schemas-microsoft-com:office:excel', 'x'], ++ ]); ++ const canonicalName = node => { ++ const prefix = prefixes.get(node.uri); ++ return prefix === undefined ? node.name : prefix ? `${prefix}:${node.local}` : node.local; ++ }; + let error; + saxesParser.on('error', err => { + error = err; + }); + let events = []; +- saxesParser.on('opentag', value => events.push({eventType: 'opentag', value})); ++ saxesParser.on('opentag', node => { ++ const attributes = Object.create(null); ++ Object.values(node.attributes).forEach(attribute => { ++ attributes[canonicalName(attribute)] = attribute.value; ++ }); ++ events.push({eventType: 'opentag', value: {...node, name: canonicalName(node), attributes}}); ++ }); + saxesParser.on('text', value => events.push({eventType: 'text', value})); +- saxesParser.on('closetag', value => events.push({eventType: 'closetag', value})); ++ saxesParser.on('cdata', value => events.push({eventType: 'text', value})); ++ saxesParser.on('closetag', node => events.push({eventType: 'closetag', value: {...node, name: canonicalName(node)}})); + for await (const chunk of iterable) { + saxesParser.write(bufferToString(chunk)); + // saxesParser.write and saxesParser.on() are synchronous, +diff --git a/lib/xlsx/xform/book/workbook-xform.js b/lib/xlsx/xform/book/workbook-xform.js +index 5c10a5857eba8d3fbf9d3841ff15b39aefde8862..c6c1dcd6fe739b37db48ae30d1b039d635e14aa5 100644 +--- a/lib/xlsx/xform/book/workbook-xform.js ++++ b/lib/xlsx/xform/book/workbook-xform.js +@@ -165,12 +165,11 @@ class WorkbookXform extends BaseXform { + + (model.sheets || []).forEach(sheet => { + const rel = rels[sheet.rId]; +- if (!rel) { +- return; ++ if (!rel) throw new Error(`Missing worksheet relationship: ${sheet.rId}`); ++ worksheet = model.worksheetHash[rel.Target]; ++ if (!worksheet && rel.Type === 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet') { ++ throw new Error(`Missing worksheet: ${rel.Target}`); + } +- // if rel.Target start with `[space]/xl/` or `/xl/` , then it will be replaced with `''` and spliced behind `xl/`, +- // otherwise it will be spliced directly behind `xl/`. i.g. +- worksheet = model.worksheetHash[`xl/${rel.Target.replace(/^(\s|\/xl\/)+/, '')}`]; + // If there are "chartsheets" in the file, rel.Target will + // come out as chartsheets/sheet1.xml or similar here, and + // that won't be in model.worksheetHash. +diff --git a/lib/xlsx/xform/comment/comment-xform.js b/lib/xlsx/xform/comment/comment-xform.js +index 16363bfea8d0903ac66c77606c4362ef3fcd72bb..dc0df108c5433c5447a37ecd163883f5fe24cf32 100644 +--- a/lib/xlsx/xform/comment/comment-xform.js ++++ b/lib/xlsx/xform/comment/comment-xform.js +@@ -74,6 +74,11 @@ utils.inherits(CommentXform, BaseXform, { + ...node.attributes, + }; + return true; ++ case 't': ++ this.plainText = true; ++ this.parser = this.richTextXform.textXform; ++ this.parser.parseOpen(node); ++ return true; + case 'r': + this.parser = this.richTextXform; + this.parser.parseOpen(node); +@@ -88,6 +93,12 @@ utils.inherits(CommentXform, BaseXform, { + } + }, + parseClose(name) { ++ if (this.plainText && name === 't') { ++ this.model.note.texts.push({text: this.parser.model}); ++ this.parser = undefined; ++ this.plainText = false; ++ return true; ++ } + switch (name) { + case 'comment': + return false; +diff --git a/lib/xlsx/xform/sheet/worksheet-xform.js b/lib/xlsx/xform/sheet/worksheet-xform.js +index b38930042cbb05dccd01c46a9adacb7a9fc59dba..e0b239143b4e80ecb0c2030c3bb7b48a803ebef8 100644 +--- a/lib/xlsx/xform/sheet/worksheet-xform.js ++++ b/lib/xlsx/xform/sheet/worksheet-xform.js +@@ -449,17 +449,17 @@ class WorkSheetXform extends BaseXform { + // options.merges.reconcile(model.mergeCells, model.rows); + const rels = (model.relationships || []).reduce((h, rel) => { + h[rel.Id] = rel; +- if (rel.Type === RelType.Comments) { +- model.comments = options.comments[rel.Target].comments; +- } +- if (rel.Type === RelType.VmlDrawing && model.comments && model.comments.length) { +- const vmlComment = options.vmlDrawings[rel.Target].comments; +- model.comments.forEach((comment, index) => { +- comment.note = Object.assign({}, comment.note, vmlComment[index]); +- }); +- } + return h; + }, {}); ++ const commentRel = Object.values(rels).find(rel => rel.Type === RelType.Comments); ++ if (commentRel) model.comments = options.comments[commentRel.Target].comments; ++ const vmlRel = Object.values(rels).find(rel => rel.Type === RelType.VmlDrawing); ++ if (vmlRel && model.comments && model.comments.length) { ++ const vmlComments = options.vmlDrawings[vmlRel.Target].comments; ++ model.comments.forEach((comment, index) => { ++ comment.note = Object.assign({}, comment.note, vmlComments[index]); ++ }); ++ } + options.commentsMap = (model.comments || []).reduce((h, comment) => { + if (comment.ref) { + h[comment.ref] = comment; +diff --git a/lib/xlsx/xlsx.js b/lib/xlsx/xlsx.js +index ff2d9a117d78cacf727564f74770e1e8f19d0fa1..179d1dac2ed02bfc4b81f85afe7abd9822ef1a1d 100644 +--- a/lib/xlsx/xlsx.js ++++ b/lib/xlsx/xlsx.js +@@ -6,7 +6,7 @@ const StreamBuf = require('../utils/stream-buf'); + + const utils = require('../utils/utils'); + const XmlStream = require('../utils/xml-stream'); +-const {bufferToString} = require('../utils/browser-buffer-decode'); ++ + + const StylesXform = require('./xform/style/styles-xform'); + +@@ -146,6 +146,31 @@ class XLSX { + delete model.vmlDrawings; + } + ++ // XML processors must accept UTF-8 and both byte orders of UTF-16. ++ async _readXmlEntry(entry) { ++ const bytes = await entry.async('uint8array'); ++ const encoding = (bytes[0] === 0xff && bytes[1] === 0xfe) || (bytes[0] === 0x3c && bytes[1] === 0) ++ ? 'utf-16le' ++ : (bytes[0] === 0xfe && bytes[1] === 0xff) || (bytes[0] === 0 && bytes[1] === 0x3c) ++ ? 'utf-16be' : 'utf-8'; ++ return new TextDecoder(encoding, {fatal: true}).decode(bytes); ++ } ++ ++ // Resolve an internal OPC target against its owning part, without filesystem access. ++ _resolvePart(owner, target) { ++ const parts = target.startsWith('/') ? [] : owner.split('/').slice(0, -1); ++ for (const segment of target.split('/')) { ++ if (!segment || segment === '.') continue; ++ if (segment === '..') { ++ if (!parts.length) throw new Error(`Relationship escapes package: ${target}`); ++ parts.pop(); ++ } else { ++ parts.push(segment); ++ } ++ } ++ return parts.join('/'); ++ } ++ + async _processWorksheetEntry(stream, model, sheetNo, options, path) { + const xform = new WorksheetXform(options); + const worksheet = await xform.parseStream(stream); +@@ -157,19 +182,13 @@ class XLSX { + async _processCommentEntry(stream, model, name) { + const xform = new CommentsXform(); + const comments = await xform.parseStream(stream); +- model.comments[`../${name}.xml`] = comments; ++ model.comments[name] = comments; + } + + async _processTableEntry(stream, model, name) { + const xform = new TableXform(); + const table = await xform.parseStream(stream); +- model.tables[`../tables/${name}.xml`] = table; +- } +- +- async _processWorksheetRelsEntry(stream, model, sheetNo) { +- const xform = new RelationshipsXform(); +- const relationships = await xform.parseStream(stream); +- model.worksheetRels[sheetNo] = relationships; ++ model.tables[name] = table; + } + + async _processMediaEntry(entry, model, filename) { +@@ -215,7 +234,7 @@ class XLSX { + async _processVmlDrawingEntry(entry, model, name) { + const xform = new VmlNotesXform(); + const vmlDrawing = await xform.parseStream(entry); +- model.vmlDrawings[`../drawings/${name}.vml`] = vmlDrawing; ++ model.vmlDrawings[name] = vmlDrawing; + } + + async _processThemeEntry(entry, model, name) { +@@ -265,7 +284,7 @@ class XLSX { + const model = { + worksheets: [], + worksheetHash: {}, +- worksheetRels: [], ++ worksheetRels: Object.create(null), + themes: {}, + media: [], + mediaIndex: {}, +@@ -277,6 +296,49 @@ class XLSX { + }; + + const zip = await JSZip.loadAsync(buffer); ++ const partKey = path => path.replace(/[A-Z]/g, character => character.toLowerCase()); ++ const partNames = new Map(); ++ for (const entry of Object.values(zip.files)) { ++ if (entry.dir) continue; ++ const key = partKey(entry.name); ++ if (partNames.has(key)) throw new Error(`Ambiguous workbook part: ${entry.name}`); ++ partNames.set(key, entry.name); ++ } ++ const partTypes = new Map(); ++ const relationships = new Map(); ++ const resolvedTypes = new Set([ ++ XLSX.RelType.OfficeDocument, XLSX.RelType.Styles, XLSX.RelType.SharedStrings, ++ XLSX.RelType.Worksheet, XLSX.RelType.Comments, XLSX.RelType.Table, XLSX.RelType.VmlDrawing, ++ ]); ++ // Relationship order and ZIP entry order do not determine part identity. ++ for (const entry of Object.values(zip.files)) { ++ const match = entry.name.match(/^(.*\/)?_rels\/([^/]+)\.rels$/i); ++ if (entry.dir || (!match && partKey(entry.name) !== '_rels/.rels')) continue; ++ const owner = match ? `${match[1] || ''}${match[2]}` : ''; ++ const rels = await this.parseRels([await this._readXmlEntry(entry)]); ++ if (!rels) throw new Error(`Invalid relationships: ${entry.name}`); ++ for (const rel of rels) { ++ rel.Type = rel.Type.replace(/^http:\/\/purl\.oclc\.org\/ooxml\/officeDocument\/relationships\//, ++ 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/'); ++ if (!resolvedTypes.has(rel.Type)) continue; ++ if (rel.TargetMode === 'External') throw new Error(`External workbook part: ${rel.Target}`); ++ const target = this._resolvePart(owner, rel.Target); ++ rel.Target = partNames.get(partKey(target)); ++ if (!rel.Target) throw new Error(`Missing workbook part: ${target}`); ++ const type = partTypes.get(rel.Target); ++ if (type && type !== rel.Type) throw new Error(`Conflicting workbook part: ${rel.Target}`); ++ partTypes.set(rel.Target, rel.Type); ++ } ++ relationships.set(partKey(owner), rels); ++ } ++ model.globalRels = relationships.get('') || []; ++ const officeDocuments = model.globalRels.filter(rel => rel.Type === XLSX.RelType.OfficeDocument); ++ if (officeDocuments.length !== 1) throw new Error('Expected one workbook relationship'); ++ model.workbookRels = relationships.get(partKey(officeDocuments[0].Target)); ++ if (!model.workbookRels) throw new Error('Missing workbook relationships'); ++ for (const [path, type] of partTypes) { ++ if (type === XLSX.RelType.Worksheet) model.worksheetRels[path] = relationships.get(partKey(path)); ++ } + for (const entry of Object.values(zip.files)) { + /* eslint-disable no-await-in-loop */ + if (!entry.dir) { +@@ -284,12 +346,9 @@ class XLSX { + if (entryName[0] === '/') { + entryName = entryName.substr(1); + } ++ if (!partTypes.has(entryName) && !/\.(xml|rels|vml)$/i.test(entryName) && !entryName.match(/xl\/media\//)) continue; + let stream; +- if ( +- entryName.match(/xl\/media\//) || +- // themes are not parsed as stream +- entryName.match(/xl\/theme\/([a-zA-Z0-9]+)[.]xml/) +- ) { ++ if (entryName.match(/xl\/media\//)) { + stream = new PassThrough(); + stream.write(await entry.async('nodebuffer')); + } else { +@@ -298,50 +357,47 @@ class XLSX { + writableObjectMode: true, + readableObjectMode: true, + }); +- let content; +- // https://www.npmjs.com/package/process +- if (process.browser) { +- // running in browser, use TextDecoder if possible +- content = bufferToString(await entry.async('nodebuffer')); +- } else { +- // running in node.js +- content = await entry.async('string'); +- } ++ const content = await this._readXmlEntry(entry); + const chunkSize = 16 * 1024; + for (let i = 0; i < content.length; i += chunkSize) { + stream.write(content.substring(i, i + chunkSize)); + } + } + stream.end(); +- switch (entryName) { +- case '_rels/.rels': +- model.globalRels = await this.parseRels(stream); +- break; +- +- case 'xl/workbook.xml': { ++ switch (partTypes.get(entryName)) { ++ case XLSX.RelType.OfficeDocument: { + const workbook = await this.parseWorkbook(stream); + model.sheets = workbook.sheets; + model.definedNames = workbook.definedNames; + model.views = workbook.views; + model.properties = workbook.properties; + model.calcProperties = workbook.calcProperties; +- break; ++ continue; + } +- +- case 'xl/_rels/workbook.xml.rels': +- model.workbookRels = await this.parseRels(stream); +- break; +- +- case 'xl/sharedStrings.xml': ++ case XLSX.RelType.SharedStrings: + model.sharedStrings = new SharedStringsXform(); + await model.sharedStrings.parseStream(stream); +- break; +- +- case 'xl/styles.xml': ++ continue; ++ case XLSX.RelType.Styles: + model.styles = new StylesXform(); + await model.styles.parseStream(stream); ++ continue; ++ case XLSX.RelType.Worksheet: ++ await this._processWorksheetEntry(stream, model, entryName, options, entryName); ++ continue; ++ case XLSX.RelType.Comments: ++ await this._processCommentEntry(stream, model, entryName); ++ continue; ++ case XLSX.RelType.Table: ++ await this._processTableEntry(stream, model, entryName); ++ continue; ++ case XLSX.RelType.VmlDrawing: ++ await this._processVmlDrawingEntry(stream, model, entryName); ++ continue; ++ default: + break; +- ++ } ++ switch (entryName) { + case 'docProps/app.xml': { + const appXform = new AppXform(); + const appProperties = await appXform.parseStream(stream); +@@ -358,17 +414,7 @@ class XLSX { + } + + default: { +- let match = entryName.match(/xl\/worksheets\/sheet(\d+)[.]xml/); +- if (match) { +- await this._processWorksheetEntry(stream, model, match[1], options, entryName); +- break; +- } +- match = entryName.match(/xl\/worksheets\/_rels\/sheet(\d+)[.]xml.rels/); +- if (match) { +- await this._processWorksheetRelsEntry(stream, model, match[1]); +- break; +- } +- match = entryName.match(/xl\/theme\/([a-zA-Z0-9]+)[.]xml/); ++ let match = entryName.match(/xl\/theme\/([a-zA-Z0-9]+)[.]xml/); + if (match) { + await this._processThemeEntry(stream, model, match[1]); + break; +@@ -383,26 +429,11 @@ class XLSX { + await this._processDrawingEntry(stream, model, match[1]); + break; + } +- match = entryName.match(/xl\/(comments\d+)[.]xml/); +- if (match) { +- await this._processCommentEntry(stream, model, match[1]); +- break; +- } +- match = entryName.match(/xl\/tables\/(table\d+)[.]xml/); +- if (match) { +- await this._processTableEntry(stream, model, match[1]); +- break; +- } + match = entryName.match(/xl\/drawings\/_rels\/([a-zA-Z0-9]+)[.]xml[.]rels/); + if (match) { + await this._processDrawingRelsEntry(stream, model, match[1]); + break; + } +- match = entryName.match(/xl\/drawings\/(vmlDrawing\d+)[.]vml/); +- if (match) { +- await this._processVmlDrawingEntry(stream, model, match[1]); +- break; +- } + } + } + } +diff --git a/package.json b/package.json +index 7a70a5e13145a917b57806a6998b8d5e04f47acd..8a1c0a87b0140412517ab7a0fa871afdfbe22b6c 100644 +--- a/package.json ++++ b/package.json +@@ -16,7 +16,7 @@ + "node": ">=8.3.0" + }, + "main": "./excel.js", +- "browser": "./dist/exceljs.min.js", ++ "browser": "./dist/exceljs.js", + "types": "./index.d.ts", + "files": [ + "dist", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 37a01073fe..0e50c53e52 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -15,6 +15,7 @@ patchedDependencies: '@fortune-sheet/core@1.0.4': 488dad2a7648b7d4df31f6bd776b7849fd0fb85be8f1acf268efff758caba3c0 '@fortune-sheet/react@1.0.4': c17549e117c8fb99f408497c1e84292c21f25516fb762a32518f91b4d9ab0f04 '@yao-pkg/pkg@6.21.0': 75891fc22b277c145cafeab83e41baf4a70f5b8fe6dc0801c6a0b922d7ee88c7 + exceljs@4.4.0: c1bf8ac8f319dab382f08e3a669b715e691d46c703ac5a4163eb383fbedd1d48 node-pty@1.2.0-beta.15: b40ae545608897914bd25fb009c97eeac478c34e8a910298ddcb01b746534bb0 importers: @@ -5040,7 +5041,7 @@ importers: version: 3.4.11 exceljs: specifier: 4.4.0 - version: 4.4.0 + version: 4.4.0(patch_hash=c1bf8ac8f319dab382f08e3a669b715e691d46c703ac5a4163eb383fbedd1d48) fast-xml-parser: specifier: 5.11.1 version: 5.11.1 @@ -25687,7 +25688,7 @@ snapshots: dependencies: eventsource-parser: 3.1.0 - exceljs@4.4.0: + exceljs@4.4.0(patch_hash=c1bf8ac8f319dab382f08e3a669b715e691d46c703ac5a4163eb383fbedd1d48): dependencies: archiver: 5.3.2 dayjs: 1.11.21 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 5480d37563..96ef53fef0 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -100,4 +100,5 @@ patchedDependencies: '@fortune-sheet/core@1.0.4': patches/@fortune-sheet__core@1.0.4.patch '@fortune-sheet/react@1.0.4': patches/@fortune-sheet__react@1.0.4.patch '@yao-pkg/pkg@6.21.0': patches/@yao-pkg__pkg@6.21.0.patch + exceljs@4.4.0: patches/exceljs@4.4.0.patch node-pty@1.2.0-beta.15: patches/node-pty@1.2.0-beta.15.patch diff --git a/snapshots/web/excel-opc/excel.expected.md b/snapshots/web/excel-opc/excel.expected.md new file mode 100644 index 0000000000..f5646c2ba5 --- /dev/null +++ b/snapshots/web/excel-opc/excel.expected.md @@ -0,0 +1,22 @@ +# Independent-writer Excel previews + +- comments.xlsx: 数据 opened; Item copied +- table.xlsx: 数据 opened; Item copied +- prefix.xlsx: 数据 opened; Item copied +- part-name.xlsx: 数据 opened; Item copied +- relative.xlsx: 数据 opened; Item copied +- combined.xlsx: 数据 opened; Item copied +- strict.xlsx: 数据 opened; Item copied +- case-root.xlsx: 数据 opened; Item copied +- case-parts.xlsx: 数据 opened; Item copied +- orphan-drawing.xlsx: 数据 opened; Item copied +- rich.xlsx: 数据 opened; Item copied +- utf16-sheet.xlsx: 数据 opened; Item copied +- utf16-metadata.xlsx: 数据 opened; Item copied +- workbook-path.xlsx: 数据 opened; Item copied +- styles-path.xlsx: 数据 opened; Item copied +- strings-path.xlsx: 数据 opened; Item copied +- cdata.xlsx: 数据 opened; Item copied +- parts-path.xlsx: 数据 opened; Item copied +- Relocated workbook: hidden sheet omitted +- Relocated workbook notice: This preview does not support charts, images, shapes, conditional formatting in this workbook. Open it in a system application for the full experience. diff --git a/snapshots/web/excel-opc/snapshot.yml b/snapshots/web/excel-opc/snapshot.yml new file mode 100644 index 0000000000..45e0103f6a --- /dev/null +++ b/snapshots/web/excel-opc/snapshot.yml @@ -0,0 +1,9 @@ +version: 1 +scenario: excel-opc +profile: web +composition: web-default +recording: authored +header: + class: web-default +session: + source: ../lifecycle-chrome/session.v3.jsonl diff --git a/tsconfig.host.json b/tsconfig.host.json index a176af9937..27ecdc9c23 100644 --- a/tsconfig.host.json +++ b/tsconfig.host.json @@ -48,6 +48,7 @@ "apps/web/tests/details-session-lifecycle.e2e.ts", "apps/web/tests/sessionless-header.e2e.ts", "apps/web/tests/document-preview.e2e.ts", + "apps/web/tests/excel-opc.e2e.ts", "apps/web/tests/office-fixture.ts", "apps/web/tests/sidebar-browser.e2e.ts", "apps/web/tests/plugin-config.e2e.ts", From 4777947b6c00810c7e102b9efbd64a5994508ff6 Mon Sep 17 00:00:00 2001 From: lsdsjy <1356263+lsdsjy@users.noreply.github.com> Date: Tue, 22 Sep 2026 16:16:34 +0800 Subject: [PATCH 18/29] fix(client): keep account UID fields out of questionnaire URLs The Contact us action already stopped prefilling the signed-in UID, but a configured contact form URL could still carry its own prefill_uid or hide_uid. contactUrl now drops both query parameters unconditionally, with regression coverage that starts from a form URL containing them. The contact URL test also pins the shipped default form path, and the injected contactUs documentation and the AccountProfile summary no longer describe a support UID that is no longer sent. --- .../client/ui-settings-account/src/client/AccountSection.tsx | 2 +- .../client/ui-settings-account/src/client/contact-url.ts | 2 ++ .../ui-settings-account/tests/contact-url.client.spec.ts | 5 ++++- packages/credentials/deepseek-account/src/types.ts | 2 +- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/client/ui-settings-account/src/client/AccountSection.tsx b/packages/client/ui-settings-account/src/client/AccountSection.tsx index d5e4f5d82a..1b0d344bd0 100644 --- a/packages/client/ui-settings-account/src/client/AccountSection.tsx +++ b/packages/client/ui-settings-account/src/client/AccountSection.tsx @@ -40,7 +40,7 @@ export interface AccountSectionInjected { } /** @returns after account details are refreshed; concurrent refreshes share a request. */ refresh: () => Promise - /** Open the external support questionnaire with the current account and environment. */ + /** Open the external support questionnaire with the current build and browser environment. */ contactUs: () => void /** Open or dismiss the login dialog. */ showLogin: (visible: boolean) => void diff --git a/packages/client/ui-settings-account/src/client/contact-url.ts b/packages/client/ui-settings-account/src/client/contact-url.ts index 5620f99d00..524a441139 100644 --- a/packages/client/ui-settings-account/src/client/contact-url.ts +++ b/packages/client/ui-settings-account/src/client/contact-url.ts @@ -28,5 +28,7 @@ export function contactUrl(config: Config, context: { url.searchParams.delete(`prefill_${name}`) if (value) url.searchParams.set(`prefill_${name}`, value) } + url.searchParams.delete('prefill_uid') + url.searchParams.delete('hide_uid') return url.href } diff --git a/packages/client/ui-settings-account/tests/contact-url.client.spec.ts b/packages/client/ui-settings-account/tests/contact-url.client.spec.ts index 943c75cfe8..3e00ee99ba 100644 --- a/packages/client/ui-settings-account/tests/contact-url.client.spec.ts +++ b/packages/client/ui-settings-account/tests/contact-url.client.spec.ts @@ -8,6 +8,7 @@ it('prefills available support context and hides all context fields', () => { version: '1.2.3', locale: 'zh-CN', width: 1512, height: 982, pixelRatio: 2, })) expect(url.origin).toBe('https://trtgsjkv6r.feishu.cn') + expect(url.pathname).toBe('/share/base/form/shrcnlCoGElW7MQznGy9r3YYXcg') expect(Object.fromEntries(url.searchParams)).toEqual({ hide_source: '1', prefill_source: 'app_harness', hide_app_version: '1', prefill_app_version: '1.2.3', hide_os_version: '1', @@ -19,10 +20,12 @@ it('prefills available support context and hides all context fields', () => { }) it('opens a configured form without stale context when unavailable', () => { - const url = new URL(contactUrl(Config({ contactFormUrl: 'https://example.test/form/?prefill_app_version=old&prefill_source=old' }), { + const url = new URL(contactUrl(Config({ contactFormUrl: 'https://example.test/form/?prefill_uid=old&hide_uid=1&prefill_app_version=old&prefill_source=old' }), { version: undefined, locale: 'en', width: 0, height: 0, pixelRatio: 1, })) expect(url.origin).toBe('https://example.test') + expect(url.searchParams.has('prefill_uid')).toBe(false) + expect(url.searchParams.has('hide_uid')).toBe(false) expect(url.searchParams.has('prefill_app_version')).toBe(false) expect(url.searchParams.has('prefill_source')).toBe(false) expect(url.searchParams.has('prefill_screen_resolution')).toBe(false) diff --git a/packages/credentials/deepseek-account/src/types.ts b/packages/credentials/deepseek-account/src/types.ts index f59c959567..7245ba1418 100644 --- a/packages/credentials/deepseek-account/src/types.ts +++ b/packages/credentials/deepseek-account/src/types.ts @@ -27,7 +27,7 @@ export interface AccountView { /** Platform account identifier supplied by the current-user endpoint. */ export type AccountUserId = Branded<'AccountUserId'> -/** Display identity and support UID; contacts retain Platform masking. */ +/** Display identity; contacts retain Platform masking. */ export interface AccountProfile { readonly id: AccountUserId | null readonly name: string | null From 780e07b8eda61042c3c59a0b4eadca714d62dbfc Mon Sep 17 00:00:00 2001 From: yixiangihsiang Date: Tue, 22 Sep 2026 16:28:46 +0800 Subject: [PATCH 19/29] test(web): align built boot assertions with diff layout --- apps/web/tests/built-boot.expected.e2e.ts | 25 +++++++++++++---------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/apps/web/tests/built-boot.expected.e2e.ts b/apps/web/tests/built-boot.expected.e2e.ts index 46115eff44..7ab01184fc 100644 --- a/apps/web/tests/built-boot.expected.e2e.ts +++ b/apps/web/tests/built-boot.expected.e2e.ts @@ -121,24 +121,27 @@ it('boots the built plugin graph and renders a fixture session end to end', asyn within(contextPanel).getByText('Tool definitions') within(contextPanel).getByText('Messages') - // The write/edit turns render a real diff card through the assembled graph - // (the keyed FileMutationRow composing ToolRow + DiffBlock), not just the - // fixture's raw text. The card is collapsed by default, so expand each edit/ - // write row first. The write turn's `hello fixture\n` proves the terminator - // rule end to end: a trailing newline terminates its line, so the footer reads - // `+1` (not a phantom `+2`) and one distinct file. The `+ ` prefix is a CSS - // ::before, so it is absent from textContent — assert on the line body and the - // footer. - const mutationRows = [...document.querySelectorAll('[data-variant="write"],[data-variant="edit"]')] + // The built ToolRow and DiffBlock share the write fixture's trailing-newline + // semantics: `hello fixture\n` contributes one addition. Counts belong to the + // tool row; the diff's line markers are CSS pseudo-elements, absent from textContent. + const mutationRows = [...document.querySelectorAll('[data-variant="write"],[data-variant="edit"]')] expect(mutationRows.length).toBeGreaterThan(0) + const writeRow = mutationRows.find(row => row.getAttribute('data-variant') === 'write' + && row.textContent?.includes('new-demo.txt')) + if (writeRow === undefined) throw new Error('fixture write row missing') + expect(within(writeRow).getAllByText('+1 -0', { exact: true })).toHaveLength(1) + expect(writeRow.querySelector('[data-diff]')).toBeNull() for (const row of mutationRows) { const toggle = row.querySelector('[data-expandable]') if (toggle !== null) act(() => { fireEvent.click(toggle) }) } const diffCards = [...document.querySelectorAll('[data-diff]')] expect(diffCards.length).toBeGreaterThan(0) - const footers = diffCards.map(card => card.textContent ?? '') - expect(footers.some(text => text.includes('hello fixture') && text.includes('+1 -0 · 1 file'))).toBe(true) + const writeDiff = writeRow.querySelector('[data-diff]') + if (writeDiff === null) throw new Error('expanded fixture write diff missing') + within(writeDiff).getByText('hello fixture', { exact: true }) + expect(within(writeRow).getAllByText('+1 -0', { exact: true })).toHaveLength(1) + expect(writeDiff.textContent).not.toContain('+1 -0') // The web render intent reaches the assembled boot graph: the fixture's // web_search / web_fetch turns render their keyed WebRow cards, proving the From 2d653be7b0e550c7a6c98ae3042a237229732fef Mon Sep 17 00:00:00 2001 From: turtle1999 Date: Tue, 22 Sep 2026 16:33:24 +0800 Subject: [PATCH 20/29] fix(tool-jobs): address review on the unbounded wake default Skip the per-owner wake ledger entirely when no cap is configured. Rewrite the 2026-08-11 Agent Note in place for the opt-in cap and add a note recording why the default was removed. Keep `subagent` untranslated in Chinese prose and drop change narration from the test. Refs #4944 --- ...b-completion-wakes-an-idle-owner.i18n.yaml | 4 +-- ...ound-job-completion-wakes-an-idle-owner.md | 16 ++++----- ...d-job-completion-wakes-an-idle-owner.zh.md | 16 ++++----- ...nded-completion-wakes-by-default.i18n.yaml | 6 ++++ ...2-unbounded-completion-wakes-by-default.md | 36 +++++++++++++++++++ ...nbounded-completion-wakes-by-default.zh.md | 36 +++++++++++++++++++ packages/jobs/tool-jobs/README.i18n.yaml | 2 +- packages/jobs/tool-jobs/README.zh.md | 2 +- packages/jobs/tool-jobs/src/index.ts | 18 ++++++---- .../jobs/tool-jobs/tests/tool-jobs.spec.ts | 4 +-- 10 files changed, 110 insertions(+), 30 deletions(-) create mode 100644 .agents/notes/implemented/feature/2026-09-22-unbounded-completion-wakes-by-default.i18n.yaml create mode 100644 .agents/notes/implemented/feature/2026-09-22-unbounded-completion-wakes-by-default.md create mode 100644 .agents/notes/implemented/feature/2026-09-22-unbounded-completion-wakes-by-default.zh.md diff --git a/.agents/notes/implemented/feature/2026-08-11-background-job-completion-wakes-an-idle-owner.i18n.yaml b/.agents/notes/implemented/feature/2026-08-11-background-job-completion-wakes-an-idle-owner.i18n.yaml index a38790ad6e..3b96b194f6 100644 --- a/.agents/notes/implemented/feature/2026-08-11-background-job-completion-wakes-an-idle-owner.i18n.yaml +++ b/.agents/notes/implemented/feature/2026-08-11-background-job-completion-wakes-an-idle-owner.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-11-background-job-completion-wakes-an-idle-owner.md -2026-08-11-background-job-completion-wakes-an-idle-owner.md: 0844948eaa8e58e9d22667eb0962865a17969c07 -2026-08-11-background-job-completion-wakes-an-idle-owner.zh.md: d09454d17b8f1b579305cc1e98540d5ecb2f2d4f +2026-08-11-background-job-completion-wakes-an-idle-owner.md: f13f09d326dc7b4e7b2998f3124f70c185c50922 +2026-08-11-background-job-completion-wakes-an-idle-owner.zh.md: f9b563ebbf90e2ca19d1fc5ca9fa5b028e4429f1 diff --git a/.agents/notes/implemented/feature/2026-08-11-background-job-completion-wakes-an-idle-owner.md b/.agents/notes/implemented/feature/2026-08-11-background-job-completion-wakes-an-idle-owner.md index 0844948eaa..f13f09d326 100644 --- a/.agents/notes/implemented/feature/2026-08-11-background-job-completion-wakes-an-idle-owner.md +++ b/.agents/notes/implemented/feature/2026-08-11-background-job-completion-wakes-an-idle-owner.md @@ -4,8 +4,6 @@ Status: implemented Update: the `reported` bit and `onJobDone` this note relies on left the registry with the [jobs seam consolidation](../architecture/2026-09-03-jobs-seam-consolidation.md): `dsh-tool-jobs` now keeps the delivery ledger (a wait or an accepted `job_kill` claims the task) and skips teardown settlements by their `settled` cause, so the wake-or-inject decision below stands while the mechanism it names is the tool's ledger, not a registry flag. -Update: `maxConsecutiveWakes` no longer defaults to 3; unset, every idle completion wakes its owner. The accepted risk below — a spent budget is restored only by user input — was reported as a bug ([dsh-external/issues#641](https://github.com/dsh-external/issues/issues/641)): a session mixing background commands and one-shot subagents exhausted the budget after three wakes, the fourth notice parked silently in the next-step inbox with nothing visible in the client, and the model's "you are notified when a job finishes" promise turned false exactly when the user was away. An invisible stall costs more than an unbounded chain of model requests the user can watch and stop, so the cap is opt-in. The self-exciting rationale for the field stands for deployments that set it. - English | [中文](2026-08-11-background-job-completion-wakes-an-idle-owner.zh.md) ## Problem @@ -30,11 +28,11 @@ For a driver that is genuinely running, `steer()` and `inject()` are the same de Injection is correct there. A cancelled turn is a user pressing stop, and reopening one on their behalf launders an interrupt into a model request they did not ask for. The turn loop already covers the ordinary case: it cannot close while the next-step inbox holds anything, so a notice arriving before that check extends the current turn, and several tasks settling together cost one step rather than one turn each. -### Waking is bounded, and the bound is not time +### The cap on consecutive wakes is opt-in, and it is not time -`maxConsecutiveWakes` (default 3) caps the turns one owner may open this way; beyond it a notice degrades to injection and waits for the next turn. Claiming any user-authored message restores the budget — claiming, not arrival, because that is the point human input actually enters a step. Notices this plugin queued never refill it. +Waking is unbounded unless `maxConsecutiveWakes` is set. With it set, the value caps the turns one owner may open this way; beyond it a notice degrades to injection and waits for the next turn. Claiming any user-authored message restores the budget — claiming, not arrival, because that is the point human input actually enters a step. Notices this plugin queued never refill it. -The bound exists because this chain is self-exciting in a way subagent settlement is not. Settlement is bounded by how many children the model spawned; a woken turn can start the background job whose completion wakes it again, with nobody watching. `dsh run` needs no separate policy: its one user message is claimed in the first turn and never repeats, so the budget is spent monotonically and the process terminates. +The cap exists because this chain is self-exciting in a way subagent settlement is not. Settlement is bounded by how many children the model spawned; a woken turn can start the background job whose completion wakes it again, with nobody watching. It has no default because a notice past the cap stalls the session invisibly; the [unbounded-by-default decision](2026-09-22-unbounded-completion-wakes-by-default.md) records that trade-off. `dsh run` needs no separate policy either way: headless exits once the task turn goes idle, so a completion after that point has no owner to wake. `completionDelivery: quiet` restores the old lane for idle owners. It exists for deterministic transcripts; job completion independently retains `quiet | wakeup` because its bounded owner-turn policy differs from next-step subagent reports. @@ -54,15 +52,15 @@ The bound exists because this chain is self-exciting in a way subagent settlemen **A general unsolicited-input queue** with priority lanes, as Claude Code uses to merge background jobs, cron, MCP push, and hooks into one drain. DSH's inbox already is that queue — durable `agent/inbox/spliced` splices over `next-turn`/`next-step` — so this would add a layer above an existing one to decide a single bit. -**Refusing to reopen a turn that already produced a visible answer,** Codex's `MailboxDeliveryPhase` latch. That latch is the default this decision deliberately inverts: waking after the model has spoken is the entire point, and the wake budget is the bound instead. +**Refusing to reopen a turn that already produced a visible answer,** Codex's `MailboxDeliveryPhase` latch. That latch is the default this decision deliberately inverts: waking after the model has spoken is the entire point, and the optional wake budget is the bound instead. -**A wall-clock window** on top of the counter. For an interactive agent the slow case is the wanted one — an hour-long build finishing and the agent resuming is the feature — and `dsh run` is already bounded by the counter it cannot refill. Worth revisiting only if an unattended long-lived deployment appears. +**A wall-clock window** on top of the counter. For an interactive agent the slow case is the wanted one — an hour-long build finishing and the agent resuming is the feature — and `dsh run` exits once its task turn goes idle regardless. Worth revisiting only if an unattended long-lived deployment appears. **Suppressing `onJobDone` entirely during owner drain,** symmetric with the service-wide `listenersClosed`. It reads cleaner and removes a signal that is not only for notices: the force-fail record and the runtime invariant both observe teardown settlements. The `reported` bit denies exactly the reporters and nothing else. ## Consequences -- Default behavior changes: an idle owner now spends a model request per completion, capped at `maxConsecutiveWakes` per owner between user messages. Deployments that want the old behavior set `completionDelivery: quiet`. +- Default behavior changes: an idle owner now spends a model request per completion, capped per owner between user messages only where `maxConsecutiveWakes` is set. Deployments that want the old behavior set `completionDelivery: quiet`. - The `tool-jobs` prompt section needs no edit; "You are notified in-session when a task finishes" became true rather than aspirational. - `JobSnapshot.reported` gains teardown as a fourth setter, documented at the Service Definition and in [the subsystem reference](../../../../docs/subsystems/jobs.md). - `settle()` announces completion after committing the record and publishing the visible-set change. Any listener relying on running before waiters were released or before `onJobsChanged` now runs after both. @@ -71,7 +69,7 @@ The bound exists because this chain is self-exciting in a way subagent settlemen ### Accepted risks -A spent budget is restored only by user input. An unattended agent that exhausts it collects its remaining notices whenever something else opens a turn, and nothing re-arms it in the meantime. +Under a configured `maxConsecutiveWakes`, a spent budget is restored only by user input. An unattended agent that exhausts it collects its remaining notices whenever something else opens a turn, nothing re-arms it in the meantime, and the client shows nothing while the notice waits. This is why the cap has no default. A notice pending on an idle owner under `quiet` still dies with that owner's disposal, unchanged from before: the disposal cancel clears the unclaimed inbox and the log keeps the insert/cancel pair as the record. The [settlement delivery note](2026-08-06-manager-owned-subagent-settlement-delivery.md) owns the offline-mailbox discussion this would need. diff --git a/.agents/notes/implemented/feature/2026-08-11-background-job-completion-wakes-an-idle-owner.zh.md b/.agents/notes/implemented/feature/2026-08-11-background-job-completion-wakes-an-idle-owner.zh.md index d09454d17b..f9b563ebbf 100644 --- a/.agents/notes/implemented/feature/2026-08-11-background-job-completion-wakes-an-idle-owner.zh.md +++ b/.agents/notes/implemented/feature/2026-08-11-background-job-completion-wakes-an-idle-owner.zh.md @@ -4,8 +4,6 @@ Status: implemented Update:本文依赖的 `reported` 位与 `onJobDone` 已随 [jobs seam 收敛](../architecture/2026-09-03-jobs-seam-consolidation.zh.md)离开注册表:`dsh-tool-jobs` 现在持有投递台账(等待或被接受的 `job_kill` 认领任务),并按 `settled` 事件的 cause 跳过 teardown 结算,因此下文唤醒或注入的决策仍然成立,只是它提到的机制是工具的台账而非注册表标志。 -Update:`maxConsecutiveWakes` 不再默认为 3;未设置时每次空闲完成都会唤醒所有者。下文"已花掉的预算只由用户输入恢复"这条接受的风险被报告为缺陷([dsh-external/issues#641](https://github.com/dsh-external/issues/issues/641)):一个会话混用后台命令与一次性子代理,三次唤醒后预算耗尽,第四条通知静默停在 next-step inbox 里,客户端毫无显示,而模型得到的"任务完成会通知你"承诺恰好在用户离开时失效。不可见的停摆比一条用户能看到并能停止的、无上限的模型请求链代价更高,因此上限改为可选。自激链的理由对设置了该字段的部署依然成立。 - [English](2026-08-11-background-job-completion-wakes-an-idle-owner.md) | 中文 ## 问题 @@ -30,11 +28,11 @@ Update:`maxConsecutiveWakes` 不再默认为 3;未设置时每次空闲完 在那里注入才是对的。轮次被取消意味着用户按了停止,替他们重新开一轮等于把一次中断洗成了他们没有要求的模型请求。普通情形已由轮次循环覆盖:只要 next-step inbox 还有内容,轮次就无法结束,因此在该检查之前抵达的通知会延长当前轮次,同时结算的多个任务只花掉一步而不是各占一轮。 -### 唤醒有界,且该界不是时间 +### 连续唤醒上限是可选的,且该界不是时间 -`maxConsecutiveWakes`(默认 3)限制一个所有者由此开启的轮数;超出后通知降级为注入,等待下一轮。领取任何用户撰写的消息都会恢复预算——是领取而非抵达,因为那才是人类输入真正进入某一步的时刻。本插件自己排队的通知永远不会补充它。 +除非设置了 `maxConsecutiveWakes`,唤醒没有上限。设置后,该值限制一个所有者由此开启的轮数;超出后通知降级为注入,等待下一轮。领取任何用户撰写的消息都会恢复预算——是领取而非抵达,因为那才是人类输入真正进入某一步的时刻。本插件自己排队的通知永远不会补充它。 -设界是因为这条链会自激,而 subagent 结算不会。结算受限于模型派生了多少子 agent;被唤醒的一轮却可能启动某个后台任务,而它的完成又会唤醒同一个所有者,且无人旁观。`dsh run` 不需要单独策略:它唯一的用户消息在第一轮就被领取且不会重复,因此预算单调消耗,进程必然终止。 +设上限是因为这条链会自激,而 subagent 结算不会。结算受限于模型派生了多少子 agent;被唤醒的一轮却可能启动某个后台任务,而它的完成又会唤醒同一个所有者,且无人旁观。它没有默认值,因为超出上限的通知会让会话不可见地停摆;[默认无上限的决策](2026-09-22-unbounded-completion-wakes-by-default.zh.md)记录了这项取舍。`dsh run` 无论如何都不需要单独策略:headless 在任务轮次空闲后即退出,此后的完成没有可唤醒的所有者。 `completionDelivery: quiet` 为空闲所有者恢复旧通道。它的存在是为了确定性 transcript;后台任务完成会独立保留 `quiet | wakeup`,因为其有界的所有者轮次策略不同于 next-step subagent 报告。 @@ -54,15 +52,15 @@ Update:`maxConsecutiveWakes` 不再默认为 3;未设置时每次空闲完 **一个通用的非请求输入队列**并带优先级通道,正如 Claude Code 用来把后台任务、cron、MCP 推送与 hook 合并进同一次排空。DSH 的 inbox 本身就是那个队列——`next-turn`/`next-step` 之上的持久 `agent/inbox/spliced` splice——因此这等于在既有层之上再加一层,只为决定一个 bit。 -**拒绝重开一个已经产出可见答复的轮次**,即 Codex 的 `MailboxDeliveryPhase` 闩锁。那条闩锁正是本决策刻意反转的默认值:在模型已经说完话之后唤醒它就是本特性的全部意义,界由唤醒预算来承担。 +**拒绝重开一个已经产出可见答复的轮次**,即 Codex 的 `MailboxDeliveryPhase` 闩锁。那条闩锁正是本决策刻意反转的默认值:在模型已经说完话之后唤醒它就是本特性的全部意义,界由可选的唤醒预算来承担。 -**在计数之上再加墙钟窗口**。对交互式 agent 而言,慢的那种情形恰恰是想要的——一小时的构建结束、agent 接着干下去,这就是特性本身——而 `dsh run` 已被它无法补充的计数封顶。只有当出现无人值守的长生命周期部署时才值得重新考虑。 +**在计数之上再加墙钟窗口**。对交互式 agent 而言,慢的那种情形恰恰是想要的——一小时的构建结束、agent 接着干下去,这就是特性本身——而 `dsh run` 无论如何都在任务轮次空闲后退出。只有当出现无人值守的长生命周期部署时才值得重新考虑。 **在 owner 排空期间整体压制 `onJobDone`**,与服务级的 `listenersClosed` 对称。它读起来更干净,但会移走一个不只服务于通知的信号:强制失败记录与运行时不变量都会观察 teardown 结算。`reported` 位恰好只否决报告方,别的什么也不否决。 ## 影响 -- 默认行为改变:空闲所有者现在每次完成会花掉一次模型请求,按所有者、在两次用户消息之间由 `maxConsecutiveWakes` 封顶。想要旧行为的部署设置 `completionDelivery: quiet`。 +- 默认行为改变:空闲所有者现在每次完成会花掉一次模型请求,只有设置了 `maxConsecutiveWakes` 时才按所有者、在两次用户消息之间封顶。想要旧行为的部署设置 `completionDelivery: quiet`。 - `tool-jobs` 的提示词段落无需改动;「任务完成时你会在会话内收到通知」从愿景变成了事实。 - `JobSnapshot.reported` 新增 teardown 作为第四个置位方,记录在 Service Definition 与[子系统参考](../../../../docs/subsystems/jobs.zh.md)中。 - `settle()` 在提交记录并发布可见集变更之后才宣布完成。任何依赖「在释放等待方之前或在 `onJobsChanged` 之前运行」的监听器现在都排在两者之后。 @@ -71,7 +69,7 @@ Update:`maxConsecutiveWakes` 不再默认为 3;未设置时每次空闲完 ### 已接受的风险 -已花掉的预算只由用户输入恢复。耗尽预算的无人值守 agent 要等到其他原因开启轮次时才收走剩余通知,在此期间没有任何机制为它重新充能。 +在设置了 `maxConsecutiveWakes` 的情况下,已花掉的预算只由用户输入恢复。耗尽预算的无人值守 agent 要等到其他原因开启轮次时才收走剩余通知,在此期间没有任何机制为它重新充能,通知等待时客户端也毫无显示。这正是上限没有默认值的原因。 在 `quiet` 下待领于空闲所有者的通知仍会随该所有者释放而消亡,与此前一致:释放时的取消会清空未领取的 inbox,日志保留插入/取消这一对作为记录。[结算交付 note](2026-08-06-manager-owned-subagent-settlement-delivery.zh.md) 承载这需要的离线信箱讨论。 diff --git a/.agents/notes/implemented/feature/2026-09-22-unbounded-completion-wakes-by-default.i18n.yaml b/.agents/notes/implemented/feature/2026-09-22-unbounded-completion-wakes-by-default.i18n.yaml new file mode 100644 index 0000000000..24ad5190da --- /dev/null +++ b/.agents/notes/implemented/feature/2026-09-22-unbounded-completion-wakes-by-default.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/feature/2026-09-22-unbounded-completion-wakes-by-default.md +2026-09-22-unbounded-completion-wakes-by-default.md: 8760154054de423240e16d93e3db5ae01521820a +2026-09-22-unbounded-completion-wakes-by-default.zh.md: e5560bc7ced5a8ca9ab55ea56ba309676d78b568 diff --git a/.agents/notes/implemented/feature/2026-09-22-unbounded-completion-wakes-by-default.md b/.agents/notes/implemented/feature/2026-09-22-unbounded-completion-wakes-by-default.md new file mode 100644 index 0000000000..8760154054 --- /dev/null +++ b/.agents/notes/implemented/feature/2026-09-22-unbounded-completion-wakes-by-default.md @@ -0,0 +1,36 @@ +# Agent Note: Background job completion wakes are unbounded by default + +Status: implemented + +English | [中文](2026-09-22-unbounded-completion-wakes-by-default.zh.md) + +## Problem + +The [idle-owner wake decision](2026-08-11-background-job-completion-wakes-an-idle-owner.md) shipped `maxConsecutiveWakes` with a default of 3: an idle owner could be woken three times by job completions before further notices degraded to injection, and only a claimed user message refilled the budget. The counter was per owner and shared by every job kind — background `bash`/`pwsh`/PTY commands and one-shot `subagent_*` children. + +A session that chained more than three of them without a user message hit the cap (issue #4944, reported as [dsh-external/issues#641](https://github.com/dsh-external/issues/issues/641)). The fourth notice was injected into the next-step inbox of an owner nothing would wake; the client renders no pending `context` message, so the session sat with a notice it could not see. The `tool-jobs` prompt promises the model "you are notified in-session when a job finishes — do not busy-poll", which encourages exactly the start-and-end-turn pattern that exhausts the cap. The stall arrived when the user was away and looked like a hang until they typed something. + +## Decision + +`maxConsecutiveWakes` has no default. Unset, every completion reaching an idle owner under `wakeup` delivery opens a turn. The `agent/inbox/claimed` refill listener and the per-owner ledger exist only when a cap is configured; a configured value must still be a whole number of turns, and `Infinity` is rejected because omitting the field already means unbounded. + +The self-exciting chain the cap was built for — a woken turn starting the job whose completion wakes it again — is still real, and deployments that want the bound set the field. The trade-off is that the chain spends model requests the user can watch and stop, while a notice parked past a cap is invisible: nothing in the client shows it, nothing re-arms the budget, and the model's promise becomes false. An observable cost beats an unobservable stall. + +`dsh run` is unaffected: headless exits once the task turn goes idle, so there is no idle owner left to wake. + +## Alternatives considered + +**Keep the default cap and make the parked notice visible** — a session-level pending indicator or an unread mark on the jobs list. This keeps the runaway bound but still breaks the prompt's promise: the model ended its turn expecting a notice and receives nothing until the user acts. Visibility is worth adding for a configured cap; it does not justify a default one. + +**Count only self-excited wakes** — a wake counts against the budget only when the woken turn starts a new background job. This bounds the runaway chain without cutting off a chain of independent jobs, but the distinction needs the plugin to correlate job starts with the turn a wake opened, state no current consumer needs. It remains the natural refinement if a configured cap proves too coarse. + +**A cooldown or rate limit instead of a counter.** Time does not distinguish a wanted chain from a runaway one; the wanted case is often the slow one, and a rate limit still parks a notice invisibly when it triggers. + +**Re-check the next-step inbox on every turn-close path** (abort, LLM error, rejected pre-step). This closes the other parking spots the issue lists, but they are reached only by an already-parked notice; with no default cap the reported scenario never parks one. It stays a separate `agent-loop` change. + +## Consequences + +- An unattended session chaining background jobs is woken for every completion; the model request per wake is the cost, and the user can stop the session. +- The cap is opt-in configuration. Its README, config-catalog, and JSDoc state the silent-stall cost of setting it. +- Unit coverage pins four unattended completions each opening a turn under the default config; the cap, refill, and quiet-delivery tests keep explicit `maxConsecutiveWakes` values. +- No recorded-session snapshot changes: no shipped profile sets the field, and no existing scenario chains more than three idle completions. diff --git a/.agents/notes/implemented/feature/2026-09-22-unbounded-completion-wakes-by-default.zh.md b/.agents/notes/implemented/feature/2026-09-22-unbounded-completion-wakes-by-default.zh.md new file mode 100644 index 0000000000..e5560bc7ce --- /dev/null +++ b/.agents/notes/implemented/feature/2026-09-22-unbounded-completion-wakes-by-default.zh.md @@ -0,0 +1,36 @@ +# Agent Note: Background job completion wakes are unbounded by default + +Status: implemented + +[English](2026-09-22-unbounded-completion-wakes-by-default.md) | 中文 + +## 问题 + +[空闲所有者唤醒决策](2026-08-11-background-job-completion-wakes-an-idle-owner.zh.md)发布时 `maxConsecutiveWakes` 默认为 3:空闲所有者最多被任务完成唤醒三次,此后的通知降级为注入,只有被领取的用户消息才补充预算。计数器按所有者记录,并由所有任务类型共用——后台 `bash`/`pwsh`/PTY 命令与一次性 `subagent_*` 子级。 + +一个会话在没有用户消息的情况下串起超过三个这样的任务就会触顶(issue #4944,来源为 [dsh-external/issues#641](https://github.com/dsh-external/issues/issues/641))。第四条通知被注入到一个无人会唤醒的所有者的 next-step inbox;客户端不渲染待领的 `context` 消息,会话就带着一条自己看不见的通知停在那里。`tool-jobs` 的提示词向模型承诺「任务完成会在会话内通知你,不要轮询」,恰恰鼓励了会耗尽上限的「启动后结束本轮」模式。停摆发生在用户离开时,看起来像挂死,直到用户输入点什么。 + +## 决策 + +`maxConsecutiveWakes` 没有默认值。未设置时,`wakeup` 投递下抵达空闲所有者的每次完成都会开启一轮。`agent/inbox/claimed` 补充监听与按所有者的台账只在配置了上限时存在;配置的值仍必须是整数轮数,`Infinity` 被拒绝,因为省略该字段已经表示无上限。 + +上限所针对的自激链——被唤醒的一轮启动某个任务,其完成又唤醒它——依然真实存在,想要该界的部署自行设置字段。取舍在于:这条链花掉的是用户看得见、能停下的模型请求,而停在上限之外的通知是不可见的:客户端不显示,没有机制重新充能预算,模型得到的承诺也成了假话。可观察的代价胜过不可观察的停摆。 + +`dsh run` 不受影响:headless 在任务轮次空闲后即退出,没有可唤醒的空闲所有者。 + +## 被否决的替代方案 + +**保留默认上限,让停驻的通知可见**——会话级的待处理指示或任务列表上的未读标记。这保住了失控约束,但仍然违背提示词的承诺:模型结束本轮等着通知,却要等到用户动手才收到。可见性值得为已配置的上限补上;它不能为默认上限辩护。 + +**只统计自激的唤醒**——只有被唤醒的一轮又启动了新的后台任务时才计入预算。这约束了失控链而不切断一串独立任务,但这种区分需要插件把任务启动与唤醒所开启的轮次关联起来,是当前没有消费者需要的状态。若配置的上限被证明过粗,它仍是自然的细化方向。 + +**用冷却或速率限制代替计数器。** 时间无法区分想要的链与失控的链;想要的情形往往正是慢的那种,而速率限制触发时同样会把通知不可见地停驻。 + +**在每条轮次结束路径上复查 next-step inbox**(abort、LLM 错误、被拒绝的 pre-step)。这关闭了 issue 列出的其他停驻点,但它们只会被一条已停驻的通知触及;没有默认上限时,报告的场景根本不会停驻通知。它仍是独立的 `agent-loop` 改动。 + +## 影响 + +- 串起后台任务的无人值守会话会为每次完成被唤醒;每次唤醒一次模型请求是其代价,用户可以停止会话。 +- 上限是可选配置。其 README、config-catalog 与 JSDoc 说明了设置它带来的静默停摆代价。 +- 单元覆盖钉住默认配置下连续四次无人值守完成各开启一轮;上限、补充与 quiet 投递的测试保留显式的 `maxConsecutiveWakes` 值。 +- 录制会话快照无变化:没有任何内置 profile 设置该字段,也没有既有场景串起超过三次空闲完成。 diff --git a/packages/jobs/tool-jobs/README.i18n.yaml b/packages/jobs/tool-jobs/README.i18n.yaml index d76b088fdc..4c58868e42 100644 --- a/packages/jobs/tool-jobs/README.i18n.yaml +++ b/packages/jobs/tool-jobs/README.i18n.yaml @@ -3,4 +3,4 @@ # after editing either side, bring the other along and re-record with: # pnpm run verify-translation-pairing --write packages/jobs/tool-jobs/README.md README.md: 2836f10e160ae3ecfe9a2df7f6b82a88b4ddf33f -README.zh.md: b5b702ab5f8ca4c72545f3e46899a3f01624eb42 +README.zh.md: 1311f5656ded91fd4cc520e1114a41bb87ebf4d3 diff --git a/packages/jobs/tool-jobs/README.zh.md b/packages/jobs/tool-jobs/README.zh.md index b5b702ab5f..1311f5656d 100644 --- a/packages/jobs/tool-jobs/README.zh.md +++ b/packages/jobs/tool-jobs/README.zh.md @@ -39,7 +39,7 @@ kind: "package-reference" 任务完成时,拥有它的 agent 会收到会话内消息 `background job (: ## Excel preview -Open `.xlsx`, `.xls`, `.csv`, and `.tsv` directly in the browser with worksheet tabs, cell selection, copying, and a read-only formula bar. XLSX retains fonts, solid fills, borders, number formats, rich text, merged cells, row and column sizes, hidden rows/columns/sheets, and frozen headings. XLS retains saved values, formulas, number formats, merges, and available row/column metadata; fonts, borders, and frozen panes are unsupported. Workbooks display saved formula results without recalculating; missing results remain blank, and a compact formula-bar warning marks workbooks whose displayed results may be incomplete or inaccurate. Spreadsheet preview does not call the Office conversion service. +Open `.xlsx`, `.xls`, `.csv`, and `.tsv` directly in the browser with worksheet tabs, cell selection, copying, and a read-only formula bar. XLSX retains fonts, solid fills, borders, number formats, rich text, merged cells, row and column sizes, hidden rows/columns/sheets, and frozen headings. XLS retains saved values, formulas, number formats, merges, and available row/column metadata; fonts, borders, and frozen panes are unsupported. Workbooks display saved formula results without recalculating; missing results remain blank, and a compact formula-bar warning marks workbooks whose displayed results may be incomplete or inaccurate. The workbook viewport follows preview pane size changes without reloading its sheets or selection. Spreadsheet preview does not call the Office conversion service. XLSX preview omits DrawingML parts from an in-memory copy before parsing and ignores worksheet drawing references. The original file and worksheet XML remain unchanged. A notice above the table lists detected charts, images, shapes, and conditional formatting that are not displayed, and recommends opening the workbook in a system application. Files without these detected features have no notice; formula warnings remain separate. diff --git a/packages/client/ui-sidebar-documentpreview/README.zh.md b/packages/client/ui-sidebar-documentpreview/README.zh.md index 18fe9e9461..559f6e337c 100644 --- a/packages/client/ui-sidebar-documentpreview/README.zh.md +++ b/packages/client/ui-sidebar-documentpreview/README.zh.md @@ -66,7 +66,7 @@ PNG、JPEG、GIF、WebP、BMP、ICO 和 SVG 通过 Blob URL 在 `` 静态 ## Excel 预览 -直接在浏览器中打开 `.xlsx`、`.xls`、`.csv` 和 `.tsv`,支持工作表标签、单元格选择、复制和只读公式栏。XLSX 保留字体、纯色填充、边框、数字格式、富文本、合并单元格、行列尺寸、隐藏行列及工作表,以及冻结标题。XLS 保留已保存的值、公式、数字格式、合并及可用的行列元数据;不支持字体、边框和冻结窗格。工作簿显示已保存的公式结果而不重新计算;缺少的结果保持为空,公式栏旁的紧凑提示会标记显示结果可能不完整或不准确的工作簿。表格预览不调用 Office 转换服务。 +直接在浏览器中打开 `.xlsx`、`.xls`、`.csv` 和 `.tsv`,支持工作表标签、单元格选择、复制和只读公式栏。XLSX 保留字体、纯色填充、边框、数字格式、富文本、合并单元格、行列尺寸、隐藏行列及工作表,以及冻结标题。XLS 保留已保存的值、公式、数字格式、合并及可用的行列元数据;不支持字体、边框和冻结窗格。工作簿显示已保存的公式结果而不重新计算;缺少的结果保持为空,公式栏旁的紧凑提示会标记显示结果可能不完整或不准确的工作簿。工作簿视图随预览面板尺寸变化自动调整,无需重新加载工作表或选择状态。表格预览不调用 Office 转换服务。 XLSX 预览在解析前从内存副本中移除 DrawingML 部件,并忽略工作表的绘图引用。原文件和工作表 XML 保持不变。表格上方的提示列出实际检测到但未展示的图表、图片、形状和条件格式,并建议使用系统应用打开工作簿。未检测到这些内容的文件不显示此提示;公式提示保持独立。 diff --git a/packages/client/ui-sidebar-documentpreview/src/client/excel/excel.tsx b/packages/client/ui-sidebar-documentpreview/src/client/excel/excel.tsx index b8bbb89159..0e1b67da4b 100644 --- a/packages/client/ui-sidebar-documentpreview/src/client/excel/excel.tsx +++ b/packages/client/ui-sidebar-documentpreview/src/client/excel/excel.tsx @@ -1,5 +1,5 @@ /** Read-only spreadsheet surface backed by browser-parsed workbook data. */ -import { useEffect, useState, type ReactNode } from 'react' +import { useEffect, useRef, useState, type ReactNode } from 'react' import { Workbook } from '@fortune-sheet/react' import { Button, IconWarningTriangleOutlineRegular, StateDot, Tooltip } from '@deepseek-ai/dsh-client-ui-primitives' import fortuneCss from '@fortune-sheet/react/dist/index.css?inline' @@ -14,6 +14,7 @@ const scopedStyles = `@scope ([data-excel-preview]) { ${fortuneCss} }` /** * Display stored spreadsheet values and formats without editing or recalculation. + * Keep the mounted workbook sized to its preview pane. * @param props - Complete workbook bytes, limits, and locale. * @returns An isolated spreadsheet surface with cancellable loading. */ @@ -21,6 +22,7 @@ export function ExcelBody({ content, format, limits, t }: LoadedExcelBodyProps): const data = content.kind === 'bytes' ? content.data : undefined const [state, setState] = useState() const [attempt, setAttempt] = useState(0) + const workbookRef = useRef(null) useEffect(() => { if (data === undefined) return const controller = new AbortController() @@ -31,6 +33,14 @@ export function ExcelBody({ content, format, limits, t }: LoadedExcelBodyProps): ) return () => { controller.abort() } }, [data, format, limits, attempt]) + useEffect(() => { + const element = workbookRef.current + if (element === null || typeof ResizeObserver === 'undefined') return + // FortuneSheet measures its canvas on window resize, but pane resizing does not emit that event. + const observer = new ResizeObserver(() => { window.dispatchEvent(new Event('resize')) }) + observer.observe(element) + return () => { observer.disconnect() } + }, [state]) if (data === undefined) return

{t('invalid')}

if (state?.data !== data || state.format !== format) return @@ -46,7 +56,7 @@ export function ExcelBody({ content, format, limits, t }: LoadedExcelBodyProps): {t('unsupportedNotice', { features: state.value.unsupportedFeatures.map(feature => t(feature)).join(t('featureSeparator')) })}
} -
+
{hasFormulas &&