Skip to content

feat: support base path prefix for OpenAI and Anthropic API targets#1369

Merged
lpcox merged 6 commits intomainfrom
copilot/fix-circular-dependency-issue
Mar 19, 2026
Merged

feat: support base path prefix for OpenAI and Anthropic API targets#1369
lpcox merged 6 commits intomainfrom
copilot/fix-circular-dependency-issue

Conversation

Copy link
Contributor

Copilot AI commented Mar 19, 2026

Summary

Fixes the issue where OPENAI_BASE_URL or ANTHROPIC_BASE_URL values with a required path prefix (e.g. Databricks /serving-endpoints, Azure OpenAI /openai/deployments/<name>) silently fail because the api-proxy sidecar drops the path component when forwarding requests.

Root Cause

proxyRequest() in containers/api-proxy/server.js used req.url directly as the upstream path (e.g. /v1/chat/completions) with no way to prepend a base path. When a custom target host requires a path prefix, the request lands at the wrong endpoint and returns 404.

Changes

  • containers/api-proxy/server.js

    • Adds normalizeBasePath(rawPath) helper that ensures a leading / and strips trailing /
    • Extracts buildUpstreamPath(reqUrl, targetHost, basePath) as a pure helper that constructs the full upstream path; used by proxyRequest()
    • Reads OPENAI_API_BASE_PATH and ANTHROPIC_API_BASE_PATH env vars (default "")
    • Adds optional basePath 6th parameter to proxyRequest(); prepends it to the upstream request path via buildUpstreamPath()
    • Passes the base paths when calling proxyRequest() for the OpenAI and Anthropic handlers
    • Logs base paths at startup
    • Exports normalizeBasePath and buildUpstreamPath for unit testing
  • containers/api-proxy/server.test.js

    • 10 tests for normalizeBasePath
    • 19 tests for buildUpstreamPath covering: no base path, Databricks /serving-endpoints, Azure OpenAI multi-segment deployment paths, Anthropic custom base paths, query string preservation, URL-encoded characters, hash fragment handling, and real-world standard endpoints
  • src/types.ts — adds openaiApiBasePath?: string and anthropicApiBasePath?: string to WrapperConfig

  • src/cli.ts — adds --openai-api-base-path <path> and --anthropic-api-base-path <path> options; maps them into config (also readable from OPENAI_API_BASE_PATH / ANTHROPIC_API_BASE_PATH env vars)

  • src/docker-manager.ts — passes the base path env vars to the api-proxy container and logs them at debug level

Usage Example

# Databricks serving endpoint
awf --enable-api-proxy \
    --openai-api-target stone-dataplatform-production.cloud.databricks.com \
    --openai-api-base-path /serving-endpoints \
    --allow-domains stone-dataplatform-production.cloud.databricks.com \
    -- your-command

# Azure OpenAI deployment
awf --enable-api-proxy \
    --openai-api-target myresource.openai.azure.com \
    --openai-api-base-path /openai/deployments/gpt-4 \
    --allow-domains myresource.openai.azure.com \
    -- your-command

💬 Send tasks to Copilot coding agent from Slack and Teams to turn conversations into code. Copilot posts an update in your thread when it's finished.

Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
@github-actions
Copy link
Contributor

⚠️ Coverage Regression Detected

This PR decreases test coverage. Please add tests to maintain coverage levels.

Overall Coverage

Metric Base PR Delta
Lines 86.05% 86.11% 📈 +0.06%
Statements 85.97% 86.03% 📈 +0.06%
Functions 86.13% 86.13% ➡️ +0.00%
Branches 79.21% 78.89% 📉 -0.32%
📁 Per-file Coverage Changes (1 files)
File Lines (Before → After) Statements (Before → After)
src/docker-manager.ts 87.4% → 87.7% (+0.25%) 86.8% → 87.0% (+0.23%)

Coverage comparison generated by scripts/ci/compare-coverage.ts

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

#1370)

* Initial plan

* fix: add tests for api-base-path feature to fix coverage regression

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
@github-actions
Copy link
Contributor

github-actions bot commented Mar 19, 2026

✅ Coverage Check Passed

Overall Coverage

Metric Base PR Delta
Lines 86.05% 86.23% 📈 +0.18%
Statements 85.97% 86.15% 📈 +0.18%
Functions 86.13% 86.13% ➡️ +0.00%
Branches 79.21% 79.38% 📈 +0.17%
📁 Per-file Coverage Changes (1 files)
File Lines (Before → After) Statements (Before → After)
src/docker-manager.ts 87.4% → 88.1% (+0.73%) 86.8% → 87.5% (+0.70%)

Coverage comparison generated by scripts/ci/compare-coverage.ts

@lpcox
Copy link
Collaborator

lpcox commented Mar 19, 2026

@copilot can you make sure that there are robust test cases for preserving path info in custom api targets?

@github-actions

This comment has been minimized.

@github-actions
Copy link
Contributor

Smoke Test Results

Test Result
GitHub MCP (last 2 merged PRs)
Playwright (github.com title contains "GitHub")
File write + verify
Bash tool

Last 2 merged PRs:

Overall: PASS

📰 BREAKING: Report filed by Smoke Copilot for issue #1369

@github-actions
Copy link
Contributor

Chroot Version Comparison Results

Runtime Host Version Chroot Version Match?
Python Python 3.12.13 Python 3.12.3 ❌ NO
Node.js v24.14.0 v20.20.1 ❌ NO
Go go1.22.12 go1.22.12 ✅ YES

Result: FAILED — Python and Node.js versions differ between host and chroot environments.

Tested by Smoke Chroot for issue #1369

Copy link
Contributor Author

Copilot AI commented Mar 19, 2026

@copilot can you make sure that there are robust test cases for preserving path info in custom api targets?

Added buildUpstreamPath(reqUrl, targetHost, basePath) as a pure exported helper that encapsulates the path-construction logic, then added 19 robust tests for it in commit 1365005.

Tests cover:

  • No base path — request path and query string pass through unchanged
  • Databricks /serving-endpoints — prepended correctly for chat completions, models, embeddings, with query strings preserved
  • Azure OpenAI /openai/deployments/gpt-4 — multi-segment paths prepended, api-version query param preserved
  • Anthropic custom paths (e.g. /anthropic) — messages endpoint and query params
  • Edge cases — URL-encoded characters (%2F preserved), hash fragments (dropped, as HTTP doesn't forward them), empty query string markers

@github-actions
Copy link
Contributor

Smoke test results — Run 23311114087

Overall: PASS

💥 [THE END] — Illustrated by Smoke Claude for issue #1369

@github-actions

This comment has been minimized.

@lpcox lpcox marked this pull request as ready for review March 19, 2026 18:57
@lpcox lpcox requested a review from Mossaka as a code owner March 19, 2026 18:57
Copilot AI review requested due to automatic review settings March 19, 2026 18:57
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds support for API targets that require a path prefix (e.g., Databricks, Azure-style gateways) by allowing OpenAI/Anthropic requests to be forwarded with an optional upstream base path, configured via CLI/env and propagated into the api-proxy sidecar.

Changes:

  • Add OPENAI_API_BASE_PATH / ANTHROPIC_API_BASE_PATH support in the api-proxy and helper functions for upstream path construction.
  • Expose new CLI flags and config fields for specifying base path prefixes, and pass them into the api-proxy container env.
  • Add/extend unit tests for upstream path building and docker-compose env propagation.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
containers/api-proxy/server.js Adds base-path normalization and upstream path construction; wires base paths into OpenAI/Anthropic proxy handlers.
containers/api-proxy/server.test.js Adds unit tests for normalizeBasePath and buildUpstreamPath.
src/types.ts Extends WrapperConfig with optional base path properties for OpenAI/Anthropic.
src/cli.ts Adds --openai-api-base-path / --anthropic-api-base-path flags and maps them into config.
src/docker-manager.ts Propagates base path env vars into api-proxy container and logs configuration.
src/docker-manager.test.ts Adds tests for base path env propagation (and minor UID/GID validation test coverage improvements).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

lpcox and others added 3 commits March 19, 2026 12:01
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
…1372)

