Skip to content

feat(dsh): add DeepSeek Harness wrap support - #2994

Open
Zenjibad wants to merge 25 commits into
headroomlabs-ai:mainfrom
Zenjibad:feat/dsh-compatibility
Open

feat(dsh): add DeepSeek Harness wrap support#2994
Zenjibad wants to merge 25 commits into
headroomlabs-ai:mainfrom
Zenjibad:feat/dsh-compatibility

Conversation

@Zenjibad

@Zenjibad Zenjibad commented Aug 13, 2026

Copy link
Copy Markdown

Description

Adds headroom wrap dsh / unwrap dsh so DeepSeek Harness (dsh) sessions get their traffic compressed through the proxy. dsh speaks OpenAI-compatible chat-completions, so this reuses the existing OpenAI handler — the only new routing is a DeepSeek upstream target and a check that sends deepseek-* models (or anything carrying dsh's x-deepseek-harness-user-id header) to DeepSeek instead of OpenAI.

Closes # (new provider, no issue)

Type of Change

  • New feature (non-breaking change that adds functionality)

Changes Made

  • New headroom/providers/dsh/ package (build_launch_env, resolve_dsh_command, install env builder).
  • deepseek upstream target wired through registry.py, ProxyConfig, server.py, and the proxy CLI (DEEPSEEK_TARGET_API_URL env / --deepseek-api-url flag).
  • DeepSeek routing in the OpenAI chat handler (_is_deepseek_request + _resolve_openai_upstream).
  • wrap dsh / unwrap dsh commands — web + headless profile, --command, --deepseek-api-url; launch-env only, no durable config.
  • Docs: README compatibility matrix, wiki/dsh.md, llms.txt.

Testing

  • Unit tests pass (pytest)
  • Linting passes (ruff check .)
  • Formatting passes (ruff format --check .)
  • Type checking passes (mypy)
  • New tests added for new functionality
  • Manual testing performed

Test Output

$ uv run python -m pytest tests/test_dsh_runtime.py tests/test_registry_deepseek.py \
    tests/test_deepseek_routing.py tests/test_cli/test_wrap_dsh.py \
    tests/test_backend_bugs.py::TestOpenAIURLNormalization -q
33 passed in 2.77s

$ uv run ruff check . && uv run ruff format --check .
All checks passed!
1415 files already formatted

$ uv run mypy headroom --ignore-missing-imports
Success: no issues found

Real Behavior Proof

  • Environment: Windows 10, Python 3.13, uv sync --extra dev --extra proxy, dsh v0.1.0-rc.6 (npm i -g @deepseek-ai/dsh).
  • Exact command / steps: uv run python smoke_dsh.py (mock DeepSeek upstream, no key) — posts a deepseek-v4-flash chat completion through the proxy with x-deepseek-harness-user-id: anon; and uv run headroom wrap dsh --profile headless "..." for the live path.
  • Observed result: the mock DeepSeek upstream received POST /v1/chat/completions with the dsh header intact, and the client got a 200. With OPENAI_TARGET_API_URL pointed at a dead port, the request still succeeded — so it hit DeepSeek, not OpenAI.
  • Not tested: the live DeepSeek API (no key on this machine); the dsh web UI end-to-end.

Runtime Rollout Safety

  • Rollout-managed feature(s): none.
  • Minimum rollout channel: n/a.
  • Stable/default behavior changed: no — deepseek defaults to https://api.deepseek.com; existing providers untouched.
  • Kill switch / disable path: headroom unwrap dsh.
  • Unsafe override required: no.
  • Qualification impact: none.
  • Rollback path: headroom unwrap dsh (proxy teardown only).

Review Readiness

  • I have performed a self-review
  • This PR is ready for human review

Checklist

  • My code follows the project's style guidelines
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • I did not edit CHANGELOG.md

Additional Notes

One known gap, documented in wiki/dsh.md rather than implemented: a baseURL hardcoded in dsh's settings/cordis.yml overrides $DEEPSEEK_BASE_URL and would silently bypass the proxy. The env-var path works (including a pre-existing DEEPSEEK_BASE_URL, which wrap dsh captures as the upstream). Durable settings-patching or a fail-loud guard would be the follow-up if that edge case matters.

@github-actions

github-actions Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

PR governance

This PR follows the template and is marked ready for human review.

@github-actions github-actions Bot added status: needs author action Pull request body or readiness checklist still needs author updates and removed status: needs author action Pull request body or readiness checklist still needs author updates labels Aug 13, 2026
@Zenjibad
Zenjibad marked this pull request as ready for review August 13, 2026 20:59
@github-actions github-actions Bot added the status: ready for review Pull request body is complete and the author marked it ready for human review label Aug 13, 2026

@JerrettDavis JerrettDavis left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is one blocking routing/credential-boundary issue on the latest head.

_resolve_openai_upstream() checks _is_deepseek_request(...) before _resolve_openai_upstream_base(...) (lines 1721–1723). That reverses the established precedence of the explicit x-headroom-base-url override. A custom OpenAI-compatible gateway request using a deepseek-* model—or carrying dsh’s identifying header—will be sent to DEEPSEEK_API_URL instead of the caller-selected gateway. Because the inbound authorization headers are forwarded, this can also send a gateway-scoped credential to the public DeepSeek endpoint.

Please resolve the explicit base URL first, then use DeepSeek detection only as the fallback before OPENAI_API_URL. Add regression cases for both detection forms with x-headroom-base-url present (DeepSeek model prefix and dsh header) so this credential boundary stays pinned.

The rest of the provider registration, launch environment, proxy compatibility check, and CLI structure looks coherent. Two small documentation cleanups can ride with the fix: add dsh to README’s supported unwrap list, and keep the runtime/docs wording aligned about the pnpm dsh fallback.

@github-actions github-actions Bot removed the status: ready for review Pull request body is complete and the author marked it ready for human review label Aug 14, 2026

@JerrettDavis JerrettDavis left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The requested routing correction is complete on the latest head. _resolve_openai_upstream now honors an explicit x-headroom-base-url before either DeepSeek signal, with regressions covering both a deepseek-* model and the harness header. This preserves custom/private gateway routing while retaining the intended public-DeepSeek fallback. The README wrap/unwrap lists and package-manager wording are also corrected.

I reran the affected routing, runtime, wrap CLI, registry, and backend regression modules: 74 passed. Focused Ruff and git diff --check also pass.

@github-actions github-actions Bot added the status: ready for review Pull request body is complete and the author marked it ready for human review label Aug 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

status: ready for review Pull request body is complete and the author marked it ready for human review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants