fix(document): select Office engines from declared native targets

This commit is contained in:
yudshj committed 2026-09-16 14:55:38 +08:00
1 parent fd3cdf539b
commit fcf9f4cfa2
39 files changed
+187 -90

No files matched your search

+2 -2
View File
@@ -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 python/sdk-runtime/README.md
README.md: ba1814ce00dea9dd35bcfbb330801942b86af155
README.zh.md: 792c7e06a29be987a25887882b6df976138b194f
README.md: adb2fb71c3893d9360d7593826fdca609f770b6e
README.zh.md: a4decd5040ada700e84b0f1b3bacba7bbec8a56f
+1 -1
View File
@@ -39,4 +39,4 @@ Production deployment permits unused workspace patches for packages outside the
From the repository root, `pnpm exec tsx scripts/build-exe-for-python-sdk.ts` verifies the closure, builds packages, deploys a symlink-free tree, packages the selected target, and syncs the executable and sidecars into this module. `scripts/build-python-release.py` stages release-shaped wheels at the root repository version and pins `deepseek-harness-sdk` to the exact runtime version.
The installed-wheel smoke creates a clean virtual environment outside the checkout, proves the installed distribution and executable identities, then exercises default and customized SDK profiles, external plugins, MCP, native tools, direct JSON-RPC, committed snapshots, and the real provider on trusted runs. Its Office scenario relocates the complete target payload and converts DOCX with the required platform engine: native on macOS/Windows and WASM on Linux. See the [Python contributor workflow](../development.md) and [installed-wheel testing decision](../../.agents/notes/implemented/testing/2026-08-23-installed-python-wheel-black-box-ci.md).
The installed-wheel smoke creates a clean virtual environment outside the checkout, proves the installed distribution and executable identities, then exercises default and customized SDK profiles, external plugins, MCP, native tools, direct JSON-RPC, committed snapshots, and the real provider on trusted runs. Its Office scenario relocates the complete target payload and converts DOCX with the required platform engine: the target’s declared native engine, or WASM when no native engine is declared. See the [Python contributor workflow](../development.md) and [installed-wheel testing decision](../../.agents/notes/implemented/testing/2026-08-23-installed-python-wheel-black-box-ci.md).
+1 -1
View File
@@ -39,4 +39,4 @@ Python bootstrap 从相邻目录解析 Office kit,让原生辅助程序与 URL
在仓库根目录运行 `pnpm exec tsx scripts/build-exe-for-python-sdk.ts`,会校验闭包、构建包、部署无符号链接的文件树、打包所选目标,并把可执行程序及伴随文件同步到本模块。`scripts/build-python-release.py` 按仓库根版本暂存发布形态的 wheel 包,并将 `deepseek-harness-sdk` 固定到完全相同的运行时版本。
已安装 wheel 包冒烟测试会在检出目录外创建干净的虚拟环境,验证分发物与可执行程序的来源,然后覆盖默认及自定义 SDK profile、外部插件、MCP、原生工具、直接 JSON-RPC、检入快照,以及可信运行中的真实提供方。Office 场景会迁移完整的目标载荷目录,并使用所需的平台引擎转换 DOCX:macOS/Windows 使用原生引擎,Linux 使用 WASM。另见 [Python 贡献者工作流](../development.zh.md) 与 [installed-wheel 测试决策](../../.agents/notes/implemented/testing/2026-08-23-installed-python-wheel-black-box-ci.zh.md)。
已安装 wheel 包冒烟测试会在检出目录外创建干净的虚拟环境,验证分发物与可执行程序的来源,然后覆盖默认及自定义 SDK profile、外部插件、MCP、原生工具、直接 JSON-RPC、检入快照,以及可信运行中的真实提供方。Office 场景会迁移完整的目标载荷目录,并使用所需的平台引擎转换 DOCX:使用目标已声明的原生引擎,未声明原生引擎时使用 WASM。另见 [Python 贡献者工作流](../development.zh.md) 与 [installed-wheel 测试决策](../../.agents/notes/implemented/testing/2026-08-23-installed-python-wheel-black-box-ci.zh.md)。
+9 -4
View File
@@ -74,7 +74,6 @@ class RuntimeBuildHook(BuildHookInterface):
)
expected_executable = matches[0][1]
target = next(name for name, value in _PLATFORMS.items() if value[0] == platform_tag)
engine = "wasm" if target.startswith("linux-") else target.replace("win-", "win32-").replace("macos-", "darwin-")
runtime_dir = Path(self.root) / "src" / "deepseek_harness_runtime" / "runtime"
runtime_files = sorted(
runtime_dir.glob("deepseek-harness-sdk-runtime-*") if runtime_dir.is_dir() else []
@@ -96,9 +95,15 @@ class RuntimeBuildHook(BuildHookInterface):
)
for executable in runtime_files:
if executable == office:
for required in ("@deepseek-ai/libreoffice-kit/package.json", f"@deepseek-ai/libreoffice-kit-{engine}/prebuilds.json"):
if not (office / "node_modules" / required).is_file():
raise RuntimeError(f"runtime Office dependency is missing: {office / required}")
adapter = office / "node_modules/@deepseek-ai/libreoffice-kit/package.json"
if not adapter.is_file():
raise RuntimeError(f"runtime Office dependency is missing: {adapter}")
native = target.replace("win-", "win32-").replace("macos-", "darwin-")
declared = json.loads(adapter.read_text(encoding="utf-8")).get("optionalDependencies", {})
engine = native if f"@deepseek-ai/libreoffice-kit-{native}" in declared else "wasm"
required = office / "node_modules" / f"@deepseek-ai/libreoffice-kit-{engine}/prebuilds.json"
if not required.is_file():
raise RuntimeError(f"runtime Office dependency is missing: {required}")
continue
if not executable.is_file():
raise RuntimeError(f"runtime executable is not a file: {executable}")
@@ -21,6 +21,7 @@ console command requires ``DSH_HOME`` for the same reason.
from __future__ import annotations
import json
import os
import platform
import shutil
@@ -89,13 +90,20 @@ def bundled_runtime_path() -> Path:
+ _EXE_ACQUISITION_HINT
)
office = path.with_name(f"{path.name.removesuffix('.exe')}-office")
engine = "wasm" if tag.startswith("linux-") else tag.replace("win-", "win32-").replace("macos-", "darwin-")
for required in ("@deepseek-ai/libreoffice-kit/package.json", f"@deepseek-ai/libreoffice-kit-{engine}/prebuilds.json"):
if not (office / "node_modules" / required).is_file():
raise FileNotFoundError(
f"deepseek-harness-runtime-bin is missing the Office sidecar at {office}. "
+ _EXE_ACQUISITION_HINT
)
adapter = office / "node_modules/@deepseek-ai/libreoffice-kit/package.json"
if not adapter.is_file():
raise FileNotFoundError(
f"deepseek-harness-runtime-bin is missing the Office sidecar at {office}. "
+ _EXE_ACQUISITION_HINT
)
native = tag.replace("win-", "win32-").replace("macos-", "darwin-")
declared = json.loads(adapter.read_text(encoding="utf-8")).get("optionalDependencies", {})
engine = native if f"@deepseek-ai/libreoffice-kit-{native}" in declared else "wasm"
if not (office / "node_modules" / f"@deepseek-ai/libreoffice-kit-{engine}/prebuilds.json").is_file():
raise FileNotFoundError(
f"deepseek-harness-runtime-bin is missing the Office sidecar engine {engine} at {office}. "
+ _EXE_ACQUISITION_HINT
)
return path
+4 -1
View File
@@ -164,6 +164,7 @@ def test_stage_runtime_rejects_a_noncanonical_executable_name(tmp_path: Path) ->
@pytest.mark.parametrize("platform_tag,selected", [
("manylinux_2_28_x86_64", "wasm"), ("macosx_14_0_arm64", "darwin-arm64"),
("macosx_14_0_x86_64", "darwin-x64"), ("win_amd64", "win32-x64"),
("manylinux_2_28_x86_64", "linux-x64"), ("macosx_14_0_arm64", "wasm"),
])
@pytest.mark.parametrize("invalid", [None, "asset", "missing-engine", "foreign-engine", "helper-mode"])
def test_office_wheel_requires_only_target_engine(
@@ -177,7 +178,9 @@ def test_office_wheel_requires_only_target_engine(
engine = ({"kind": "native", "executable": "bin/helper"} if native else
{"kind": "wasm", "loader": "loader.cjs", "wasm": "engine.wasm", "data": "engine.data", "metadata": "fonts.json"})
with zipfile.ZipFile(wheel, "w") as archive:
archive.writestr(f"{root}/@deepseek-ai/libreoffice-kit/package.json", "{}")
archive.writestr(f"{root}/@deepseek-ai/libreoffice-kit/package.json", json.dumps({
"optionalDependencies": {f"@deepseek-ai/libreoffice-kit-{selected}": "0.0.1"},
}))
base = f"{root}/@deepseek-ai/libreoffice-kit-{selected}"
if invalid != "missing-engine":
archive.writestr(f"{base}/prebuilds.json", json.dumps({"engine": engine}))
+18 -6
View File
@@ -2,6 +2,7 @@
from __future__ import annotations
import json
import os
import subprocess
import sys
@@ -19,14 +20,19 @@ from deepseek_harness_runtime import (
)
def _office_sidecar(executable: Path) -> Path:
def _office_sidecar(executable: Path, native_targets: tuple[str, ...] = ("darwin-arm64", "darwin-x64", "win32-x64")) -> Path:
office = executable.with_name(f"{executable.name.removesuffix('.exe')}-office")
tag = executable.name.removeprefix("deepseek-harness-sdk-runtime-").removesuffix(".exe")
engine = "wasm" if tag.startswith("linux-") else tag.replace("win-", "win32-").replace("macos-", "darwin-")
native = tag.replace("win-", "win32-").replace("macos-", "darwin-")
engine = native if native in native_targets else "wasm"
for required in ("@deepseek-ai/libreoffice-kit/package.json", f"@deepseek-ai/libreoffice-kit-{engine}/prebuilds.json"):
path = office / "node_modules" / required
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text("{}")
adapter = office / "node_modules/@deepseek-ai/libreoffice-kit/package.json"
adapter.write_text(json.dumps({"optionalDependencies": {
f"@deepseek-ai/libreoffice-kit-{target}": "0.0.1" for target in (*native_targets, "wasm")
}}), encoding="utf-8")
return office
@@ -229,8 +235,14 @@ def test_windows_console_branch_preserves_real_child_io_and_completion(tmp_path:
assert sentinel.read_text() == "done"
@pytest.mark.parametrize("target", ["linux-x64", "linux-arm64", "macos-arm64", "macos-x64", "win-x64"])
def test_runtime_requires_its_platform_office_engine(tmp_path: Path, monkeypatch: pytest.MonkeyPatch, target: str) -> None:
@pytest.mark.parametrize("target,native_targets", [
("linux-x64", ()), ("linux-arm64", ()),
("macos-arm64", ("darwin-arm64",)), ("macos-x64", ("darwin-x64",)), ("win-x64", ("win32-x64",)),
("linux-x64", ("linux-x64",)), ("macos-arm64", ()),
])
def test_runtime_requires_its_platform_office_engine(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch, target: str, native_targets: tuple[str, ...],
) -> None:
extension = ".exe" if target.startswith("win-") else ""
executable = tmp_path / "runtime" / f"deepseek-harness-sdk-runtime-{target}{extension}"
executable.parent.mkdir()
@@ -238,13 +250,13 @@ def test_runtime_requires_its_platform_office_engine(tmp_path: Path, monkeypatch
executable.with_name(f"{executable.stem}-rg{extension}").touch()
if target.startswith("macos-"):
Path(f"{executable}-spawn-helper").touch()
office = _office_sidecar(executable)
office = _office_sidecar(executable, native_targets)
monkeypatch.setattr(runtime, "bundled_package_dir", lambda: tmp_path)
monkeypatch.setattr(runtime, "_current_platform_tag", lambda: target)
assert runtime.bundled_runtime_path() == executable
engine = next(office.glob("node_modules/@deepseek-ai/libreoffice-kit-*/prebuilds.json"))
engine.unlink()
foreign = office / "node_modules/@deepseek-ai" / ("libreoffice-kit-darwin-arm64" if target.startswith("linux-") else "libreoffice-kit-wasm") / "prebuilds.json"
foreign = office / "node_modules/@deepseek-ai" / ("libreoffice-kit-darwin-arm64" if engine.parent.name == "libreoffice-kit-wasm" else "libreoffice-kit-wasm") / "prebuilds.json"
foreign.parent.mkdir(parents=True, exist_ok=True)
foreign.write_text("{}")
with pytest.raises(FileNotFoundError, match="Office sidecar"):