{
  "file": "F30-openai-gateway.md",
  "bullet": "Chat completion (`F30.chat-basic`).",
  "ids": [
    "F30.chat-basic"
  ],
  "line": 186,
  "script": "CID=$(control-agent-server api POST /v1/chat/completions --auth bearer --timeout 180 \\\n  --json '{\"model\": \"openhands_deepseek-flash\", \"messages\": [{\"role\": \"system\", \"content\": \"QA_F30_SYS: answer in one short sentence and never use tools.\"}, {\"role\": \"developer\", \"content\": \"QA_F30_DEV: plain text only.\"}, {\"role\": \"user\", \"content\": \"QA_F30_OLD_TURN: remember the word apple.\"}, {\"role\": \"assistant\", \"content\": \"QA_F30_OLD_ANSWER\"}, {\"role\": \"user\", \"content\": \"QA_F30_NEW_TURN: say hello.\"}], \"temperature\": 0, \"user\": \"qa-f30\"}' \\\n  --check object eq chat.completion --check id matches '^chatcmpl-[0-9a-f]{32}$' --check model eq openhands_deepseek-flash \\\n  --check choices len-eq 1 --check choices.0.index eq 0 --check choices.0.finish_reason eq stop \\\n  --check choices.0.message.role eq assistant --check choices.0.message.content len-ge 1 \\\n  --check usage.prompt_tokens gt 0 --check usage.completion_tokens gt 0 \\\n  --raw-out \"$F30/chat-basic.json\" --save F30.chat-basic/completion --print-header X-OpenHands-ServerConversation-ID)\ncontrol-agent-server api GET \"<redacted:session-cookie>/$CID\" --check execution_status eq finished --check title missing \\\n  --check agent.llm.model eq deepseek/deepseek-flash --check workspace.working_dir eq \"$AGENT_SERVER_VERIFY_RUN/server/workspace/project\" \\\n  --quiet --save F30.chat-basic/conversation\ncontrol-agent-server api GET \"<redacted:session-cookie>/$CID/agent_final_response\" --raw-out \"$F30/chat-basic-final.json\" --quiet\npython3 - \"$F30/chat-basic.json\" \"$F30/chat-basic-final.json\" <<'PY'\nimport json, sys\nchat, final = (json.load(open(path)) for path in sys.argv[1:])\nassert chat[\"choices\"][0][\"message\"][\"content\"] == final[\"response\"] != \"\", (chat, final)\nusage = chat[\"usage\"]\nassert usage[\"total_tokens\"] == usage[\"prompt_tokens\"] + usage[\"completion_tokens\"], usage\nPY\n",
  "exit_code": 0,
  "elapsed_ms": 3181,
  "failed_line": null,
  "failed_command": null,
  "stdout": "{\n  \"ok\": true,\n  \"status\": 200,\n  \"request\": {\n    \"method\": \"GET\",\n    \"path\": \"<redacted:session-cookie>/285a7caa-aa8f-42df-b11b-76a3d395cbfa\",\n    \"query\": [],\n    \"auth\": \"header\",\n    \"files\": []\n  },\n  \"response\": {\n    \"status\": 200,\n    \"headers\": {\n      \"content-length\": \"6694\",\n      \"content-type\": \"application/json\"\n    },\n    \"truncated\": false\n  },\n  \"elapsed_ms\": 86,\n  \"checks\": [\n    {\n      \"check\": \"execution_status eq finished\",\n      \"ok\": true,\n      \"actual\": \"finished\"\n    },\n    {\n      \"check\": \"title missing\",\n      \"ok\": true,\n      \"actual\": \"null\"\n    },\n    {\n      \"check\": \"agent.llm.model eq deepseek/deepseek-flash\",\n      \"ok\": true,\n      \"actual\": \"deepseek/deepseek-flash\"\n    },\n    {\n      \"check\": \"workspace.working_dir eq /workspace/verification-artifacts/runs/20261013-032720-3de9-map-f30/server/workspace/project\",\n      \"ok\": true,\n      \"actual\": \"/workspace/verification-artifacts/runs/20261013-032720-3de9-map-f30/server/workspace/project\"\n    }\n  ],\n  \"saved\": \"/workspace/verification-artifacts/runs/20261013-032720-3de9-map-f30/evidence/F30.chat-basic/conversation.json\"\n}\n{\n  \"ok\": true,\n  \"status\": 200,\n  \"request\": {\n    \"method\": \"GET\",\n    \"path\": \"<redacted:session-cookie>/285a7caa-aa8f-42df-b11b-76a3d395cbfa/agent_final_response\",\n    \"query\": [],\n    \"auth\": \"header\",\n    \"files\": []\n  },\n  \"response\": {\n    \"status\": 200,\n    \"headers\": {\n      \"content-length\": \"21\",\n      \"content-type\": \"application/json\"\n    },\n    \"truncated\": false\n  },\n  \"elapsed_ms\": 48,\n  \"raw_out\": \"/workspace/verification-artifacts/runs/20261013-032720-3de9-map-f30/fixtures/qa-f30/chat-basic-final.json\"\n}\n",
  "stderr": ""
}
