Skip to content

feat(cli): add headroom wrap auggie - #2720

Draft
rNoz wants to merge 7 commits into
headroomlabs-ai:mainfrom
rNoz:rnoz/wrap-auggie
Draft

feat(cli): add headroom wrap auggie#2720
rNoz wants to merge 7 commits into
headroomlabs-ai:mainfrom
rNoz:rnoz/wrap-auggie

Conversation

@rNoz

@rNoz rNoz commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Description

Add headroom wrap auggie, which routes an AugmentCode Auggie session through the local Headroom proxy with a single command, mirroring the shipped wrap droid / wrap copilot.

Auggie reads its tenant URL from its OAuth session (~/.augment/session.json) and calls that host for every request. This command rewrites ONLY the session tenantURL to the local proxy (the access token is preserved byte-for-byte), passes the rewritten session to Auggie via AUGMENT_SESSION_AUTH, and starts the proxy in Auggie mode. The proxy forwards every Auggie tenant path verbatim to the real tenant and tags the POST /chat-stream inference call as the augment provider in /stats. All models (including Prism routing) stay on the user's Augment subscription, with no API keys and no persistent config edits.

Auggie's tenant wire is Augment-proprietary (/chat-stream uses a bespoke request/response shape, not Anthropic/OpenAI), so this first version forwards inference bodies unchanged. The value delivered is the single-command redirect plus proxy observability. Request compression and output-token shaping for the Augment shape are follow-ups.

Closes #2719

Type of Change

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

Changes Made

  • headroom/proxy/models.py: add ProxyConfig.augment_api_url: str | None.
  • headroom/proxy/server.py: thread augment_api_url through the /health config report, _proxy_config_from_env (AUGMENT_TARGET_API_URL), the argparse --augment-api-url flag, and the CLI config build.
  • headroom/cli/proxy.py: add the --augment-api-url click option (env AUGMENT_TARGET_API_URL).
  • headroom/providers/proxy_routes.py: when augment_api_url is set, register POST /chat-stream -> handle_passthrough(request, <tenant>, "chat-stream", "augment"). Registered only when configured (mirrors the Bedrock precedent). The upstream is an explicit argument, not resolved from a client-controllable header, so there is no routing-header spoofing vector to harden against.
  • headroom/providers/proxy_targets.py: select_passthrough_base_url returns the Augment tenant upstream first when set, so every other Auggie REST call (/get-models, /agents/list-remote-tools, /settings/get-mcp-*-configs, /find-missing) reaches the tenant via the catch-all.
  • headroom/providers/augment/ (new): runtime.py (resolve_augment_upstream, build_redirected_session, load_session with defensive errors, proxy_base_url), __init__.py.
  • headroom/cli/wrap.py: new @wrap.command auggie. Reads the session (friendly errors on missing/malformed), rewrites tenantURL, scrubs inherited AUGMENT_* env, sets AUGMENT_SESSION_AUTH, and launches via _launch_tool(..., agent_type="augment", augment_api_url=<tenant>). augment_api_url is threaded through _launch_tool -> _ensure_proxy -> _start_proxy (new optional param, default None, so all other wrappers are unchanged). A reuse guard refuses to reuse a non-Auggie proxy on the target port, since its missing /chat-stream route would misroute Auggie, and points at a dedicated port instead.
  • Docs: new docs/content/docs/auggie.mdx (registered in meta.json); README.md feature list and compatibility matrix; llms.txt. No CHANGELOG.md edit, release-please generates that entry from this PR title.
  • Tests: tests/test_cli/test_wrap_auggie.py (16) plus /chat-stream route present/absent and passthrough-forward cases in tests/test_provider_proxy_routes.py, and an Augment target case in tests/test_provider_proxy_targets.py.

Testing

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

Test Output

$ uv run pytest tests/test_cli/test_wrap_auggie.py tests/test_provider_proxy_routes.py tests/test_provider_proxy_targets.py
52 passed (re-verified 2026-08-04 after merging current upstream/main)

$ uv run ruff format --check . && uv run ruff check . && uv run mypy headroom
clean on all touched files

Real Behavior Proof

  • Environment: macOS, Auggie @augmentcode/auggie (interactive), model haiku4.5 (cheapest), Headroom current-tree build, isolated proxy port 8790 (not the shared 8787).
  • Exact command / steps: headroom wrap auggie --port 8790 -- -m haiku4.5, then at the Auggie prompt: Reply with exactly the single word: PONG.
  • Observed result: wrap output showed Auggie tenant URL rewritten -> http://127.0.0.1:8790 and Auggie tenant upstream: https://xlb.api.augmentcode.com; Auggie replied PONG. GET http://127.0.0.1:8790/stats showed "by_provider": {"augment": 2} and "agent_usage" attributing both requests to the augment provider, confirming real subscription traffic flowed through the proxy via the rewritten session. The model shows as passthrough:chat-stream because v1 does not parse Auggie's proprietary response for the real model id or token counts, which is the documented follow-up. Session-integrity check: md5 of ~/.augment/session.json was unchanged before and after a wrapped run, and its tenantURL remained the real tenant, confirming the env-only redirect writes nothing to disk.
  • Not tested: a BYOK / third_party_override model (no third-party provider key available in the test env); request/response compression (out of scope for v1, proprietary wire); streaming UX beyond the buffered response shown above (token-by-token streaming and JSON-lines usage parsing is a follow-up).

A real session, a screenshot of my terminal, how AugmentCode/Auggie has been supported, the real proofs:
image

Detection in dashboard (telemetry):
image

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, it is generated by release-please from my Conventional Commit PR title

Additional Notes

One logical change, minimal diff, mirrors wrap droid exactly. No changes to default proxy behavior, since the route and target selection are gated on augment_api_url. No persistent config writes and no unwrap auggie needed, since nothing durable is written. No credential is stored, logged, or fabricated, the token is preserved byte-for-byte and forwarded untouched.

Follow-ups not in this PR: parsing the /chat-stream JSON-lines response for the real model id, token usage, and cost so /stats shows real tokens and cost; streaming /chat-stream instead of buffering; an Augment-shape request compressor and output-token shaping (the response reports tool_definitions_tokens ~= 34k per turn).

@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

PR governance

This PR does not yet satisfy the required template fields:

  • Missing required section Runtime Rollout Safety.

Please update the PR body, or move the PR back to draft while it is still in progress.

@github-actions github-actions Bot added the status: needs author action Pull request body or readiness checklist still needs author updates label Aug 2, 2026
@codecov-commenter

codecov-commenter commented Aug 2, 2026

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Comment thread tests/test_cli/test_wrap_auggie.py Fixed
@github-actions github-actions Bot added status: ci failing Required or reported CI checks are failing and removed status: ci failing Required or reported CI checks are failing labels Aug 2, 2026
@rNoz
rNoz force-pushed the rnoz/wrap-auggie branch from 6951d34 to eae3996 Compare August 2, 2026 17:30
@github-actions github-actions Bot added status: ci failing Required or reported CI checks are failing and removed status: needs author action Pull request body or readiness checklist still needs author updates labels Aug 2, 2026
@rNoz
rNoz force-pushed the rnoz/wrap-auggie branch from eae3996 to fc97930 Compare August 2, 2026 18:15
@github-actions github-actions Bot removed the status: ci failing Required or reported CI checks are failing label Aug 2, 2026
@github-actions github-actions Bot added the status: has conflicts Pull request has merge conflicts with the base branch label Aug 3, 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 dedicated-proxy path is thoughtfully isolated by tenant, but --no-proxy bypasses that safety check entirely. The preflight guard is wrapped in if not no_proxy and _check_proxy(port), and _ensure_proxy only warns when no_proxy=True; it does not compare augment_api_url. The wrapper then injects the OAuth-bearing session with tenantURL=http://127.0.0.1:<port> regardless. Thus headroom wrap auggie --no-proxy can send the Augment access token to a non-Auggie Headroom proxy (which will route /chat-stream elsewhere/404) or any unrelated local service on that port, contradicting the docs’ promise that a non-Auggie proxy is rejected. Please require an existing healthy Headroom proxy whose normalized config.augment_api_url exactly matches the resolved tenant before launching in --no-proxy mode; otherwise fail closed with a dedicated-port instruction. Add regressions for no service, non-Headroom service/unavailable config, non-Auggie config, wrong tenant, and matching tenant. The branch is also currently conflicting with main; once this safety boundary is fixed, resolve the drift while preserving main’s newer proxy-target/routing changes. Since this remains a draft, I am not approving it as merge-ready.

@vercel

vercel Bot commented Aug 4, 2026

Copy link
Copy Markdown

Someone is attempting to deploy a commit to the Headroom Labs Team on Vercel.

A member of the Team first needs to authorize it.

@github-actions github-actions Bot added status: ci failing Required or reported CI checks are failing and removed status: has conflicts Pull request has merge conflicts with the base branch labels Aug 4, 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.

Re-reviewed the refreshed head after merging current main; the focused Auggie suite is green locally (52 tests), and the merge resolution is clean. The prior security blocker remains: AUGMENT_SESSION_AUTH contains the OAuth-bearing redirected session, while the wrapped child can still receive --no-proxy (or another argument path that prevents the local proxy from being used). That can leave the real Augment tenant URL paired with the injected credential-bearing environment value. Please reject proxy-bypass arguments for wrap auggie, or otherwise prove the credential-bearing redirected session cannot be sent directly to the tenant. A focused regression test for the bypass case would make the invariant explicit.

@JerrettDavis JerrettDavis added status: needs author action Pull request body or readiness checklist still needs author updates status: code changes requested status: has conflicts Pull request has merge conflicts with the base branch and removed status: ci failing Required or reported CI checks are failing labels Aug 12, 2026
@github-actions github-actions Bot added status: ci failing Required or reported CI checks are failing and removed status: has conflicts Pull request has merge conflicts with the base branch status: ci failing Required or reported CI checks are failing labels Aug 13, 2026
@rNoz

rNoz commented Aug 14, 2026

Copy link
Copy Markdown
Contributor Author

I'll work on these minor improvements when the other 3 PRs I have accepted for 3-5 weeks are merged.

@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.

Re-reviewed exact head 4af4b2a after the main sync. The security invariant remains unresolved: wrap auggie still accepts --no-proxy and still injects the OAuth-bearing redirected AUGMENT_SESSION_AUTH, allowing the child to launch without establishing the local proxy path. Please reject that combination (or otherwise prove direct tenant use is impossible) and add the focused regression requested previously.

@rNoz
rNoz force-pushed the rnoz/wrap-auggie branch from 4af4b2a to 509f0ff Compare August 21, 2026 12:00
rNoz added 2 commits August 22, 2026 00:33
Route an AugmentCode Auggie session through the local Headroom proxy with a
single command, mirroring `headroom wrap droid` / `wrap copilot`.

Auggie reads its tenant URL from its OAuth session (~/.augment/session.json) and
calls that host for every request. `wrap auggie` rewrites ONLY the session
`tenantURL` to the local proxy (the access token is preserved byte-for-byte),
passes the rewritten session via AUGMENT_SESSION_AUTH (env-only, so the token is
never exposed on the process command line), and forwards every tenant path
verbatim to the real tenant. The `POST /chat-stream` inference call gets an
explicitly-registered route so its telemetry is tagged the `augment` provider in
/stats; the upstream is an explicit argument (not a client header), so there is
no routing-header spoofing vector. All models, including Prism routing, stay on
the user's Augment subscription with no API keys and no persistent config edits.

Ports are automatic: reuse a running Auggie proxy for the same tenant, otherwise
start a dedicated proxy on the next free port (never disrupt a shared `wrap
claude` or a different tenant, never fail asking for `--port`).

Auggie's tenant wire is Augment-proprietary, so v1 forwards inference bodies
unchanged (redirect + telemetry/observability); request compression and
output-shaping for the Augment shape are follow-ups. New `--augment-api-url`
proxy option (env AUGMENT_TARGET_API_URL) plus ProxyConfig.augment_api_url
register the passthrough only when configured, so all other proxy behavior is
unchanged (mirrors the --bedrock-api-url precedent). New provider module
headroom/providers/augment/ with defensive session loading (friendly errors on
missing/malformed session) and inherited-AUGMENT_*-env scrubbing.

Also fixes a shared `_launch_tool` cosmetic bug: on proxy port fallback the
printed banner now matches the corrected child env (both point at the live port).

