Python 88.3%
TypeScript 7.6%
Shell 4.1%
1"""Smoke tests for the OpenAI Responses API family (responses, conversations, input_tokens, compact, background).23Cheap: gpt-5.4-nano, "Reply with OK.", max_output_tokens <= 32 (~$0.001 per full run). Compaction is the most expensive4call (~$0.0003) and is gated behind RUN_EXPENSIVE_TESTS.5"""6from __future__ import annotations78import json9import time1011import pytest1213PING = "Reply with OK."141516def _text(resp: dict) -> str:17 return "".join(c.get("text", "") for i in resp["output"] if i["type"] == "message" for c in i["content"] if c["type"] == "output_text")181920@pytest.fixture(scope="module")21def stored_response(openai, models):22 st, body, _ = openai("POST", "/v1/responses", {"model": models["openai"], "input": PING, "max_output_tokens": 32}, est_cost_usd=0.00002, note="test_responses minimal")23 assert st == 200, body24 yield body25 openai("DELETE", f"/v1/responses/{body['id']}", note="test_responses cleanup")262728def test_minimal_response_shape(stored_response):29 r = stored_response30 assert r["object"] == "response" and r["status"] == "completed"31 assert "OK" in _text(r)32 usage = r["usage"]33 assert usage["total_tokens"] == usage["input_tokens"] + usage["output_tokens"]34 assert "reasoning_tokens" in usage["output_tokens_details"] and "cached_tokens" in usage["input_tokens_details"]35 # fields the docs do not list but the API returns (2026-09-18)36 for extra in ("billing", "tool_usage"):37 assert extra in r, f"{extra} disappeared from the live Response object"383940def test_input_tokens_matches_usage(openai, models, stored_response):41 st, body, _ = openai("POST", "/v1/responses/input_tokens", {"model": models["openai"], "input": PING}, note="test_responses input_tokens")42 assert st == 200 and body["object"] == "response.input_tokens"43 assert body["input_tokens"] == stored_response["usage"]["input_tokens"]444546def test_retrieve_and_input_items(openai, stored_response):47 rid = stored_response["id"]48 st, body, _ = openai("GET", f"/v1/responses/{rid}", note="test_responses retrieve")49 assert st == 200 and body["id"] == rid50 st, items, _ = openai("GET", f"/v1/responses/{rid}/input_items?limit=5", note="test_responses input_items")51 assert st == 200 and items["object"] == "list" and items["data"][0]["type"] == "message"525354def test_streaming_event_sequence(openai, models):55 st, lines, _ = openai("POST", "/v1/responses", {"model": models["openai"], "input": PING, "max_output_tokens": 32, "stream": True}, stream=True, est_cost_usd=0.00002, note="test_responses stream")56 assert st == 20057 types, seqs = [], []58 for line in lines:59 if line.startswith("data:"):60 d = json.loads(line[5:])61 types.append(d["type"])62 seqs.append(d["sequence_number"])63 assert types[0] == "response.created" and types[-1] == "response.completed"64 assert "response.output_text.delta" in types and "response.output_item.done" in types65 assert seqs == list(range(len(seqs)))666768def test_previous_response_id_chain(openai, models, stored_response):69 st, body, _ = openai("POST", "/v1/responses", {"model": models["openai"], "input": "Reply with OK again.", "previous_response_id": stored_response["id"], "max_output_tokens": 32}, est_cost_usd=0.00002, note="test_responses chain")70 assert st == 200 and body["previous_response_id"] == stored_response["id"]71 assert body["usage"]["input_tokens"] > stored_response["usage"]["input_tokens"] # prior turn re-billed72 openai("DELETE", f"/v1/responses/{body['id']}", note="cleanup")737475def test_store_false_is_not_retrievable(openai, models):76 st, body, _ = openai("POST", "/v1/responses", {"model": models["openai"], "input": PING, "max_output_tokens": 32, "store": False}, est_cost_usd=0.00002, note="test_responses store=false")77 assert st == 200 and body["store"] is False78 st, err, _ = openai("GET", f"/v1/responses/{body['id']}", note="test_responses retrieve unstored")79 assert st == 404808182def test_structured_output_json_schema(openai, models):83 schema = {"type": "object", "properties": {"answer": {"type": "string"}}, "required": ["answer"], "additionalProperties": False}84 st, body, _ = openai("POST", "/v1/responses", {"model": models["openai"], "input": PING, "max_output_tokens": 32, "store": False,85 "text": {"format": {"type": "json_schema", "name": "ok", "strict": True, "schema": schema}}}, est_cost_usd=0.00003, note="test_responses json_schema")86 assert st == 200 and body["text"]["format"]["type"] == "json_schema"87 assert "answer" in json.loads(_text(body))888990def test_validation_errors(openai, models):91 st, err, _ = openai("POST", "/v1/responses", {"model": models["openai"], "input": PING, "max_output_tokens": 8}, note="test_responses max_output_tokens<16")92 assert st == 400 and err["error"]["code"] == "integer_below_min_value"93 st, err, _ = openai("POST", "/v1/responses", {"model": models["openai"], "input": PING, "max_output_tokens": 16, "conversation": "conv_x", "previous_response_id": "resp_x"}, note="test_responses mutually exclusive")94 assert st == 400 and err["error"]["code"] == "mutually_exclusive_parameters"959697def test_background_create_cancel(openai, models):98 st, body, _ = openai("POST", "/v1/responses", {"model": models["openai"], "input": PING, "max_output_tokens": 32, "background": True}, est_cost_usd=0.00002, note="test_responses background")99 assert st == 200 and body["status"] in ("queued", "in_progress", "completed")100 st, c, _ = openai("POST", f"/v1/responses/{body['id']}/cancel", note="test_responses cancel")101 # Race: a tiny background response may already be completed → 400 "Cannot cancel a completed response." (live 2026-09-18)102 assert (st == 200 and c["status"] in ("cancelled", "completed")) or (st == 400 and "completed" in c["error"]["message"])103 for _ in range(10):104 st, p, _ = openai("GET", f"/v1/responses/{body['id']}", note="test_responses poll")105 if p["status"] not in ("queued", "in_progress"):106 break107 time.sleep(1)108 assert p["status"] in ("cancelled", "completed")109 openai("DELETE", f"/v1/responses/{body['id']}", note="cleanup")110111112def test_conversations_lifecycle(openai, models):113 st, conv, _ = openai("POST", "/v1/conversations", {"metadata": {"atlas": "test"}}, note="test_responses conversation create")114 assert st == 200 and conv["object"] == "conversation"115 cid = conv["id"]116 st, items, _ = openai("POST", f"/v1/conversations/{cid}/items", {"items": [{"type": "message", "role": "user", "content": [{"type": "input_text", "text": PING}]}]}, note="items create")117 assert st == 200 and items["data"][0]["type"] == "message"118 st, resp, _ = openai("POST", "/v1/responses", {"model": models["openai"], "conversation": cid, "input": "Reply with OK once more.", "max_output_tokens": 32}, est_cost_usd=0.00002, note="response with conversation")119 assert st == 200 and resp["conversation"]["id"] == cid120 st, listed, _ = openai("GET", f"/v1/conversations/{cid}/items?order=asc", note="items list")121 assert st == 200 and [i["type"] for i in listed["data"]] == ["message", "message", "message"]122 st, deleted, _ = openai("DELETE", f"/v1/conversations/{cid}", note="conversation delete")123 assert st == 200 and deleted["deleted"] is True124125126@pytest.mark.run_expensive_tests127def test_compaction_endpoint(openai, models):128 st, body, _ = openai("POST", "/v1/responses/compact", {"model": models["openai"], "input": [{"role": "user", "content": PING}, {"role": "assistant", "content": "OK"}, {"role": "user", "content": "Reply with OK again."}]}, est_cost_usd=0.0003, note="test_responses compact")129 assert st == 200 and body["object"] == "response.compaction"130 assert any(i["type"] == "compaction" and i.get("encrypted_content") for i in body["output"])131