Skip to content

feat(turn): bind the default Turn host to the operator credential - #4409

Closed
huangruiteng wants to merge 3 commits into
codex/dsh-latest-sdk-20260915from
codex/default-turn-host-binding-20260915
Closed

huangruiteng wants to merge 3 commits into
codex/dsh-latest-sdk-20260915from
codex/default-turn-host-binding-20260915

Conversation

@huangruiteng

@huangruiteng huangruiteng commented Sep 15, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

loopx turn run-once defaulted to generic-cli and loopx turn plan hard-coded
codex-cli, so an operator who had configured their own model credential still
had to pass --host dsh explicitly to keep governed Turns off an individual CLI
subscription.

Default host resolution is now one typed rule in
loopx/control_plane/turn_driver/host_binding.py:

Operator configuration Default --host
DEEPSEEK_API_KEY set to a non-empty value dsh
no configured credential codex-cli

DEEPSEEK_BASE_URL selects the endpoint the credential is used against but does
not switch hosts on its own; whitespace-only values count as unconfigured; an
explicit --host always wins, and the resolved value is what loopx turn plan
reports back. turn plan also accepts the dsh host it can already route.

Default behavior change

  • loopx turn run-once: generic-cli -> credential-resolved (dsh with a
    configured DEEPSEEK_API_KEY, otherwise codex-cli).
  • loopx turn plan: codex-cli -> same credential-resolved default; dsh added
    to its explicit --host choices (claude-code planning choice unchanged).
  • Affected lanes: codex-cli, dsh, generic-cli Turn hosts.

Tests and one smoke that encoded the former generic-cli default now pass
--host generic-cli explicitly, so they keep testing the host they named rather
than the ambient default.

Validation

.venv/bin/python -m pytest \
  tests/test_turn_default_host_binding.py tests/test_loopx_turn_driver.py \
  tests/test_loopx_turn_executor.py tests/test_dsh_goal_mode.py \
  tests/test_default_public_scan_root.py tests/control_plane/test_cli_output_budget.py -q
# 226 passed (2:09)

tests/test_turn_default_host_binding.py covers the resolution matrix
(configured, empty, whitespace-only, endpoint-without-credential), both CLI
defaults with and without the credential, and explicit --host precedence.

No live provider call is made by this change or its tests. Public/private scan of
the touched paths is clean (no local paths, credentials, or private context).

Refactor pass

The resolution rule lives in one typed module with a single call site per
command default, so the next host surface (the manager executor and manager
model defaults) can consume the same rule instead of re-deriving it.

Stack

This stack now carries the dsh release pin: #4420 (deepseek-harness-sdk==0.1.5rc1, upstream released channel) -> #4409 -> #4416 -> #4417 -> #4419. Each branch was rebased on the pin; the managed dsh default therefore runs on the current released runtime rather than the previous 0.1.2a3 pin.

The `deepseek-harness` extra now pins `deepseek-harness-sdk==0.1.5rc1` and its
bundled `deepseek-harness-runtime-bin==0.1.5rc1`, the newest release channel
published for dsh (PyPI for the wheels, `latest` on npm for `@deepseek-ai/dsh`).
The Python client surface is unchanged from the previously pinned `0.1.2a3`;
the bump moves the bundled dsh runtime behind the managed host.

Validation (hermetic, local mock LLM, no provider call):
- `examples/loopx-turn-dsh-real-e2e-smoke.py --host generic-cli` and
  `--host dsh` both pass against 0.1.2a3 (control) and 0.1.5rc1.
- `tests/test_dsh_goal_mode.py` (55 passed), `examples/dsh-turn-host-adapter-smoke.py`
  (11 checks), `examples/loopx-turn-dsh-e2e-smoke.py`,
  `examples/loopx-turn-dsh-builtin-host-e2e-smoke.py` all pass.

Signed-off-by: Codex Product Agent <codex@loopx.local>
Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
`loopx turn run-once` defaulted to `generic-cli` and `loopx turn plan`
hard-coded `codex-cli`, so a machine with an operator-supplied model credential
still needed an explicit `--host dsh` to keep governed Turns off an individual
CLI subscription.

Default host resolution now follows one typed rule in
`control_plane/turn_driver/host_binding.py`: a non-empty `DEEPSEEK_API_KEY`
selects the `dsh` host, and an unconfigured credential keeps `codex-cli`.
`DEEPSEEK_BASE_URL` chooses the endpoint but does not switch hosts, an explicit
`--host` still wins, and `turn plan` now accepts the `dsh` host it can already
route.

Tests that encoded the former `generic-cli` default pass it explicitly now, and
`tests/test_turn_default_host_binding.py` covers the resolution matrix plus both
CLI defaults.

Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
Record the shipped default-host rule on the connector surface: a configured
`DEEPSEEK_API_KEY` selects `dsh`, no configured credential keeps `codex-cli`,
`DEEPSEEK_BASE_URL` does not switch hosts on its own, an explicit `--host` wins,
and the resolved value is what `turn plan` reports back.

Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
@huangruiteng

Copy link
Copy Markdown
Collaborator Author

Superseded by #4443 (feat(turn): select the managed Turn host explicitly).

The value here is kept: the shipped managed default, the explicit LOOPX_TURN_HOST selector, the per-command --host override, the migrated tests, and the disclosed default-behavior change. What changed is the rule this PR encoded: the Turn host is now selected, never inferred. A configured DEEPSEEK_API_KEY only authenticates the host that was already selected, instead of resolving the default host and the billing boundary for the operator.

#4443 is main-based rather than stacked, so it needs one review and carries no layer-refresh cost. Closing this to compress the delivery chain.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant