deepseek-harness/python/sdk/tests/test_bundled_runtime.py

117 lines
3.8 KiB
Python
Raw Normal View History

"""Keyless boot tests for the production exe and development node carrier.
Each carrier skips independently when absent. The dummy API key only satisfies
adapter loading; initialize and shutdown do not call a model.
"""
from __future__ import annotations
from pathlib import Path
import pytest
from deepseek_harness import DeepSeekHarness, HarnessClient, HarnessConfig
from deepseek_harness.errors import TransportClosedError
from deepseek_harness_runtime import resolve_bundled_launch_args
_MODES = ("exe", "node")
# The config must include the JSON-RPC serving plugin.
_CORDIS_YML = """\
- id: jsonrpc
name: '@deepseek-ai/dsh-jsonrpc'
- id: agent-core
name: '@deepseek-ai/dsh-agent-spine-demo'
Merge remote-tracking branch 'origin/master' into codex/project-instruction-files # Conflicts: # AGENTS.md # docs/config-catalog.md # docs/cordis-catalog/events.md # docs/cordis-catalog/services.md # docs/core-data-structures/core.md # docs/event-producer-consumer.md # docs/persistence-catalog.md # docs/rfc/implemented/architecture/2026-07-05-reconstructable-requests.md # docs/rfc/implemented/feature/2026-06-15-code-mode.md # docs/rfc/implemented/feature/2026-06-30-hook-bridges.md # docs/rfc/implemented/feature/2026-06-30-interception-seams.md # docs/rfc/implemented/feature/2026-07-08-repeat-tool-guard.md # docs/rfc/proposed/simplification/2026-07-04-prune-dead-core-spine-surface.md # examples/AGENTS.md # examples/acp-agent/cordis.yml # examples/acp-agent/tests/acp.snapshot.ts # examples/echo-agent/cordis.yml # examples/sandbox-acp-agent/cordis.yml # packages/cordis/tool-cordis/src/api-catalog.ts # packages/core/agent-core/README.md # packages/core/agent-core/src/index.ts # packages/core/agent-loop/README.md # packages/core/agent-loop/src/loop.ts # packages/core/agent-loop/tests/interception.spec.ts # packages/core/agent/src/types.ts # packages/core/tools/README.md # packages/core/tools/src/code-mode.ts # packages/core/tools/src/index.ts # packages/fs/fs-local/src/index.ts # packages/fs/fs/README.md # packages/fs/fs/src/index.ts # packages/guard/repeat-tool-guard/README.md # packages/guard/repeat-tool-guard/src/index.ts # packages/hooks/hooks-claude/src/index.ts # packages/hooks/hooks-codex/src/index.ts # packages/ui/acp-agent/src/index.ts
2026-07-14 19:50:25 +08:00
config:
workspaceContext: false
- id: sessions
name: '@deepseek-ai/dsh-session-persistence-jsonl'
config:
root: './sessions'
- id: bash
name: '@deepseek-ai/dsh-bash-local'
config:
cwd: '.'
- id: todo
name: '@deepseek-ai/dsh-tool-todo'
"""
def _launch_args(mode: str) -> tuple[str, ...]:
try:
return resolve_bundled_launch_args(mode)
except FileNotFoundError as exc:
pytest.skip(f"bundled {mode}-mode runtime unavailable on this machine: {exc}")
def _client(tmp_path: Path, launch_args: tuple[str, ...]) -> HarnessClient:
return HarnessClient(
HarnessConfig(
launch_args_override=launch_args,
cwd=str(tmp_path),
env={
"DSH_CORDIS_CONFIG": "./cordis.yml",
"DSH_SESSION_ROOT": str(tmp_path / "sessions"),
"DSH_CWD": str(tmp_path),
# The lazily mounted adapter requires a key even without a model call.
"DEEPSEEK_API_KEY": "sk-dummy-for-boot",
"DEEPSEEK_BASE_URL": "http://127.0.0.1:9",
},
request_timeout_seconds=120,
)
)
@pytest.mark.parametrize("mode", _MODES)
def test_bundled_runtime_boots_a_cordis_config(tmp_path: Path, mode: str) -> None:
launch_args = _launch_args(mode)
(tmp_path / "cordis.yml").write_text(_CORDIS_YML)
with _client(tmp_path, launch_args) as client:
2026-07-14 21:57:52 +08:00
init = client.initialize(provider="deepseek", cwd=str(tmp_path), model="deepseek-v4-pro")
assert init.serverInfo is not None
assert init.serverInfo.name == "deepseek-harness-sdk-runtime"
@pytest.mark.parametrize("mode", _MODES)
def test_bundled_runtime_surfaces_unbundled_plugin_failure(tmp_path: Path, mode: str) -> None:
launch_args = _launch_args(mode)
(tmp_path / "cordis.yml").write_text(
"- id: missing\n name: '@deepseek-ai/dsh-does-not-exist'\n"
)
client = _client(tmp_path, launch_args)
client.start()
try:
with pytest.raises((TransportClosedError, TimeoutError)) as excinfo:
2026-07-14 21:57:52 +08:00
client.initialize(provider="deepseek", cwd=str(tmp_path), model="deepseek-v4-pro")
finally:
client.close()
assert "@deepseek-ai/dsh-does-not-exist" in str(excinfo.value)
@pytest.mark.parametrize("mode", _MODES)
@pytest.mark.parametrize("ambient_config", [None, ""], ids=["unset", "empty-counts-as-absent"])
def test_zero_config_run_injects_bundled_default_cordis_config(
tmp_path: Path, mode: str, ambient_config: str | None, monkeypatch: pytest.MonkeyPatch
) -> None:
_launch_args(mode) # skip early when this carrier is unavailable
monkeypatch.setenv("DSH_RUNTIME_MODE", mode)
if ambient_config is None:
monkeypatch.delenv("DSH_CORDIS_CONFIG", raising=False)
else:
monkeypatch.setenv("DSH_CORDIS_CONFIG", ambient_config)
harness = DeepSeekHarness(
model="deepseek-v4-pro",
cwd=str(tmp_path),
session_root=str(tmp_path / "sessions"),
api_key="sk-dummy-for-boot",
base_url="http://127.0.0.1:9",
request_timeout_seconds=120,
)
with harness:
pass