* Initial plan

* fix: update flatted to 3.4.2 to resolve high severity prototype pollution vulnerability

Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
@github-actions
Copy link
Contributor

Smoke Test Results — Run #23312074359

✅ GitHub MCP — Last 2 merged PRs: #1372 "fix: resolve high severity flatted prototype pollution vulnerability", #1370 "[WIP] Fix the failing GitHub Actions workflow for test coverage report"
✅ Playwright — github.com title contains "GitHub"
✅ File Write — /tmp/gh-aw/agent/smoke-test-copilot-23312074359.txt created
✅ Bash — File verified via cat

Overall: PASS | Author: @Copilot | Assignees: @lpcox @Copilot

📰 BREAKING: Report filed by Smoke Copilot for issue #1369

@github-actions
Copy link
Contributor

Chroot Version Comparison Results

Runtime Host Version Chroot Version Match?
Python Python 3.12.13 Python 3.12.3
Node.js v24.14.0 v20.20.1
Go go1.22.12 go1.22.12

Result: FAILED — Python and Node.js versions differ between host and chroot environments.

Tested by Smoke Chroot for issue #1369

@github-actions
Copy link
Contributor

🏗️ Build Test Suite Results

Ecosystem Project Build/Install Tests Status
Bun elysia 1/1 passed ✅ PASS
Bun hono 1/1 passed ✅ PASS
C++ fmt N/A ✅ PASS
C++ json N/A ✅ PASS
Deno oak N/A 1/1 passed ✅ PASS
Deno std N/A 1/1 passed ✅ PASS
.NET hello-world N/A ✅ PASS
.NET json-parse N/A ✅ PASS
Go color passed ✅ PASS
Go env passed ✅ PASS
Go uuid passed ✅ PASS
Java gson 1/1 passed ✅ PASS
Java caffeine 1/1 passed ✅ PASS
Node.js clsx passed ✅ PASS
Node.js execa passed ✅ PASS
Node.js p-limit passed ✅ PASS
Rust fd 1/1 passed ✅ PASS
Rust zoxide 1/1 passed ✅ PASS

Overall: 8/8 ecosystems passed — ✅ PASS

Generated by Build Test Suite for issue #1369 ·

@github-actions
Copy link
Contributor

🔮 The oracle records this smoke pass for PR #1369.

  • PR titles: "fix: resolve high severity flatted prototype pollution vulnerability"; "[WIP] Fix the failing GitHub Actions workflow for test coverage report"
    1. GitHub MCP last 2 merged PRs: ✅
    1. safeinputs-gh PR query: ❌ (tool not available in this runtime)
    1. Playwright github.com title contains "GitHub": ✅
    1. Tavily search result check: ❌ (Tavily MCP server not available)
  • 5-6) File write + cat verify: ✅
    1. github-discussion-query + discussion comment: ❌ (tool not available)
    1. npm ci && npm run build: ✅
  • Overall status: FAIL

🔮 The oracle has spoken through Smoke Codex

Warning

⚠️ Firewall blocked 2 domains

The following domains were blocked by the firewall during workflow execution:

  • ab.chatgpt.com
  • registry.npmjs.org

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "ab.chatgpt.com"
    - "registry.npmjs.org"

See Network Configuration for more information.

@github-actions
Copy link
Contributor

Smoke Test Results

✅ GitHub MCP: #1372 fix: resolve high severity flatted prototype pollution vulnerability, #1370 [WIP] Fix the failing GitHub Actions workflow for test coverage report
✅ Playwright: github.com title contains "GitHub"
✅ File write: /tmp/gh-aw/agent/smoke-test-claude-23312074327.txt created
✅ Bash verify: file contents confirmed

Overall: PASS

💥 [THE END] — Illustrated by Smoke Claude for issue #1369

@lpcox lpcox merged commit 9a1d4d3 into main Mar 19, 2026
60 checks passed
@lpcox lpcox deleted the copilot/fix-circular-dependency-issue branch March 19, 2026 19:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants