feat(llm): route adapters by provider

This commit is contained in:
Yichen Jiang
2026-07-14 21:57:52 +08:00
parent a0359bc4a9
commit e547980d77
218 changed files with 2605 additions and 1844 deletions
@@ -30,9 +30,6 @@
config:
apiKey: !!js process.env.DEEPSEEK_API_KEY
baseURL: !!js process.env.DEEPSEEK_BASE_URL
models:
- deepseek-v4-flash
- deepseek-v4-pro
# JSONL session persistence. $DSH_SESSION_ROOT (set by the SDK whenever
# `session_root` is configured) wins; otherwise ./.sessions relative to the
+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
README.md: 60540376c5fd85b0852e204bc8bad3f01c849de5
README.zh.md: 241c06057889f1aa4add6fc54024fba92bd19429
README.md: b1189a789963a5e4180cc4ee402c885b0ec82dca
README.zh.md: 721221418eb65f323f521a4fa16cbc355d283f0d
+3
View File
@@ -25,12 +25,15 @@ By default, the SDK launches the bundled single-file `dsh-jsonrpc-agent` executa
from deepseek_harness import DeepSeekHarness
with DeepSeekHarness(
provider="deepseek",
model="deepseek-v4-flash",
cordis="examples/dsbench-coding-agent/cordis.yml",
) as harness:
result = harness.run("Make the requested code change.")
```
`provider` selects a provider route registered by the chosen Cordis composition; `model` is the model id resolved by that adapter. The bundled default composition registers `deepseek`. A custom composition can mount `llm-pi-ai`, configure provider-specific credentials/endpoints there, and select any provider/model present in pi-ai's installed catalog.
`TurnResult.final_response` is the text content from the last
`assistant/message` event in the turn. Use `TurnResult.events` for the complete
event stream, including intermediate assistant messages and tool activity.
+3
View File
@@ -21,12 +21,15 @@ with DeepSeekHarness() as harness:
from deepseek_harness import DeepSeekHarness
with DeepSeekHarness(
provider="deepseek",
model="deepseek-v4-flash",
cordis="examples/dsbench-coding-agent/cordis.yml",
) as harness:
result = harness.run("Make the requested code change.")
```
`provider` 用于选择当前 Cordis 组合已注册的 provider 路由;`model` 是该适配器解析的模型 ID。内置默认组合注册 `deepseek`。自定义组合可以挂载 `llm-pi-ai`,在其中配置各 provider 的凭据与端点,再选择 pi-ai 已安装目录中的任意 provider/model。
`TurnResult.final_response` 是本轮次最后一个 `assistant/message` 事件的文本内容。完整的事件流(包括中间的助手消息与工具活动)用 `TurnResult.events` 获取。
同样的行为也可以通过 `DSH_CORDIS_CONFIG` 为运行时子进程选定。注入逻辑位于 `HarnessClient.start()`,因此底层客户端的默认启动也具有此行为:当启动解析到内置运行时,且 `cordis` 与非空的 `DSH_CORDIS_CONFIG` 均未设置时(运行时把空值视为缺省,注入检查与之一致),使用内置的默认配置;显式给出 `runtime_bin``launch_args_override` 则完全禁用注入。运行时载体(生产用 exe 与仅限开发的 `node` 闭包)及其获取方式见 [sdk-runtime README](../sdk-runtime/README.md)。
+2
View File
@@ -18,6 +18,7 @@ class DeepSeekHarnessConfig:
intentionally override or inject variables for a subprocess.
"""
provider: str = "deepseek"
model: str = "deepseek-v4-flash"
cwd: str | None = None
runtime_cwd: str | None = None
@@ -97,6 +98,7 @@ class DeepSeekHarness:
self._client.start()
self._client.initialize(
cwd=self._cwd,
provider=self.config.provider,
model=self.config.model,
)
self._initialized = True
@@ -115,10 +115,12 @@ class HarnessClient:
self,
*,
cwd: str,
provider: str,
model: str,
) -> InitializeResponse:
payload: JsonObject = {
"cwd": str(Path(cwd).resolve()),
"provider": provider,
"model": model,
}
try:
+2 -2
View File
@@ -74,7 +74,7 @@ def test_bundled_runtime_boots_a_cordis_config(tmp_path: Path, mode: str) -> Non
(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")
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"
@@ -91,7 +91,7 @@ def test_bundled_runtime_surfaces_unbundled_plugin_failure(tmp_path: Path, mode:
client.start()
try:
with pytest.raises((TransportClosedError, TimeoutError)) as excinfo:
client.initialize(cwd=str(tmp_path), model="deepseek-v4-pro")
client.initialize(provider="deepseek", cwd=str(tmp_path), model="deepseek-v4-pro")
finally:
client.close()
+13 -13
View File
@@ -330,7 +330,7 @@ for line in sys.stdin:
with HarnessClient(
HarnessConfig(launch_args_override=(sys.executable, str(script)))
) as client:
init = client.initialize(cwd="/workspace", model="dsagent")
init = client.initialize(provider="deepseek", cwd="/workspace", model="dsagent")
assert init.serverInfo.name == "fake-dsh"
client.session_prompt("main", [{"type": "text", "text": "fix it"}])
@@ -382,7 +382,7 @@ for line in sys.stdin:
raise RuntimeError("bad notification filter")
with HarnessClient(HarnessConfig(launch_args_override=(sys.executable, str(script)))) as client:
client.initialize(cwd="/workspace", model="dsagent")
client.initialize(provider="deepseek", cwd="/workspace", model="dsagent")
with (
client.subscribe_notifications(broken_filter) as broken,
client.subscribe_notifications(lambda notification: notification.method == "tick") as healthy,
@@ -419,7 +419,7 @@ for line in sys.stdin:
)
with HarnessClient(HarnessConfig(launch_args_override=(sys.executable, str(script)))) as client:
client.initialize(cwd="/workspace", model="dsagent")
client.initialize(provider="deepseek", cwd="/workspace", model="dsagent")
with pytest.raises(ValueError):
client.session_prompt("main", [{"type": "text", "text": "fix it"}])
@@ -448,7 +448,7 @@ for line in sys.stdin:
with HarnessClient(
HarnessConfig(launch_args_override=(sys.executable, str(script)))
) as client:
client.initialize(cwd="/workspace", model="dsagent")
client.initialize(provider="deepseek", cwd="/workspace", model="dsagent")
request = client.next_request()
assert request.id == "bridge-req-1"
@@ -482,7 +482,7 @@ for line in sys.stdin:
with HarnessClient(
HarnessConfig(launch_args_override=(sys.executable, str(script)))
) as client:
init = client.initialize(cwd="/workspace", model="dsagent")
init = client.initialize(provider="deepseek", cwd="/workspace", model="dsagent")
assert init.serverInfo.name == "fake-dsh"
@@ -504,7 +504,7 @@ time.sleep(60)
) as client:
start = time.monotonic()
try:
client.initialize(cwd="/workspace", model="dsagent")
client.initialize(provider="deepseek", cwd="/workspace", model="dsagent")
except TimeoutError:
assert time.monotonic() - start < 2
else:
@@ -540,7 +540,7 @@ for line in sys.stdin:
client.start()
proc = client._proc
assert proc is not None
client.initialize(cwd="/workspace", model="dsagent")
client.initialize(provider="deepseek", cwd="/workspace", model="dsagent")
start = time.monotonic()
client.close()
assert time.monotonic() - start < 2
@@ -571,7 +571,7 @@ for line in sys.stdin:
assert proc is not None
with pytest.raises(Exception, match="bad initialize"):
client.initialize(cwd=".", model="dsagent")
client.initialize(provider="deepseek", cwd=".", model="dsagent")
assert proc.wait(timeout=1) is not None
assert client._proc is None
@@ -611,7 +611,7 @@ for line in sys.stdin:
client = HarnessClient(HarnessConfig(launch_args_override=(sys.executable, str(script))))
client.start()
client.initialize(cwd="/workspace", model="dsagent")
client.initialize(provider="deepseek", cwd="/workspace", model="dsagent")
client.close()
client.close()
@@ -634,7 +634,7 @@ sys.exit(42)
)
) as client:
with pytest.raises(Exception, match="fatal bridge exploded"):
client.initialize(cwd="/workspace", model="dsagent")
client.initialize(provider="deepseek", cwd="/workspace", model="dsagent")
def test_client_serializes_concurrent_writes(tmp_path: Path) -> None:
@@ -665,7 +665,7 @@ with open(os.environ["SEEN"], "w") as seen:
env={"SEEN": str(output)},
)
) as client:
client.initialize(cwd="/workspace", model="dsagent")
client.initialize(provider="deepseek", cwd="/workspace", model="dsagent")
threads = [
threading.Thread(target=client.notify, args=(f"notice-{index}", {"index": index}))
for index in range(50)
@@ -738,7 +738,7 @@ def test_client_default_launch_uses_bundled_runtime_and_injects_default_config(
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")
init = client.initialize(provider="deepseek", 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)
@@ -754,7 +754,7 @@ def test_client_respects_explicit_config_over_bundled_default(
with HarnessClient(
HarnessConfig(env={"ENV_DUMP": str(env_dump), "DSH_CORDIS_CONFIG": "./explicit.yml"})
) as client:
client.initialize(cwd="/workspace", model="deepseek-v4-pro")
client.initialize(provider="deepseek", cwd="/workspace", model="deepseek-v4-pro")
assert json.loads(env_dump.read_text())["DSH_CORDIS_CONFIG"] == "./explicit.yml"