feat(python-sdk): launch dsh profiles from explicit homes
Replace complete-config, session_root, runtime-bin, bridge-bin, and public argv override options with dsh_bin, profile, ordered patches, and dsh_home. Resolve executable/home/patch/cwd paths before spawn, select the sdk profile by default, and fail before launch unless dsh_home or non-empty DSH_HOME is explicit; Python never inherits ~/.dsh silently.
Remove Python-owned DSH_CORDIS_CONFIG, DSH_SESSION_ROOT, and DSH_CWD injection and drop session_root from RunResult. Keep arbitrary argv only as an underscore-prefixed fake-runtime adapter, retain provider/model/token and process controls, and append subprocess stderr to initialization JSON-RPC errors so profile boot failures name their actual plugin cause. Unit and carrier tests cover both exe and Node modes.
2026-08-23 14:56:16 +08:00
|
|
|
"""Keyless boot tests for the production exe and development dsh carrier.
|
2026-07-14 00:40:36 +08:00
|
|
|
|
|
|
|
|
Each carrier skips independently when absent. The dummy API key only satisfies
|
|
|
|
|
adapter loading; initialize and shutdown do not call a model.
|
2026-07-11 14:08:24 +08:00
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
feat(python-sdk): launch dsh profiles from explicit homes
Replace complete-config, session_root, runtime-bin, bridge-bin, and public argv override options with dsh_bin, profile, ordered patches, and dsh_home. Resolve executable/home/patch/cwd paths before spawn, select the sdk profile by default, and fail before launch unless dsh_home or non-empty DSH_HOME is explicit; Python never inherits ~/.dsh silently.
Remove Python-owned DSH_CORDIS_CONFIG, DSH_SESSION_ROOT, and DSH_CWD injection and drop session_root from RunResult. Keep arbitrary argv only as an underscore-prefixed fake-runtime adapter, retain provider/model/token and process controls, and append subprocess stderr to initialization JSON-RPC errors so profile boot failures name their actual plugin cause. Unit and carrier tests cover both exe and Node modes.
2026-08-23 14:56:16 +08:00
|
|
|
import json
|
2026-07-11 14:08:24 +08:00
|
|
|
from pathlib import Path
|
|
|
|
|
|
|
|
|
|
import pytest
|
|
|
|
|
|
|
|
|
|
from deepseek_harness import DeepSeekHarness, HarnessClient, HarnessConfig
|
feat(python-sdk): launch dsh profiles from explicit homes
Replace complete-config, session_root, runtime-bin, bridge-bin, and public argv override options with dsh_bin, profile, ordered patches, and dsh_home. Resolve executable/home/patch/cwd paths before spawn, select the sdk profile by default, and fail before launch unless dsh_home or non-empty DSH_HOME is explicit; Python never inherits ~/.dsh silently.
Remove Python-owned DSH_CORDIS_CONFIG, DSH_SESSION_ROOT, and DSH_CWD injection and drop session_root from RunResult. Keep arbitrary argv only as an underscore-prefixed fake-runtime adapter, retain provider/model/token and process controls, and append subprocess stderr to initialization JSON-RPC errors so profile boot failures name their actual plugin cause. Unit and carrier tests cover both exe and Node modes.
2026-08-23 14:56:16 +08:00
|
|
|
from deepseek_harness.errors import JsonRpcError, TransportClosedError
|
|
|
|
|
from deepseek_harness_runtime import RUNTIME_MODE_ENV_VAR, resolve_bundled_launch_args
|
2026-07-11 14:08:24 +08:00
|
|
|
|
|
|
|
|
_MODES = ("exe", "node")
|
|
|
|
|
|
|
|
|
|
|
feat(python-sdk): launch dsh profiles from explicit homes
Replace complete-config, session_root, runtime-bin, bridge-bin, and public argv override options with dsh_bin, profile, ordered patches, and dsh_home. Resolve executable/home/patch/cwd paths before spawn, select the sdk profile by default, and fail before launch unless dsh_home or non-empty DSH_HOME is explicit; Python never inherits ~/.dsh silently.
Remove Python-owned DSH_CORDIS_CONFIG, DSH_SESSION_ROOT, and DSH_CWD injection and drop session_root from RunResult. Keep arbitrary argv only as an underscore-prefixed fake-runtime adapter, retain provider/model/token and process controls, and append subprocess stderr to initialization JSON-RPC errors so profile boot failures name their actual plugin cause. Unit and carrier tests cover both exe and Node modes.
2026-08-23 14:56:16 +08:00
|
|
|
def _select_mode(mode: str, monkeypatch: pytest.MonkeyPatch) -> None:
|
2026-07-11 14:08:24 +08:00
|
|
|
try:
|
feat(python-sdk): launch dsh profiles from explicit homes
Replace complete-config, session_root, runtime-bin, bridge-bin, and public argv override options with dsh_bin, profile, ordered patches, and dsh_home. Resolve executable/home/patch/cwd paths before spawn, select the sdk profile by default, and fail before launch unless dsh_home or non-empty DSH_HOME is explicit; Python never inherits ~/.dsh silently.
Remove Python-owned DSH_CORDIS_CONFIG, DSH_SESSION_ROOT, and DSH_CWD injection and drop session_root from RunResult. Keep arbitrary argv only as an underscore-prefixed fake-runtime adapter, retain provider/model/token and process controls, and append subprocess stderr to initialization JSON-RPC errors so profile boot failures name their actual plugin cause. Unit and carrier tests cover both exe and Node modes.
2026-08-23 14:56:16 +08:00
|
|
|
resolve_bundled_launch_args(mode)
|
2026-07-11 14:08:24 +08:00
|
|
|
except FileNotFoundError as exc:
|
|
|
|
|
pytest.skip(f"bundled {mode}-mode runtime unavailable on this machine: {exc}")
|
feat(python-sdk): launch dsh profiles from explicit homes
Replace complete-config, session_root, runtime-bin, bridge-bin, and public argv override options with dsh_bin, profile, ordered patches, and dsh_home. Resolve executable/home/patch/cwd paths before spawn, select the sdk profile by default, and fail before launch unless dsh_home or non-empty DSH_HOME is explicit; Python never inherits ~/.dsh silently.
Remove Python-owned DSH_CORDIS_CONFIG, DSH_SESSION_ROOT, and DSH_CWD injection and drop session_root from RunResult. Keep arbitrary argv only as an underscore-prefixed fake-runtime adapter, retain provider/model/token and process controls, and append subprocess stderr to initialization JSON-RPC errors so profile boot failures name their actual plugin cause. Unit and carrier tests cover both exe and Node modes.
2026-08-23 14:56:16 +08:00
|
|
|
monkeypatch.setenv(RUNTIME_MODE_ENV_VAR, mode)
|
2026-07-11 14:08:24 +08:00
|
|
|
|
|
|
|
|
|
feat(python-sdk): launch dsh profiles from explicit homes
Replace complete-config, session_root, runtime-bin, bridge-bin, and public argv override options with dsh_bin, profile, ordered patches, and dsh_home. Resolve executable/home/patch/cwd paths before spawn, select the sdk profile by default, and fail before launch unless dsh_home or non-empty DSH_HOME is explicit; Python never inherits ~/.dsh silently.
Remove Python-owned DSH_CORDIS_CONFIG, DSH_SESSION_ROOT, and DSH_CWD injection and drop session_root from RunResult. Keep arbitrary argv only as an underscore-prefixed fake-runtime adapter, retain provider/model/token and process controls, and append subprocess stderr to initialization JSON-RPC errors so profile boot failures name their actual plugin cause. Unit and carrier tests cover both exe and Node modes.
2026-08-23 14:56:16 +08:00
|
|
|
def _client(tmp_path: Path, mode: str, monkeypatch: pytest.MonkeyPatch, *patches: Path) -> HarnessClient:
|
|
|
|
|
_select_mode(mode, monkeypatch)
|
2026-07-11 14:08:24 +08:00
|
|
|
return HarnessClient(
|
|
|
|
|
HarnessConfig(
|
feat(python-sdk): launch dsh profiles from explicit homes
Replace complete-config, session_root, runtime-bin, bridge-bin, and public argv override options with dsh_bin, profile, ordered patches, and dsh_home. Resolve executable/home/patch/cwd paths before spawn, select the sdk profile by default, and fail before launch unless dsh_home or non-empty DSH_HOME is explicit; Python never inherits ~/.dsh silently.
Remove Python-owned DSH_CORDIS_CONFIG, DSH_SESSION_ROOT, and DSH_CWD injection and drop session_root from RunResult. Keep arbitrary argv only as an underscore-prefixed fake-runtime adapter, retain provider/model/token and process controls, and append subprocess stderr to initialization JSON-RPC errors so profile boot failures name their actual plugin cause. Unit and carrier tests cover both exe and Node modes.
2026-08-23 14:56:16 +08:00
|
|
|
dsh_home=str(tmp_path / "home"),
|
|
|
|
|
patches=tuple(str(patch) for patch in patches),
|
2026-07-11 14:08:24 +08:00
|
|
|
cwd=str(tmp_path),
|
|
|
|
|
env={
|
2026-07-14 00:40:36 +08:00
|
|
|
# The lazily mounted adapter requires a key even without a model call.
|
2026-07-11 14:08:24 +08:00
|
|
|
"DEEPSEEK_API_KEY": "sk-dummy-for-boot",
|
|
|
|
|
"DEEPSEEK_BASE_URL": "http://127.0.0.1:9",
|
feat(python-sdk): launch dsh profiles from explicit homes
Replace complete-config, session_root, runtime-bin, bridge-bin, and public argv override options with dsh_bin, profile, ordered patches, and dsh_home. Resolve executable/home/patch/cwd paths before spawn, select the sdk profile by default, and fail before launch unless dsh_home or non-empty DSH_HOME is explicit; Python never inherits ~/.dsh silently.
Remove Python-owned DSH_CORDIS_CONFIG, DSH_SESSION_ROOT, and DSH_CWD injection and drop session_root from RunResult. Keep arbitrary argv only as an underscore-prefixed fake-runtime adapter, retain provider/model/token and process controls, and append subprocess stderr to initialization JSON-RPC errors so profile boot failures name their actual plugin cause. Unit and carrier tests cover both exe and Node modes.
2026-08-23 14:56:16 +08:00
|
|
|
"DSH_PERMISSION_MODE": "danger-full-access",
|
|
|
|
|
"DSH_TELEMETRY_DISABLED": "1",
|
2026-07-11 14:08:24 +08:00
|
|
|
},
|
|
|
|
|
request_timeout_seconds=120,
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize("mode", _MODES)
|
feat(python-sdk): launch dsh profiles from explicit homes
Replace complete-config, session_root, runtime-bin, bridge-bin, and public argv override options with dsh_bin, profile, ordered patches, and dsh_home. Resolve executable/home/patch/cwd paths before spawn, select the sdk profile by default, and fail before launch unless dsh_home or non-empty DSH_HOME is explicit; Python never inherits ~/.dsh silently.
Remove Python-owned DSH_CORDIS_CONFIG, DSH_SESSION_ROOT, and DSH_CWD injection and drop session_root from RunResult. Keep arbitrary argv only as an underscore-prefixed fake-runtime adapter, retain provider/model/token and process controls, and append subprocess stderr to initialization JSON-RPC errors so profile boot failures name their actual plugin cause. Unit and carrier tests cover both exe and Node modes.
2026-08-23 14:56:16 +08:00
|
|
|
def test_bundled_runtime_boots_the_sdk_profile(
|
|
|
|
|
tmp_path: Path, mode: str, monkeypatch: pytest.MonkeyPatch
|
|
|
|
|
) -> None:
|
|
|
|
|
with _client(tmp_path, mode, monkeypatch) as client:
|
2026-07-29 16:36:07 +08:00
|
|
|
init = client.initialize(provider="deepseek-official", cwd=str(tmp_path), model="deepseek-v4-pro")
|
2026-07-11 14:08:24 +08:00
|
|
|
|
|
|
|
|
assert init.serverInfo is not None
|
|
|
|
|
assert init.serverInfo.name == "deepseek-harness-sdk-runtime"
|
feat(python-sdk): launch dsh profiles from explicit homes
Replace complete-config, session_root, runtime-bin, bridge-bin, and public argv override options with dsh_bin, profile, ordered patches, and dsh_home. Resolve executable/home/patch/cwd paths before spawn, select the sdk profile by default, and fail before launch unless dsh_home or non-empty DSH_HOME is explicit; Python never inherits ~/.dsh silently.
Remove Python-owned DSH_CORDIS_CONFIG, DSH_SESSION_ROOT, and DSH_CWD injection and drop session_root from RunResult. Keep arbitrary argv only as an underscore-prefixed fake-runtime adapter, retain provider/model/token and process controls, and append subprocess stderr to initialization JSON-RPC errors so profile boot failures name their actual plugin cause. Unit and carrier tests cover both exe and Node modes.
2026-08-23 14:56:16 +08:00
|
|
|
profile = json.loads((tmp_path / "home" / "profiles" / "sdk" / "package.json").read_text())
|
|
|
|
|
assert profile["dsh"]["profile"]["bundles"] == [
|
|
|
|
|
"@deepseek-ai/dsh-base",
|
|
|
|
|
"@deepseek-ai/dsh-sdk-app",
|
|
|
|
|
]
|
2026-07-11 14:08:24 +08:00
|
|
|
|
|
|
|
|
|
2026-08-11 15:19:24 +08:00
|
|
|
@pytest.mark.parametrize("mode", _MODES)
|
feat(python-sdk): launch dsh profiles from explicit homes
Replace complete-config, session_root, runtime-bin, bridge-bin, and public argv override options with dsh_bin, profile, ordered patches, and dsh_home. Resolve executable/home/patch/cwd paths before spawn, select the sdk profile by default, and fail before launch unless dsh_home or non-empty DSH_HOME is explicit; Python never inherits ~/.dsh silently.
Remove Python-owned DSH_CORDIS_CONFIG, DSH_SESSION_ROOT, and DSH_CWD injection and drop session_root from RunResult. Keep arbitrary argv only as an underscore-prefixed fake-runtime adapter, retain provider/model/token and process controls, and append subprocess stderr to initialization JSON-RPC errors so profile boot failures name their actual plugin cause. Unit and carrier tests cover both exe and Node modes.
2026-08-23 14:56:16 +08:00
|
|
|
def test_python_sdk_applies_an_ordered_profile_patch(
|
|
|
|
|
tmp_path: Path, mode: str, monkeypatch: pytest.MonkeyPatch
|
|
|
|
|
) -> None:
|
|
|
|
|
_select_mode(mode, monkeypatch)
|
|
|
|
|
patch = tmp_path / "persona.patch.yml"
|
|
|
|
|
patch.write_text(json.dumps([{
|
|
|
|
|
"id": "system-prompt",
|
|
|
|
|
"config": {"persona": "Python SDK ordered patch marker."},
|
|
|
|
|
}]))
|
2026-08-11 15:19:24 +08:00
|
|
|
harness = DeepSeekHarness(
|
feat(python-sdk): launch dsh profiles from explicit homes
Replace complete-config, session_root, runtime-bin, bridge-bin, and public argv override options with dsh_bin, profile, ordered patches, and dsh_home. Resolve executable/home/patch/cwd paths before spawn, select the sdk profile by default, and fail before launch unless dsh_home or non-empty DSH_HOME is explicit; Python never inherits ~/.dsh silently.
Remove Python-owned DSH_CORDIS_CONFIG, DSH_SESSION_ROOT, and DSH_CWD injection and drop session_root from RunResult. Keep arbitrary argv only as an underscore-prefixed fake-runtime adapter, retain provider/model/token and process controls, and append subprocess stderr to initialization JSON-RPC errors so profile boot failures name their actual plugin cause. Unit and carrier tests cover both exe and Node modes.
2026-08-23 14:56:16 +08:00
|
|
|
model="deepseek-v4-pro",
|
2026-08-11 15:19:24 +08:00
|
|
|
cwd=str(tmp_path),
|
feat(python-sdk): launch dsh profiles from explicit homes
Replace complete-config, session_root, runtime-bin, bridge-bin, and public argv override options with dsh_bin, profile, ordered patches, and dsh_home. Resolve executable/home/patch/cwd paths before spawn, select the sdk profile by default, and fail before launch unless dsh_home or non-empty DSH_HOME is explicit; Python never inherits ~/.dsh silently.
Remove Python-owned DSH_CORDIS_CONFIG, DSH_SESSION_ROOT, and DSH_CWD injection and drop session_root from RunResult. Keep arbitrary argv only as an underscore-prefixed fake-runtime adapter, retain provider/model/token and process controls, and append subprocess stderr to initialization JSON-RPC errors so profile boot failures name their actual plugin cause. Unit and carrier tests cover both exe and Node modes.
2026-08-23 14:56:16 +08:00
|
|
|
dsh_home=str(tmp_path / "home"),
|
|
|
|
|
patches=(str(patch),),
|
|
|
|
|
env={"DSH_PERMISSION_MODE": "danger-full-access"},
|
2026-08-11 15:19:24 +08:00
|
|
|
api_key="sk-dummy-for-boot",
|
|
|
|
|
base_url="http://127.0.0.1:9",
|
|
|
|
|
request_timeout_seconds=120,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
with harness:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
2026-07-11 14:08:24 +08:00
|
|
|
@pytest.mark.parametrize("mode", _MODES)
|
feat(python-sdk): launch dsh profiles from explicit homes
Replace complete-config, session_root, runtime-bin, bridge-bin, and public argv override options with dsh_bin, profile, ordered patches, and dsh_home. Resolve executable/home/patch/cwd paths before spawn, select the sdk profile by default, and fail before launch unless dsh_home or non-empty DSH_HOME is explicit; Python never inherits ~/.dsh silently.
Remove Python-owned DSH_CORDIS_CONFIG, DSH_SESSION_ROOT, and DSH_CWD injection and drop session_root from RunResult. Keep arbitrary argv only as an underscore-prefixed fake-runtime adapter, retain provider/model/token and process controls, and append subprocess stderr to initialization JSON-RPC errors so profile boot failures name their actual plugin cause. Unit and carrier tests cover both exe and Node modes.
2026-08-23 14:56:16 +08:00
|
|
|
def test_bundled_runtime_surfaces_unbundled_plugin_failure(
|
|
|
|
|
tmp_path: Path, mode: str, monkeypatch: pytest.MonkeyPatch
|
|
|
|
|
) -> None:
|
|
|
|
|
patch = tmp_path / "missing.patch.yml"
|
|
|
|
|
patch.write_text(json.dumps([{
|
|
|
|
|
"insert": [{"id": "missing", "name": "@deepseek-ai/dsh-does-not-exist"}],
|
|
|
|
|
}]))
|
2026-07-11 14:08:24 +08:00
|
|
|
|
feat(python-sdk): launch dsh profiles from explicit homes
Replace complete-config, session_root, runtime-bin, bridge-bin, and public argv override options with dsh_bin, profile, ordered patches, and dsh_home. Resolve executable/home/patch/cwd paths before spawn, select the sdk profile by default, and fail before launch unless dsh_home or non-empty DSH_HOME is explicit; Python never inherits ~/.dsh silently.
Remove Python-owned DSH_CORDIS_CONFIG, DSH_SESSION_ROOT, and DSH_CWD injection and drop session_root from RunResult. Keep arbitrary argv only as an underscore-prefixed fake-runtime adapter, retain provider/model/token and process controls, and append subprocess stderr to initialization JSON-RPC errors so profile boot failures name their actual plugin cause. Unit and carrier tests cover both exe and Node modes.
2026-08-23 14:56:16 +08:00
|
|
|
client = _client(tmp_path, mode, monkeypatch, patch)
|
2026-07-11 14:08:24 +08:00
|
|
|
client.start()
|
|
|
|
|
try:
|
feat(python-sdk): launch dsh profiles from explicit homes
Replace complete-config, session_root, runtime-bin, bridge-bin, and public argv override options with dsh_bin, profile, ordered patches, and dsh_home. Resolve executable/home/patch/cwd paths before spawn, select the sdk profile by default, and fail before launch unless dsh_home or non-empty DSH_HOME is explicit; Python never inherits ~/.dsh silently.
Remove Python-owned DSH_CORDIS_CONFIG, DSH_SESSION_ROOT, and DSH_CWD injection and drop session_root from RunResult. Keep arbitrary argv only as an underscore-prefixed fake-runtime adapter, retain provider/model/token and process controls, and append subprocess stderr to initialization JSON-RPC errors so profile boot failures name their actual plugin cause. Unit and carrier tests cover both exe and Node modes.
2026-08-23 14:56:16 +08:00
|
|
|
with pytest.raises((JsonRpcError, TransportClosedError, TimeoutError)) as excinfo:
|
2026-07-29 16:36:07 +08:00
|
|
|
client.initialize(provider="deepseek-official", cwd=str(tmp_path), model="deepseek-v4-pro")
|
2026-07-11 14:08:24 +08:00
|
|
|
finally:
|
|
|
|
|
client.close()
|
|
|
|
|
|
|
|
|
|
assert "@deepseek-ai/dsh-does-not-exist" in str(excinfo.value)
|