mirror of
https://github.com/deepseek-ai/deepseek-harness
synced 2026-08-15 21:04:50 +00:00
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
This commit is contained in:
120
python/sdk/tests/manual_sdk_agent_smoke.py
Normal file
120
python/sdk/tests/manual_sdk_agent_smoke.py
Normal file
@@ -0,0 +1,120 @@
|
||||
"""Drive the repo-source JSON-RPC bin through the SDK and a keyless mock SSE server.
|
||||
|
||||
Requires ``pnpm install`` but no build. This manual test is not collected by
|
||||
pytest; run ``python tests/manual_sdk_agent_smoke.py``.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import shutil
|
||||
import tempfile
|
||||
import threading
|
||||
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
from deepseek_harness import DeepSeekHarness
|
||||
from deepseek_harness_runtime import bundled_default_config_path
|
||||
|
||||
|
||||
class MockCompletionHandler(BaseHTTPRequestHandler):
|
||||
requests: list[dict[str, Any]] = []
|
||||
|
||||
def do_POST(self) -> None:
|
||||
length = int(self.headers.get("content-length", "0"))
|
||||
body = self.rfile.read(length).decode("utf-8")
|
||||
self.requests.append({
|
||||
"path": self.path,
|
||||
"authorization": self.headers.get("authorization"),
|
||||
"body": json.loads(body),
|
||||
})
|
||||
self.send_response(200)
|
||||
self.send_header("content-type", "text/event-stream")
|
||||
self.end_headers()
|
||||
self.wfile.write(b'data: {"choices":[{"delta":{"role":"assistant","content":null,"reasoning_content":""}}]}\n\n')
|
||||
self.wfile.write(b'data: {"choices":[{"delta":{"content":"SDK runtime reached the configured HTTP model endpoint."}}]}\n\n')
|
||||
self.wfile.write(b'data: {"choices":[{"delta":{"content":""},"finish_reason":"stop"}],"usage":{"prompt_tokens":7,"completion_tokens":9}}\n\n')
|
||||
self.wfile.write(b"data: [DONE]\n\n")
|
||||
|
||||
def log_message(self, _format: str, *_args: object) -> None:
|
||||
return
|
||||
|
||||
|
||||
def run_smoke(repo_root: Path, keep_sessions: bool) -> None:
|
||||
session_root = Path(tempfile.mkdtemp(prefix="dsh-sdk-smoke-sessions-"))
|
||||
runtime_entry = repo_root / "packages/ui/jsonrpc-agent/src/bin.ts"
|
||||
server = ThreadingHTTPServer(("127.0.0.1", 0), MockCompletionHandler)
|
||||
thread = threading.Thread(target=server.serve_forever, name="mock-openai-compatible-server", daemon=True)
|
||||
thread.start()
|
||||
base_url = f"http://127.0.0.1:{server.server_address[1]}"
|
||||
|
||||
print(f"repo_root={repo_root}")
|
||||
print(f"session_root={session_root}")
|
||||
print(f"mock_base_url={base_url}")
|
||||
|
||||
try:
|
||||
with DeepSeekHarness(
|
||||
model="sdk-smoke-model",
|
||||
cwd=str(repo_root / "python/sdk"),
|
||||
runtime_cwd=str(repo_root),
|
||||
session_root=str(session_root),
|
||||
cordis=str(bundled_default_config_path()),
|
||||
launch_args_override=("node", "--import", "tsx", str(runtime_entry)),
|
||||
env={
|
||||
"DEEPSEEK_BASE_URL": base_url,
|
||||
"DEEPSEEK_API_KEY": "sdk-smoke-key",
|
||||
},
|
||||
request_timeout_seconds=20,
|
||||
shutdown_timeout_seconds=2,
|
||||
) as harness:
|
||||
result = harness.run(
|
||||
"Please reply with a short confirmation and do not call tools.",
|
||||
session_id="sdk-smoke-main",
|
||||
)
|
||||
print(f"turn_status={result.status}")
|
||||
print(f"final_response={result.final_response}")
|
||||
assert result.status == "ok", result
|
||||
assert "configured HTTP model endpoint" in result.final_response
|
||||
assert len(MockCompletionHandler.requests) == 1
|
||||
request = MockCompletionHandler.requests[0]
|
||||
print(json.dumps(request, ensure_ascii=False, indent=2)[:4000])
|
||||
assert request["authorization"] == "Bearer sdk-smoke-key"
|
||||
assert request["body"]["model"] == "sdk-smoke-model"
|
||||
|
||||
jsonl_files = sorted(session_root.rglob("*.jsonl"))
|
||||
assert jsonl_files, f"no jsonl sessions were written under {session_root}"
|
||||
print("session_jsonl_files:")
|
||||
for path in jsonl_files:
|
||||
print(f" {path} bytes={path.stat().st_size}")
|
||||
with path.open("r", encoding="utf-8") as handle:
|
||||
first_line = handle.readline().strip()
|
||||
if first_line:
|
||||
print(f" first_line={first_line[:500]}")
|
||||
finally:
|
||||
server.shutdown()
|
||||
server.server_close()
|
||||
|
||||
if keep_sessions:
|
||||
print(f"kept_session_root={session_root}")
|
||||
else:
|
||||
shutil.rmtree(session_root)
|
||||
print("removed temporary session root")
|
||||
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument(
|
||||
"--repo-root",
|
||||
type=Path,
|
||||
default=Path(__file__).resolve().parents[3],
|
||||
help="Path to the deepseek-harness checkout.",
|
||||
)
|
||||
parser.add_argument("--keep-sessions", action="store_true")
|
||||
args = parser.parse_args()
|
||||
run_smoke(args.repo_root.resolve(), args.keep_sessions)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
116
python/sdk/tests/test_bundled_runtime.py
Normal file
116
python/sdk/tests/test_bundled_runtime.py
Normal file
@@ -0,0 +1,116 @@
|
||||
"""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-core'
|
||||
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:
|
||||
init = client.initialize(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:
|
||||
client.initialize(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
|
||||
765
python/sdk/tests/test_client.py
Normal file
765
python/sdk/tests/test_client.py
Normal file
@@ -0,0 +1,765 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import inspect
|
||||
import sys
|
||||
import threading
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from deepseek_harness import DeepSeekHarness, HarnessClient, HarnessConfig
|
||||
|
||||
|
||||
def test_high_level_sdk_runs_turn_and_collects_final_response(tmp_path: Path) -> None:
|
||||
script = tmp_path / "fake_runtime.py"
|
||||
env_dump = tmp_path / "env.json"
|
||||
script.write_text(
|
||||
"""
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
|
||||
env_dump = os.environ["ENV_DUMP"]
|
||||
json.dump({
|
||||
"DEEPSEEK_API_KEY": os.environ.get("DEEPSEEK_API_KEY"),
|
||||
"DEEPSEEK_BASE_URL": os.environ.get("DEEPSEEK_BASE_URL"),
|
||||
"DSH_CWD": os.environ.get("DSH_CWD"),
|
||||
"DSH_SESSION_ROOT": os.environ.get("DSH_SESSION_ROOT"),
|
||||
"DSH_CORDIS_CONFIG": os.environ.get("DSH_CORDIS_CONFIG"),
|
||||
}, open(env_dump, "w"))
|
||||
|
||||
for line in sys.stdin:
|
||||
msg = json.loads(line)
|
||||
method = msg.get("method")
|
||||
if method == "initialize":
|
||||
print(json.dumps({"jsonrpc": "2.0", "id": msg["id"], "result": {"serverInfo": {"name": "fake-runtime"}}}), flush=True)
|
||||
elif method == "session/prompt":
|
||||
params = msg.get("params") or {}
|
||||
print(json.dumps({
|
||||
"jsonrpc": "2.0",
|
||||
"method": "session.event",
|
||||
"params": {
|
||||
"sessionId": params["sessionId"],
|
||||
"event": {
|
||||
"type": "assistant/message",
|
||||
"data": {"content": [{"type": "text", "text": "hello from runtime"}]},
|
||||
},
|
||||
},
|
||||
}), flush=True)
|
||||
print(json.dumps({
|
||||
"jsonrpc": "2.0",
|
||||
"method": "session.finished",
|
||||
"params": {"sessionId": params["sessionId"], "status": "ok"},
|
||||
}), flush=True)
|
||||
print(json.dumps({"jsonrpc": "2.0", "id": msg["id"], "result": {"accepted": True}}), flush=True)
|
||||
elif method == "shutdown":
|
||||
print(json.dumps({"jsonrpc": "2.0", "id": msg["id"], "result": {}}), flush=True)
|
||||
break
|
||||
""".strip()
|
||||
)
|
||||
|
||||
with DeepSeekHarness(
|
||||
model="deepseek-v4-flash",
|
||||
cwd=str(tmp_path),
|
||||
cordis=str(tmp_path / "cordis.yml"),
|
||||
session_root=str(tmp_path / "sessions"),
|
||||
launch_args_override=(sys.executable, str(script)),
|
||||
env={
|
||||
"ENV_DUMP": str(env_dump),
|
||||
"DEEPSEEK_API_KEY": "env-key",
|
||||
"DEEPSEEK_BASE_URL": "http://127.0.0.1:4321",
|
||||
},
|
||||
) as harness:
|
||||
result = harness.run("say hello", session_id="main")
|
||||
|
||||
assert result.status == "ok"
|
||||
assert result.final_response == "hello from runtime"
|
||||
assert result.events[0]["type"] == "assistant/message"
|
||||
dumped_env = json.loads(env_dump.read_text())
|
||||
assert dumped_env["DEEPSEEK_API_KEY"] == "env-key"
|
||||
assert dumped_env["DEEPSEEK_BASE_URL"] == "http://127.0.0.1:4321"
|
||||
assert dumped_env["DSH_CWD"] == str(tmp_path)
|
||||
assert dumped_env["DSH_SESSION_ROOT"] == str(tmp_path / "sessions")
|
||||
assert dumped_env["DSH_CORDIS_CONFIG"] == str(tmp_path / "cordis.yml")
|
||||
|
||||
|
||||
def test_session_run_invokes_notification_callback_before_returning(tmp_path: Path) -> None:
|
||||
script = tmp_path / "fake_runtime.py"
|
||||
script.write_text(
|
||||
"""
|
||||
import json
|
||||
import sys
|
||||
|
||||
for line in sys.stdin:
|
||||
msg = json.loads(line)
|
||||
method = msg.get("method")
|
||||
if method == "initialize":
|
||||
print(json.dumps({"jsonrpc": "2.0", "id": msg["id"], "result": {"serverInfo": {"name": "fake-runtime"}}}), flush=True)
|
||||
elif method == "session/prompt":
|
||||
print(json.dumps({"jsonrpc": "2.0", "method": "subagent.started", "params": {"parentSessionId": "main", "childSessionId": "child"}}), flush=True)
|
||||
print(json.dumps({"jsonrpc": "2.0", "method": "session.finished", "params": {"sessionId": "main", "status": "ok"}}), flush=True)
|
||||
print(json.dumps({"jsonrpc": "2.0", "id": msg["id"], "result": {"accepted": True}}), flush=True)
|
||||
elif method == "shutdown":
|
||||
print(json.dumps({"jsonrpc": "2.0", "id": msg["id"], "result": {}}), flush=True)
|
||||
break
|
||||
""".strip()
|
||||
)
|
||||
|
||||
seen: list[str] = []
|
||||
with DeepSeekHarness(
|
||||
launch_args_override=(sys.executable, str(script)),
|
||||
cwd=str(tmp_path),
|
||||
) as harness:
|
||||
session = harness.start_session("main")
|
||||
result = session.run(
|
||||
"spawn a helper",
|
||||
on_notification=lambda notification: seen.append(notification.method),
|
||||
)
|
||||
|
||||
assert result.status == "ok"
|
||||
assert seen == ["subagent.started", "session.finished"]
|
||||
|
||||
|
||||
def test_relative_cwd_is_absolute_in_process_environment_and_wire(
|
||||
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
script = tmp_path / "capture_cwd.py"
|
||||
capture = tmp_path / "cwd.json"
|
||||
script.write_text(
|
||||
"""
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
|
||||
for line in sys.stdin:
|
||||
msg = json.loads(line)
|
||||
if msg.get("method") == "initialize":
|
||||
json.dump({"process": os.getcwd(), "environment": os.environ.get("DSH_CWD"), "wire": msg["params"]["cwd"]}, open(os.environ["CAPTURE"], "w"))
|
||||
print(json.dumps({"jsonrpc": "2.0", "id": msg["id"], "result": {"serverInfo": {"name": "fake-runtime"}}}), flush=True)
|
||||
elif msg.get("method") == "shutdown":
|
||||
print(json.dumps({"jsonrpc": "2.0", "id": msg["id"], "result": {}}), flush=True)
|
||||
break
|
||||
""".strip()
|
||||
)
|
||||
monkeypatch.chdir(tmp_path)
|
||||
|
||||
with DeepSeekHarness(
|
||||
cwd=".",
|
||||
runtime_cwd=".",
|
||||
launch_args_override=(sys.executable, str(script)),
|
||||
env={"CAPTURE": str(capture)},
|
||||
):
|
||||
pass
|
||||
|
||||
expected = str(tmp_path.resolve())
|
||||
assert json.loads(capture.read_text()) == {
|
||||
"process": expected,
|
||||
"environment": expected,
|
||||
"wire": expected,
|
||||
}
|
||||
|
||||
|
||||
def test_session_run_includes_subagent_finished_for_parent_session(tmp_path: Path) -> None:
|
||||
script = tmp_path / "fake_runtime.py"
|
||||
script.write_text(
|
||||
"""
|
||||
import json
|
||||
import sys
|
||||
|
||||
for line in sys.stdin:
|
||||
msg = json.loads(line)
|
||||
method = msg.get("method")
|
||||
if method == "initialize":
|
||||
print(json.dumps({"jsonrpc": "2.0", "id": msg["id"], "result": {"serverInfo": {"name": "fake-runtime"}}}), flush=True)
|
||||
elif method == "session/prompt":
|
||||
print(json.dumps({"jsonrpc": "2.0", "method": "subagent.started", "params": {"parentSessionId": "main", "childSessionId": "child"}}), flush=True)
|
||||
print(json.dumps({"jsonrpc": "2.0", "method": "subagent.finished", "params": {"parentSessionId": "main", "childSessionId": "child", "status": "ok", "stopReason": "completed"}}), flush=True)
|
||||
print(json.dumps({"jsonrpc": "2.0", "method": "session.finished", "params": {"sessionId": "main", "status": "ok"}}), flush=True)
|
||||
print(json.dumps({"jsonrpc": "2.0", "id": msg["id"], "result": {"accepted": True}}), flush=True)
|
||||
elif method == "shutdown":
|
||||
print(json.dumps({"jsonrpc": "2.0", "id": msg["id"], "result": {}}), flush=True)
|
||||
break
|
||||
""".strip()
|
||||
)
|
||||
|
||||
with DeepSeekHarness(
|
||||
launch_args_override=(sys.executable, str(script)),
|
||||
cwd=str(tmp_path),
|
||||
) as harness:
|
||||
result = harness.run("spawn a helper", session_id="main")
|
||||
|
||||
assert result.status == "ok"
|
||||
assert [notification.method for notification in result.notifications] == [
|
||||
"subagent.started",
|
||||
"subagent.finished",
|
||||
"session.finished",
|
||||
]
|
||||
|
||||
|
||||
def test_session_run_ignores_notifications_for_other_sessions(tmp_path: Path) -> None:
|
||||
script = tmp_path / "fake_runtime.py"
|
||||
script.write_text(
|
||||
"""
|
||||
import json
|
||||
import sys
|
||||
|
||||
for line in sys.stdin:
|
||||
msg = json.loads(line)
|
||||
method = msg.get("method")
|
||||
if method == "initialize":
|
||||
print(json.dumps({"jsonrpc": "2.0", "id": msg["id"], "result": {"serverInfo": {"name": "fake-runtime"}}}), flush=True)
|
||||
elif method == "session/prompt":
|
||||
params = msg.get("params") or {}
|
||||
print(json.dumps({"jsonrpc": "2.0", "method": "session.event", "params": {"sessionId": "other", "event": {"type": "assistant/message", "data": {"content": [{"type": "text", "text": "wrong session"}]}}}}), flush=True)
|
||||
print(json.dumps({"jsonrpc": "2.0", "method": "session.finished", "params": {"sessionId": "other", "status": "ok"}}), flush=True)
|
||||
print(json.dumps({"jsonrpc": "2.0", "method": "session.event", "params": {"sessionId": params["sessionId"], "event": {"type": "assistant/message", "data": {"content": [{"type": "text", "text": "right session"}]}}}}), flush=True)
|
||||
print(json.dumps({"jsonrpc": "2.0", "method": "session.finished", "params": {"sessionId": params["sessionId"], "status": "ok"}}), flush=True)
|
||||
print(json.dumps({"jsonrpc": "2.0", "id": msg["id"], "result": {"accepted": True}}), flush=True)
|
||||
elif method == "shutdown":
|
||||
print(json.dumps({"jsonrpc": "2.0", "id": msg["id"], "result": {}}), flush=True)
|
||||
break
|
||||
""".strip()
|
||||
)
|
||||
|
||||
with DeepSeekHarness(
|
||||
launch_args_override=(sys.executable, str(script)),
|
||||
cwd=str(tmp_path),
|
||||
) as harness:
|
||||
result = harness.run("stay in your lane", session_id="main")
|
||||
|
||||
assert result.status == "ok"
|
||||
assert result.final_response == "right session"
|
||||
assert [notification.payload.get("sessionId") for notification in result.notifications] == ["main", "main"]
|
||||
|
||||
|
||||
def test_high_level_session_run_does_not_accumulate_global_notifications(tmp_path: Path) -> None:
|
||||
script = tmp_path / "fake_runtime.py"
|
||||
script.write_text(
|
||||
"""
|
||||
import json
|
||||
import sys
|
||||
|
||||
for line in sys.stdin:
|
||||
msg = json.loads(line)
|
||||
method = msg.get("method")
|
||||
if method == "initialize":
|
||||
print(json.dumps({"jsonrpc": "2.0", "id": msg["id"], "result": {"serverInfo": {"name": "fake-runtime"}}}), flush=True)
|
||||
elif method == "session/prompt":
|
||||
params = msg.get("params") or {}
|
||||
print(json.dumps({"jsonrpc": "2.0", "method": "session.event", "params": {"sessionId": params["sessionId"], "event": {"type": "assistant/message", "data": {"content": [{"type": "text", "text": "ok"}]}}}}), flush=True)
|
||||
print(json.dumps({"jsonrpc": "2.0", "method": "session.finished", "params": {"sessionId": params["sessionId"], "status": "ok"}}), flush=True)
|
||||
print(json.dumps({"jsonrpc": "2.0", "id": msg["id"], "result": {"accepted": True}}), flush=True)
|
||||
elif method == "shutdown":
|
||||
print(json.dumps({"jsonrpc": "2.0", "id": msg["id"], "result": {}}), flush=True)
|
||||
break
|
||||
""".strip()
|
||||
)
|
||||
|
||||
with DeepSeekHarness(launch_args_override=(sys.executable, str(script)), cwd=str(tmp_path)) as harness:
|
||||
result = harness.run("one turn", session_id="main")
|
||||
assert result.status == "ok"
|
||||
assert harness.client._notifications.qsize() == 0
|
||||
|
||||
|
||||
def test_session_run_waits_for_late_finished_without_replaying_stale_notifications(tmp_path: Path) -> None:
|
||||
script = tmp_path / "fake_runtime.py"
|
||||
script.write_text(
|
||||
"""
|
||||
import json
|
||||
import sys
|
||||
import time
|
||||
|
||||
turn = 0
|
||||
for line in sys.stdin:
|
||||
msg = json.loads(line)
|
||||
method = msg.get("method")
|
||||
if method == "initialize":
|
||||
print(json.dumps({"jsonrpc": "2.0", "id": msg["id"], "result": {"serverInfo": {"name": "fake-runtime"}}}), flush=True)
|
||||
elif method == "session/prompt":
|
||||
turn += 1
|
||||
params = msg.get("params") or {}
|
||||
session_id = params["sessionId"]
|
||||
if turn == 1:
|
||||
print(json.dumps({"jsonrpc": "2.0", "method": "session.event", "params": {"sessionId": session_id, "event": {"type": "assistant/message", "data": {"content": [{"type": "text", "text": "first"}]}}}}), flush=True)
|
||||
print(json.dumps({"jsonrpc": "2.0", "method": "session.finished", "params": {"sessionId": session_id, "status": "ok"}}), flush=True)
|
||||
print(json.dumps({"jsonrpc": "2.0", "id": msg["id"], "result": {"accepted": True}}), flush=True)
|
||||
else:
|
||||
print(json.dumps({"jsonrpc": "2.0", "id": msg["id"], "result": {"accepted": True}}), flush=True)
|
||||
time.sleep(0.05)
|
||||
print(json.dumps({"jsonrpc": "2.0", "method": "session.event", "params": {"sessionId": session_id, "event": {"type": "assistant/message", "data": {"content": [{"type": "text", "text": "second"}]}}}}), flush=True)
|
||||
print(json.dumps({"jsonrpc": "2.0", "method": "session.finished", "params": {"sessionId": session_id, "status": "ok"}}), flush=True)
|
||||
elif method == "shutdown":
|
||||
print(json.dumps({"jsonrpc": "2.0", "id": msg["id"], "result": {}}), flush=True)
|
||||
break
|
||||
""".strip()
|
||||
)
|
||||
|
||||
with DeepSeekHarness(launch_args_override=(sys.executable, str(script)), cwd=str(tmp_path)) as harness:
|
||||
first = harness.run("first turn", session_id="main")
|
||||
second = harness.run("second turn", session_id="main")
|
||||
|
||||
assert first.final_response == "first"
|
||||
assert second.final_response == "second"
|
||||
assert [notification.payload.get("sessionId") for notification in second.notifications] == ["main", "main"]
|
||||
|
||||
|
||||
def test_client_starts_subprocess_sends_requests_and_routes_notifications(tmp_path: Path) -> None:
|
||||
script = tmp_path / "fake_bridge.py"
|
||||
script.write_text(
|
||||
"""
|
||||
import json
|
||||
import sys
|
||||
|
||||
for line in sys.stdin:
|
||||
msg = json.loads(line)
|
||||
method = msg.get("method")
|
||||
if method == "initialize":
|
||||
print(json.dumps({"jsonrpc": "2.0", "id": msg["id"], "result": {"serverInfo": {"name": "fake-dsh"}}}), flush=True)
|
||||
elif method == "session/prompt":
|
||||
params = msg.get("params") or {}
|
||||
print(json.dumps({"jsonrpc": "2.0", "method": "llm/request", "params": {"requestId": "req-1", "sessionId": params["sessionId"], "model": "dsagent", "messages": []}}), flush=True)
|
||||
print(json.dumps({"jsonrpc": "2.0", "id": msg["id"], "result": {"accepted": True}}), flush=True)
|
||||
elif method == "shutdown":
|
||||
print(json.dumps({"jsonrpc": "2.0", "id": msg["id"], "result": {}}), flush=True)
|
||||
break
|
||||
""".strip()
|
||||
)
|
||||
|
||||
with HarnessClient(
|
||||
HarnessConfig(launch_args_override=(sys.executable, str(script)))
|
||||
) as client:
|
||||
init = client.initialize(cwd="/workspace", model="dsagent")
|
||||
assert init.serverInfo.name == "fake-dsh"
|
||||
|
||||
client.session_prompt("main", [{"type": "text", "text": "fix it"}])
|
||||
notification = client.next_notification()
|
||||
assert notification.method == "llm/request"
|
||||
assert notification.payload["requestId"] == "req-1"
|
||||
assert notification.payload["sessionId"] == "main"
|
||||
|
||||
|
||||
def test_client_keeps_unmatched_notifications_available_globally_while_subscribed() -> None:
|
||||
client = HarnessClient()
|
||||
with client.subscribe_session_notifications("main"):
|
||||
client._handle_message({
|
||||
"jsonrpc": "2.0",
|
||||
"method": "session.event",
|
||||
"params": {"sessionId": "other", "event": {"type": "assistant/message"}},
|
||||
})
|
||||
|
||||
assert client._notifications.qsize() == 1
|
||||
notification = client._notifications.get_nowait()
|
||||
assert not isinstance(notification, BaseException)
|
||||
assert notification.method == "session.event"
|
||||
assert notification.payload["sessionId"] == "other"
|
||||
|
||||
|
||||
def test_client_contains_notification_filter_failure_to_its_subscription(tmp_path: Path) -> None:
|
||||
script = tmp_path / "fake_bridge.py"
|
||||
script.write_text(
|
||||
"""
|
||||
import json
|
||||
import sys
|
||||
|
||||
for line in sys.stdin:
|
||||
msg = json.loads(line)
|
||||
method = msg.get("method")
|
||||
if method == "initialize":
|
||||
print(json.dumps({"jsonrpc": "2.0", "id": msg["id"], "result": {"serverInfo": {"name": "fake-dsh"}}}), flush=True)
|
||||
elif method in {"emit-first", "emit-second"}:
|
||||
print(json.dumps({"jsonrpc": "2.0", "method": "tick", "params": {"source": method}}), flush=True)
|
||||
elif method == "session/prompt":
|
||||
print(json.dumps({"jsonrpc": "2.0", "id": msg["id"], "result": {"accepted": True}}), flush=True)
|
||||
elif method == "shutdown":
|
||||
print(json.dumps({"jsonrpc": "2.0", "id": msg["id"], "result": {}}), flush=True)
|
||||
break
|
||||
""".strip()
|
||||
)
|
||||
|
||||
def broken_filter(_notification: object) -> bool:
|
||||
raise RuntimeError("bad notification filter")
|
||||
|
||||
with HarnessClient(HarnessConfig(launch_args_override=(sys.executable, str(script)))) as client:
|
||||
client.initialize(cwd="/workspace", model="dsagent")
|
||||
with (
|
||||
client.subscribe_notifications(broken_filter) as broken,
|
||||
client.subscribe_notifications(lambda notification: notification.method == "tick") as healthy,
|
||||
):
|
||||
client.notify("emit-first")
|
||||
with pytest.raises(RuntimeError, match="bad notification filter"):
|
||||
broken.next()
|
||||
assert healthy.next().payload == {"source": "emit-first"}
|
||||
assert client._notifications.qsize() == 0
|
||||
|
||||
client.session_prompt("main", [{"type": "text", "text": "reader still works"}])
|
||||
client.notify("emit-second")
|
||||
assert healthy.next().payload == {"source": "emit-second"}
|
||||
|
||||
|
||||
def test_client_rejects_unaccepted_session_prompt_response(tmp_path: Path) -> None:
|
||||
script = tmp_path / "fake_bridge.py"
|
||||
script.write_text(
|
||||
"""
|
||||
import json
|
||||
import sys
|
||||
|
||||
for line in sys.stdin:
|
||||
msg = json.loads(line)
|
||||
method = msg.get("method")
|
||||
if method == "initialize":
|
||||
print(json.dumps({"jsonrpc": "2.0", "id": msg["id"], "result": {"serverInfo": {"name": "fake-dsh"}}}), flush=True)
|
||||
elif method == "session/prompt":
|
||||
print(json.dumps({"jsonrpc": "2.0", "id": msg["id"], "result": {"accepted": False}}), flush=True)
|
||||
elif method == "shutdown":
|
||||
print(json.dumps({"jsonrpc": "2.0", "id": msg["id"], "result": {}}), flush=True)
|
||||
break
|
||||
""".strip()
|
||||
)
|
||||
|
||||
with HarnessClient(HarnessConfig(launch_args_override=(sys.executable, str(script)))) as client:
|
||||
client.initialize(cwd="/workspace", model="dsagent")
|
||||
with pytest.raises(ValueError):
|
||||
client.session_prompt("main", [{"type": "text", "text": "fix it"}])
|
||||
|
||||
|
||||
def test_client_routes_bridge_requests_and_sends_responses(tmp_path: Path) -> None:
|
||||
script = tmp_path / "fake_bridge.py"
|
||||
script.write_text(
|
||||
"""
|
||||
import json
|
||||
import sys
|
||||
|
||||
for line in sys.stdin:
|
||||
msg = json.loads(line)
|
||||
method = msg.get("method")
|
||||
if method == "initialize":
|
||||
print(json.dumps({"jsonrpc": "2.0", "id": msg["id"], "result": {"serverInfo": {"name": "fake-dsh"}}}), flush=True)
|
||||
print(json.dumps({"jsonrpc": "2.0", "id": "bridge-req-1", "method": "llm.request", "params": {"requestId": "req-1", "sessionId": "main", "model": "dsagent", "messages": []}}), flush=True)
|
||||
elif "id" in msg and "method" not in msg:
|
||||
print(json.dumps({"jsonrpc": "2.0", "method": "response/seen", "params": {"result": msg.get("result")}}), flush=True)
|
||||
elif method == "shutdown":
|
||||
print(json.dumps({"jsonrpc": "2.0", "id": msg["id"], "result": {}}), flush=True)
|
||||
break
|
||||
""".strip()
|
||||
)
|
||||
|
||||
with HarnessClient(
|
||||
HarnessConfig(launch_args_override=(sys.executable, str(script)))
|
||||
) as client:
|
||||
client.initialize(cwd="/workspace", model="dsagent")
|
||||
|
||||
request = client.next_request()
|
||||
assert request.id == "bridge-req-1"
|
||||
assert request.method == "llm.request"
|
||||
assert request.payload["requestId"] == "req-1"
|
||||
|
||||
client.respond(request.id, {"content_blocks": [{"type": "text", "text": "done"}]})
|
||||
notification = client.next_notification()
|
||||
assert notification.method == "response/seen"
|
||||
assert notification.payload["result"]["content_blocks"][0]["text"] == "done"
|
||||
|
||||
|
||||
def test_client_ignores_non_json_stdout_lines(tmp_path: Path) -> None:
|
||||
script = tmp_path / "fake_bridge.py"
|
||||
script.write_text(
|
||||
"""
|
||||
import json
|
||||
import sys
|
||||
|
||||
print("node warning: experimental loader", flush=True)
|
||||
for line in sys.stdin:
|
||||
msg = json.loads(line)
|
||||
if msg.get("method") == "initialize":
|
||||
print(json.dumps({"jsonrpc": "2.0", "id": msg["id"], "result": {"serverInfo": {"name": "fake-dsh"}}}), flush=True)
|
||||
elif msg.get("method") == "shutdown":
|
||||
print(json.dumps({"jsonrpc": "2.0", "id": msg["id"], "result": {}}), flush=True)
|
||||
break
|
||||
""".strip()
|
||||
)
|
||||
|
||||
with HarnessClient(
|
||||
HarnessConfig(launch_args_override=(sys.executable, str(script)))
|
||||
) as client:
|
||||
init = client.initialize(cwd="/workspace", model="dsagent")
|
||||
assert init.serverInfo.name == "fake-dsh"
|
||||
|
||||
|
||||
def test_client_request_times_out_when_bridge_does_not_respond(tmp_path: Path) -> None:
|
||||
script = tmp_path / "fake_bridge.py"
|
||||
script.write_text(
|
||||
"""
|
||||
import time
|
||||
|
||||
time.sleep(60)
|
||||
""".strip()
|
||||
)
|
||||
|
||||
with HarnessClient(
|
||||
HarnessConfig(
|
||||
launch_args_override=(sys.executable, str(script)),
|
||||
request_timeout_seconds=0.1,
|
||||
)
|
||||
) as client:
|
||||
start = time.monotonic()
|
||||
try:
|
||||
client.initialize(cwd="/workspace", model="dsagent")
|
||||
except TimeoutError:
|
||||
assert time.monotonic() - start < 2
|
||||
else:
|
||||
raise AssertionError("initialize should time out")
|
||||
|
||||
|
||||
def test_client_close_times_out_when_shutdown_does_not_respond(tmp_path: Path) -> None:
|
||||
script = tmp_path / "fake_bridge.py"
|
||||
script.write_text(
|
||||
"""
|
||||
import json
|
||||
import signal
|
||||
import sys
|
||||
import time
|
||||
|
||||
signal.signal(signal.SIGTERM, signal.SIG_IGN)
|
||||
|
||||
for line in sys.stdin:
|
||||
msg = json.loads(line)
|
||||
if msg.get("method") == "initialize":
|
||||
print(json.dumps({"jsonrpc": "2.0", "id": msg["id"], "result": {"serverInfo": {"name": "fake-dsh"}}}), flush=True)
|
||||
elif msg.get("method") == "shutdown":
|
||||
time.sleep(60)
|
||||
""".strip()
|
||||
)
|
||||
|
||||
client = HarnessClient(
|
||||
HarnessConfig(
|
||||
launch_args_override=(sys.executable, str(script)),
|
||||
shutdown_timeout_seconds=0.1,
|
||||
)
|
||||
)
|
||||
client.start()
|
||||
proc = client._proc
|
||||
assert proc is not None
|
||||
client.initialize(cwd="/workspace", model="dsagent")
|
||||
start = time.monotonic()
|
||||
client.close()
|
||||
assert time.monotonic() - start < 2
|
||||
assert proc.poll() is not None
|
||||
assert client._proc is None
|
||||
|
||||
|
||||
def test_initialize_failure_reaps_started_runtime(tmp_path: Path) -> None:
|
||||
script = tmp_path / "rejecting_runtime.py"
|
||||
script.write_text(
|
||||
"""
|
||||
import json
|
||||
import sys
|
||||
|
||||
for line in sys.stdin:
|
||||
msg = json.loads(line)
|
||||
if msg.get("method") == "initialize":
|
||||
print(json.dumps({"jsonrpc": "2.0", "id": msg["id"], "error": {"code": -32000, "message": "bad initialize"}}), flush=True)
|
||||
elif msg.get("method") == "shutdown":
|
||||
print(json.dumps({"jsonrpc": "2.0", "id": msg["id"], "result": {}}), flush=True)
|
||||
break
|
||||
""".strip()
|
||||
)
|
||||
|
||||
client = HarnessClient(HarnessConfig(launch_args_override=(sys.executable, str(script))))
|
||||
client.start()
|
||||
proc = client._proc
|
||||
assert proc is not None
|
||||
|
||||
with pytest.raises(Exception, match="bad initialize"):
|
||||
client.initialize(cwd=".", model="dsagent")
|
||||
|
||||
assert proc.wait(timeout=1) is not None
|
||||
assert client._proc is None
|
||||
|
||||
|
||||
def test_public_signatures_omit_unsupported_wire_parameters() -> None:
|
||||
from deepseek_harness import DeepSeekHarnessConfig, Session
|
||||
|
||||
assert "session_root" not in inspect.signature(HarnessClient.initialize).parameters
|
||||
assert "system_prompt" not in inspect.signature(HarnessClient.initialize).parameters
|
||||
assert "profile" not in inspect.signature(HarnessClient.session_prompt).parameters
|
||||
assert "profile" not in inspect.signature(DeepSeekHarness.run).parameters
|
||||
assert "profile" not in inspect.signature(Session.run).parameters
|
||||
assert "system_prompt" not in DeepSeekHarnessConfig.__dataclass_fields__
|
||||
assert "client_name" not in HarnessConfig.__dataclass_fields__
|
||||
assert "client_version" not in HarnessConfig.__dataclass_fields__
|
||||
|
||||
|
||||
def test_client_close_is_idempotent_before_and_after_start(tmp_path: Path) -> None:
|
||||
HarnessClient().close()
|
||||
|
||||
script = tmp_path / "fake_bridge.py"
|
||||
script.write_text(
|
||||
"""
|
||||
import json
|
||||
import sys
|
||||
|
||||
for line in sys.stdin:
|
||||
msg = json.loads(line)
|
||||
if msg.get("method") == "initialize":
|
||||
print(json.dumps({"jsonrpc": "2.0", "id": msg["id"], "result": {"serverInfo": {"name": "fake-dsh"}}}), flush=True)
|
||||
elif msg.get("method") == "shutdown":
|
||||
print(json.dumps({"jsonrpc": "2.0", "id": msg["id"], "result": {}}), flush=True)
|
||||
break
|
||||
""".strip()
|
||||
)
|
||||
|
||||
client = HarnessClient(HarnessConfig(launch_args_override=(sys.executable, str(script))))
|
||||
client.start()
|
||||
client.initialize(cwd="/workspace", model="dsagent")
|
||||
client.close()
|
||||
client.close()
|
||||
|
||||
|
||||
def test_runtime_closed_error_includes_stderr_tail(tmp_path: Path) -> None:
|
||||
script = tmp_path / "crashing_runtime.py"
|
||||
script.write_text(
|
||||
"""
|
||||
import sys
|
||||
|
||||
print("fatal bridge exploded", file=sys.stderr, flush=True)
|
||||
sys.exit(42)
|
||||
""".strip()
|
||||
)
|
||||
|
||||
with HarnessClient(
|
||||
HarnessConfig(
|
||||
launch_args_override=(sys.executable, str(script)),
|
||||
request_timeout_seconds=2,
|
||||
)
|
||||
) as client:
|
||||
with pytest.raises(Exception, match="fatal bridge exploded"):
|
||||
client.initialize(cwd="/workspace", model="dsagent")
|
||||
|
||||
|
||||
def test_client_serializes_concurrent_writes(tmp_path: Path) -> None:
|
||||
script = tmp_path / "fake_bridge.py"
|
||||
output = tmp_path / "seen.jsonl"
|
||||
script.write_text(
|
||||
"""
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
|
||||
with open(os.environ["SEEN"], "w") as seen:
|
||||
for line in sys.stdin:
|
||||
seen.write(line)
|
||||
seen.flush()
|
||||
msg = json.loads(line)
|
||||
if "id" in msg and msg.get("method") == "initialize":
|
||||
print(json.dumps({"jsonrpc": "2.0", "id": msg["id"], "result": {"serverInfo": {"name": "fake-dsh"}}}), flush=True)
|
||||
elif "id" in msg and msg.get("method") == "shutdown":
|
||||
print(json.dumps({"jsonrpc": "2.0", "id": msg["id"], "result": {}}), flush=True)
|
||||
break
|
||||
""".strip()
|
||||
)
|
||||
|
||||
with HarnessClient(
|
||||
HarnessConfig(
|
||||
launch_args_override=(sys.executable, str(script)),
|
||||
env={"SEEN": str(output)},
|
||||
)
|
||||
) as client:
|
||||
client.initialize(cwd="/workspace", model="dsagent")
|
||||
threads = [
|
||||
threading.Thread(target=client.notify, args=(f"notice-{index}", {"index": index}))
|
||||
for index in range(50)
|
||||
]
|
||||
for thread in threads:
|
||||
thread.start()
|
||||
for thread in threads:
|
||||
thread.join()
|
||||
|
||||
for line in output.read_text().splitlines():
|
||||
json.loads(line)
|
||||
|
||||
|
||||
def _install_fake_bundled_runtime(
|
||||
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
||||
) -> Path:
|
||||
"""Install a fake runtime package that records config and serves lifecycle calls.
|
||||
|
||||
Returns the fake bundled default config path.
|
||||
"""
|
||||
runtime = tmp_path / "dsh-jsonrpc-agent"
|
||||
runtime.write_text(
|
||||
"""#!/usr/bin/env python3
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
|
||||
json.dump({"DSH_CORDIS_CONFIG": os.environ.get("DSH_CORDIS_CONFIG")}, open(os.environ["ENV_DUMP"], "w"))
|
||||
for line in sys.stdin:
|
||||
msg = json.loads(line)
|
||||
if msg.get("method") == "initialize":
|
||||
print(json.dumps({"jsonrpc": "2.0", "id": msg["id"], "result": {"serverInfo": {"name": "bundled-runtime"}}}), flush=True)
|
||||
elif msg.get("method") == "shutdown":
|
||||
print(json.dumps({"jsonrpc": "2.0", "id": msg["id"], "result": {}}), flush=True)
|
||||
break
|
||||
""".strip()
|
||||
)
|
||||
runtime.chmod(0o755)
|
||||
|
||||
default_config = tmp_path / "default-cordis.yml"
|
||||
module_dir = tmp_path / "deepseek_harness_runtime"
|
||||
module_dir.mkdir()
|
||||
(module_dir / "__init__.py").write_text(
|
||||
f"""
|
||||
def resolve_bundled_launch_args(mode=None):
|
||||
return ({str(runtime)!r},)
|
||||
|
||||
|
||||
def bundled_default_config_path():
|
||||
return {str(default_config)!r}
|
||||
""".strip()
|
||||
)
|
||||
|
||||
monkeypatch.syspath_prepend(str(tmp_path))
|
||||
monkeypatch.delitem(sys.modules, "deepseek_harness_runtime", raising=False)
|
||||
return default_config
|
||||
|
||||
|
||||
@pytest.mark.parametrize("ambient_config", [None, ""], ids=["unset", "empty-counts-as-absent"])
|
||||
def test_client_default_launch_uses_bundled_runtime_and_injects_default_config(
|
||||
tmp_path: Path, monkeypatch: pytest.MonkeyPatch, ambient_config: str | None
|
||||
) -> None:
|
||||
env_dump = tmp_path / "env.json"
|
||||
default_config = _install_fake_bundled_runtime(tmp_path, monkeypatch)
|
||||
if ambient_config is None:
|
||||
monkeypatch.delenv("DSH_CORDIS_CONFIG", raising=False)
|
||||
else:
|
||||
monkeypatch.setenv("DSH_CORDIS_CONFIG", ambient_config)
|
||||
|
||||
with HarnessClient(HarnessConfig(env={"ENV_DUMP": str(env_dump)})) as client:
|
||||
init = client.initialize(cwd="/workspace", model="deepseek-v4-pro")
|
||||
|
||||
assert init.serverInfo.name == "bundled-runtime"
|
||||
assert json.loads(env_dump.read_text())["DSH_CORDIS_CONFIG"] == str(default_config)
|
||||
|
||||
|
||||
def test_client_respects_explicit_config_over_bundled_default(
|
||||
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
env_dump = tmp_path / "env.json"
|
||||
_install_fake_bundled_runtime(tmp_path, monkeypatch)
|
||||
monkeypatch.delenv("DSH_CORDIS_CONFIG", raising=False)
|
||||
|
||||
with HarnessClient(
|
||||
HarnessConfig(env={"ENV_DUMP": str(env_dump), "DSH_CORDIS_CONFIG": "./explicit.yml"})
|
||||
) as client:
|
||||
client.initialize(cwd="/workspace", model="deepseek-v4-pro")
|
||||
|
||||
assert json.loads(env_dump.read_text())["DSH_CORDIS_CONFIG"] == "./explicit.yml"
|
||||
|
||||
|
||||
def test_client_reports_missing_bundled_runtime_dependency(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
monkeypatch.delitem(sys.modules, "deepseek_harness_runtime", raising=False)
|
||||
monkeypatch.setattr(sys, "path", [])
|
||||
|
||||
with pytest.raises(FileNotFoundError, match="Install deepseek-harness-runtime-bin"):
|
||||
HarnessClient().start()
|
||||
39
python/sdk/tests/test_release_version.py
Normal file
39
python/sdk/tests/test_release_version.py
Normal file
@@ -0,0 +1,39 @@
|
||||
"""Tests for repository-owned Python release versions."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import runpy
|
||||
from pathlib import Path
|
||||
from types import SimpleNamespace
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[3]
|
||||
SCRIPT = ROOT / "scripts" / "build-python-release.py"
|
||||
build_python_release = SimpleNamespace(**runpy.run_path(str(SCRIPT)))
|
||||
|
||||
|
||||
def test_repository_version_matches_root_package_json() -> None:
|
||||
expected = json.loads((ROOT / "package.json").read_text())["version"]
|
||||
|
||||
assert build_python_release.repository_version() == expected
|
||||
|
||||
|
||||
def test_release_tag_is_optional_for_non_release_builds() -> None:
|
||||
build_python_release.validate_release_tag(None, "1.2.3")
|
||||
|
||||
|
||||
def test_release_tag_must_match_repository_version() -> None:
|
||||
build_python_release.validate_release_tag("python-v1.2.3", "1.2.3")
|
||||
|
||||
with pytest.raises(ValueError, match="expected 'python-v1.2.3'"):
|
||||
build_python_release.validate_release_tag("python-v1.2.4", "1.2.3")
|
||||
|
||||
|
||||
def test_repository_version_rejects_non_stable_versions(tmp_path: Path) -> None:
|
||||
(tmp_path / "package.json").write_text('{"version":"1.2.3-dev"}\n')
|
||||
|
||||
with pytest.raises(ValueError, match="must be stable X.Y.Z"):
|
||||
build_python_release.repository_version(tmp_path)
|
||||
38
python/sdk/tests/test_runtime_resolution.py
Normal file
38
python/sdk/tests/test_runtime_resolution.py
Normal file
@@ -0,0 +1,38 @@
|
||||
"""Keyless runtime-resolution tests; launch coverage lives in test_bundled_runtime.py."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
|
||||
from deepseek_harness_runtime import (
|
||||
RUNTIME_MODE_ENV_VAR,
|
||||
bundled_default_config_path,
|
||||
bundled_package_dir,
|
||||
resolve_bundled_launch_args,
|
||||
)
|
||||
|
||||
|
||||
def test_default_config_is_shipped_with_the_package() -> None:
|
||||
path = bundled_default_config_path()
|
||||
assert path == bundled_package_dir() / "runtime" / "cordis.yml"
|
||||
assert "@deepseek-ai/dsh-agent-core" in path.read_text()
|
||||
|
||||
|
||||
def test_unknown_explicit_mode_fails_loud() -> None:
|
||||
with pytest.raises(ValueError, match="expected 'exe' or 'node'"):
|
||||
resolve_bundled_launch_args("bogus")
|
||||
|
||||
|
||||
def test_unknown_env_mode_fails_loud(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
monkeypatch.setenv(RUNTIME_MODE_ENV_VAR, "bogus")
|
||||
with pytest.raises(ValueError, match="expected 'exe' or 'node'"):
|
||||
resolve_bundled_launch_args()
|
||||
|
||||
|
||||
def test_explicit_mode_wins_over_env_mode(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
monkeypatch.setenv(RUNTIME_MODE_ENV_VAR, "bogus")
|
||||
try:
|
||||
args = resolve_bundled_launch_args("exe")
|
||||
except FileNotFoundError:
|
||||
return # explicit 'exe' was honored; only the artifact is missing
|
||||
assert args[0].endswith(("-x64", "-arm64"))
|
||||
Reference in New Issue
Block a user