Tests: tests/test_cli/test_wrap_auggie.py (session rewrite, upstream precedence,
env hygiene, automatic port fallback + same-tenant reuse, friendly errors) plus
route present/absent, passthrough-forward, and malformed-body passthrough cases.
…ie docs

CI added a no-manual-changelog guard: release-please generates CHANGELOG.md
from the Conventional Commit PR title, so a hand-written entry fails the
gate. Removed it; the auggie feature entry will appear automatically in the
next release PR.

docs/content/docs/auggie.mdx also had a stray trailing `</content>` line
with no matching opening tag, which fumadocs-mdx rejects as invalid MDX and
fails the Next.js docs build. Removed it.
rNoz added 5 commits August 22, 2026 00:33
Codecov flagged patch-coverage gaps on this PR. Added direct coverage for:

- _start_proxy's augment_api_url wiring (forwarding --augment-api-url to
  the actual proxy subprocess), which no existing test exercised since
  every wrap-auggie test mocks _start_proxy away.
- load_session raising ValueError when the session JSON parses but is not
  a dict (list/scalar), the one load_session error path with no test.
- The CLI-level ValueError -> click.ClickException translation for a
  malformed session, previously only exercised at the load_session()
  unit level, not through the full `wrap auggie` command.

Rebased onto the latest upstream/main.
… wrap auggie

Closes the rest of the Codecov gap on this PR:

- _launch_tool's port-fallback branch (rewriting env and the printed
  env_vars_display lines when _ensure_proxy falls back to a different
  port than requested) had no direct test.
- resolve_augment_upstream can return an empty string even when
  load_session's truthiness check passed, if tenantURL strips down to
  empty (all slashes). Added the CLI-level test for the friendly error
  this produces.

Also fixes a live CodeQL / incomplete-url-substring-sanitization finding
(github.com/headroomlabs-ai/headroom/security/code-scanning/158): the
missing-binary test asserted a bare hostname substring
("docs.augmentcode.com" in result.output), which the query flags as a
potential hostname-validation anti-pattern regardless of whether the
code is actually validating anything. Asserting the full literal URL
instead resolves it.

100% patch coverage on this PR's own diff, verified locally by
cross-referencing exact added line numbers against coverage --cov-report.
…se positives

Same fix as the sibling wrap-droid-factory PR. CodeQL's security-extended
pack flags these test assertions as if they were security-relevant URL
validation, even after using the full literal URL instead of a bare
hostname fragment (both trigger it, the query pattern-matches on any
domain-shaped string substring check regardless of scheme prefix).

These are plain assertions on captured CLI stdout in a test, not a trust
decision about an untrusted URL: the documented false-positive case for
this query (no attacker-controlled input reaches these checks). Suppressed
with the current-format inline annotation (# codeql[rule-id] on the line
before the flagged line; the legacy same-line "lgtm[...]" syntax is
deprecated and does not work with GitHub's current code scanning).
…ust via suppression comment

Same root cause as the sibling wrap-droid-factory PR: the inline
# codeql[...] suppression comment did not actually suppress the alert
(this repo evidently restricts in-code alert dismissal, so a
contributor's suppression comment is silently ignored). Fixed
structurally instead: moved the two flagged URL literals to named
constants / an f-string, which are different AST nodes than the
StringLiteral the query's Compare-node check matches on.
Codecov's last report showed 1 partial line (98.9% patch coverage).
Traced to two untested branches via --cov-branch:

- _start_proxy's `if augment_api_url:` guard only had the True side
  tested (forwarding --augment-api-url). Added the False side: called
  without augment_api_url, the flag must not appear in the subprocess cmd.
- The port-fallback block only had the "found a different port" branch
  tested. Added the case where _find_available_port returns the same
  port back (no free port found nearby): no fallback message printed,
  requested port kept.

100% patch coverage now, verified locally with branch coverage enabled.
@rNoz
rNoz force-pushed the rnoz/wrap-auggie branch from 509f0ff to fadfe10 Compare August 21, 2026 22:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

status: code changes requested status: needs author action Pull request body or readiness checklist still needs author updates

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] headroom wrap auggie (AugmentCode Auggie CLI)

4 participants