Skip to content

hive/openai-server: held to OpenAI's spec and to Open Responses, checked in every test - #104

Merged
adiled merged 1 commit into
mainfrom
fix/openai-server-spec
Oct 28, 2026
Merged

adiled merged 1 commit into
mainfrom
fix/openai-server-spec

Conversation

@adiled

@adiled adiled commented Oct 28, 2026 •

Copy link
Copy Markdown
Owner

Why

wryme turned out to read a field of the Responses stream (output_item) that no server sends, and its tests passed because their fixtures agreed with the bug. The same could be true of hum: openai-server's tests checked it against what we thought OpenAI sends, not against the spec. This holds the hive to both specs it speaks, and makes the tests check every shape against them.

Specs

  • OpenAI's OpenAPI (openai/openai-openapi @ 26a2991), cut to the schemas the hive serves (402, 362 KB).
  • Open Responses (openresponses/openresponses @ 8907bc3, release 2026-04-24), whole.
  • bun spec/fetch.ts pulls both again at their pinned commits.

Checked in every test

test/spec.ts (ajv) validates against either spec. The e2e client checks every request it sends against the route's request schema and every answer, error body and stream event it hears against both specs (each event by its type). The seven HTTP cases of the Open Responses compliance suite run as the suite writes them, with its validators.

What the specs found

Spec says hum did Now
a deleted response is object: "response.deleted" "response" "response.deleted"
chat system_fingerprint is a string, optional null everywhere left out
a response requires access_programs, cache_write_tokens (OpenAI) and completed_at, background, service_tier, top_logprobs, the penalties, max_tool_calls, safety_identifier, prompt_cache_key, numeric temperature/top_p (Open Responses) missing or null the request's settings or the spec's defaults; cache writes from the nurse's counts
an echoed function tool has description, parameters, strict echoed as given filled
response.failed error.code is one of a fixed list hum's own codes mapped; hum's code kept as type
a failed mcp_call.error is an object (mcp_tool_execution_error, …) a string the spec's shape, on responses and chat mcp_calls; read back as its words
item_reference / compaction input items silently dropped refused with a 400

Kept on purpose

  • mcp_call items keep OpenAI's name, since OpenAI's clients read them; Open Responses would want a prefixed type, so its check sets them aside.
  • Extensions: reasoning_content and mcp_calls on chat messages, X-Hum-Sid.
  • Not served: WebSocket and /responses/compact.

Testing

  • openai-server: 80 pass (e2e against a real humd included), type check clean. New: a streamed function call, a streamed and a failed server-run tool, a cut-short response, a failure, delete then retrieve, a streamed chat tool call and failure, the refused input items, and the seven compliance cases.

Official compliance runner

The Open Responses runner (bin/compliance-test.ts @ 8907bc3), run unchanged against this branch under the e2e harness (real humd, scripted upstream, gpt-lab): every case for what hum serves passes, 8 of 8: Basic Text Response, Streaming Response, System Prompt, Multi-turn Conversation, Image Input, Tool Calling, Assistant Message Phase, Response Output Phase Schema. The other 9 need what hum does not serve: the WebSocket transport (6) and /responses/compact (3).

…ked in every test

The specs ride in spec/, pinned: OpenAI's OpenAPI cut to what the hive
serves, and Open Responses whole; `bun spec/fetch.ts` pulls them again.
The end-to-end client checks every request it sends, and every answer
and stream event it hears, against both, so a test cannot pass on a
shape no client would send or take. The seven HTTP cases of the Open
Responses compliance suite run among them, as the suite writes them.

What the specs found, and how it is now:
- a deleted response says `object: "response.deleted"`;
- chat leaves `system_fingerprint` out rather than sending null;
- a response carries every field both specs require, the request's
  settings or their defaults, `completed_at` once complete, and the
  tokens a cache was written with;
- an echoed function tool carries `description`, `parameters` and
  `strict`;
- `response.failed` says an error code from the spec's list, its own
  code kept as `type`;
- a call the server ran that failed says so as the spec shapes it, an
  `mcp_tool_execution_error`, in a response and on a chat message, and
  is read back as its words;
- `item_reference` and `compaction` input items, whose words are kept
  elsewhere, are refused rather than silently dropped.

`mcp_call` items stay as OpenAI names them, since OpenAI's clients read
them; Open Responses would want a prefixed name.
@adiled
adiled merged commit 65a2174 into main Oct 28, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant