Skip to content

[Feature]: Pre-adapter request transform hook (custom handlers on OcxParsedRequest) #3459

Description

@drakonkat

What are you trying to accomplish?

We are looking to run request-level optimizations such as pxpipe (converting large text blocks into images for vision-capable models to optimize token consumption) and headroom (context compression) in front of model routing.

Today, OpenCodeX acts as the universal routing layer to multiple providers (OpenAI, Anthropic, Google Antigravity, etc.). Having a way to plug in pre-adapter request transforms directly on the normalized request would allow these optimizations to work seamlessly across any provider.

What prevents this today?

Attempting to chain external proxy tools via baseUrl works for OpenAI-compatible wires, but completely breaks when routing to other providers—most notably Google / Gemini Antigravity (adapters/google.ts).

By the time an upstream HTTP request leaves OpenCodeX, adapter.buildRequest(parsed, ...) has already translated the request into that provider's proprietary wire format. An external proxy sitting on baseUrl would need to deconstruct, re-parse, and re-serialize Google's wire protocol, Anthropic's wire protocol, and Responses format separately.

In contrast, before buildRequest is invoked in server/responses/core.ts, OpenCodeX has already parsed the incoming turn into a single, provider-agnostic representation: OcxParsedRequest.

What should OpenCodex do?

Expose a clean pre-adapter request transform hook (or custom handler interface) that operates on OcxParsedRequest before adapter.buildRequest is called.

Key requirements:

  1. Single normalized format: Operates on OcxParsedRequest so transforms don't need to know anything about vendor wire formats.
  2. Applied once per turn: Executed once for the turn rather than re-running on every internal retry/continuation/replay in server/responses/core.ts that re-invokes buildRequest.
  3. Model & Provider Awareness: The transform receives context (providerName, modelId, providerConfig). This allows tools like pxpipe to inspect whether the target model accepts image input (reusing modelAcceptsImageInput from vision/eligibility.ts).

Example usage or interface

A lightweight transform handler signature:

export type RequestTransform = (
  parsed: OcxParsedRequest,
  ctx: {
    providerName: string;
    modelId: string;
    providerConfig: OcxProviderConfig;
  }
) => OcxParsedRequest | Promise<OcxParsedRequest>;

Configurable via ~/.opencodex/config.json by pointing to a custom TS/JS handler script (either globally or scoped per provider / model):

{
  "requestTransforms": [
    "./transforms/pxpipe-vision.ts"
  ],
  "providers": {
    "google-antigravity": {
      "requestTransforms": ["./transforms/custom-handler.ts"]
    }
  }
}

Alternatives or workarounds

  1. Chaining standalone proxies before/after ocx: Fails due to disparate downstream wire formats (e.g. Google's format).
  2. Private fork: Feasible but introduces ongoing merge maintenance for what could be a general-purpose extension point.

Additional context

This is functionally the inverse of OpenCodeX's existing vision/ sidecar (which converts images to text for non-vision models): here, text transforms into images for vision models or is compressed before routing.

Would you be open to a PR introducing this pre-adapter transform hook? If so, what architecture/interface would you prefer for registering custom handlers?

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestproviderProvider adapters, OpenAI-compat presets, upstream API quirks

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions