Menci / Menci/Floway

Gateway model discovery from Claude Desktop 3P inference never advertises the 1M context window

Open
#496 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
85
Forks
33
Avg merge
45m
Merged PRs (30d)
10

Description

Filed by Claude Code (Opus 5), running as an agent on behalf of @moooyo. Everything below is either directly observed on the reporter's machine or read out of main at ac2bbb0; I've marked clearly which parts are hypothesis.

Summary

When Claude Desktop's third-party (custom) inference is pointed at a Floway gateway, gateway model discovery never yields the 1M-context variant of a 1M-capable model. Every discovered model behaves as the default 200K context window; there is no way to select 1M from the Desktop client.

Environment

  • Floway: self-hosted; behavior below read from main @ ac2bbb0
  • Client: Claude Desktop 1.30096.5 on Windows 11, configured for third-party inference against the Floway gateway
  • Bundled CLI in that profile: claude-code 2.1.234
  • Upstream: an Anthropic-native upstream serving a model whose limits.max_context_window_tokens is ≥ 1,000,000

Expected

Discovery through Claude Desktop's 3P inference path advertises the 1M-capable model such that the 1M context window is selectable, the same way it is for the Claude Code CLI.

Actual

Only the default 200K context window is available. No [1m] variant is offered anywhere in the Desktop model picker.

Where it comes from

packages/gateway/src/data-plane/models/http.ts gates the whole Anthropic-native catalog shape — including the [1m] id rewrite — behind a claude-code/ User-Agent prefix:

https://github.com/Menci/Floway/blob/ac2bbb0/packages/gateway/src/data-plane/models/http.ts#L72-L96

const isClaudeCodeUserAgent = (userAgent: string | undefined): boolean =>
  userAgent?.startsWith('claude-code/') ?? false;

// ...
return Response.json(isClaudeCodeUserAgent(userAgent)
  ? toClaudeCodeCatalog(publicCatalog)
  : publicCatalog);

and toClaudeCodeCatalog is the only place the suffix is ever applied:

id: max !== undefined && max >= 1_000_000 ? `${model.id}[1m]` : model.id,

The file's own comment states why this is fatal rather than cosmetic — the suffix has to arrive on the wire, because the client will not synthesize it:

the [1m] suffix convention — append [1m] to a model id and the CLI switches that pick to the 1M-context window — only reaches the picker when the discovered id itself carries the suffix; the CLI does not synthesize the variant on discovered ids in gateway mode.

So any discovery client that does not present a claude-code/<version> User-Agent falls through to the generic PublicModelsResponse branch, whose ids never carry [1m]. limits.max_context_window_tokens is still 1000000 on that payload, but nothing downstream turns that number into a selectable 1M window.

Hypothesis (unverified): Claude Desktop's 3P gateway discovery is issued by the Electron app itself rather than by the bundled CLI, so it presents some other User-Agent and misses the prefix check. I was not able to capture the exact User-Agent string Desktop sends — I only have the client side here, not the gateway's request log. If it's useful, the reporter can capture it from the Floway instance and post it.

Worth noting the codebase already treats "is this Claude Code?" as two different tests: the strict claude-code/ prefix here, versus /^claude-cli\/\d+\.\d+\.\d+/i in answer-claude-code-probe.ts. Neither would match a Desktop-originated request.

Possible directions

Listing these as options, not as a preferred design — the right call depends on how you want discovery clients identified:

  1. Recognize Claude Desktop's discovery User-Agent alongside claude-code/.
  2. Stop keying the Anthropic-native catalog shape on User-Agent, and instead serve it when the request is unambiguously Anthropic-native discovery (e.g. path/anthropic-version based), keeping the superset only as the fallback.
  3. Make it an operator-visible switch (per API key or per gateway) so a client whose UA you don't yet recognize can still be served the [1m]-suffixed catalog.

Happy to supply any further detail from the client side — logs, exact Desktop build, or a reproduction against a clean upstream.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in packages/gateway/src/data-plane/models/http.ts, especially the User-Agent check and toClaudeCodeCatalog path, then confirm the User-Agent used by Claude Desktop's discovery request. Decide how that client should receive the Anthropic-native catalog and verify that discovery exposes the [1m] model variant without regressing the existing Claude Code behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
api, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.