{"record":{"id":"988cc4bba0bfeca8","repo":"moeru-ai/airi","slug":"unsupported-responses-tool-output","errorCode":null,"errorMessage":"Unsupported Responses tool output","messagePattern":"Unsupported Responses tool output","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/core-agent/src/runtime/responses.ts","lineNumber":110,"sourceCode":"function readToolResultContent(content: Extract<ItemParam, { type: 'function_call_output' }>['output']): InputSegment[] {\n  if (typeof content === 'string')\n    return [{ type: 'text', text: content }]\n  return content.map((part) => {\n    switch (part.type) {\n      case 'input_text': return { type: 'text', text: part.text }\n      case 'input_image':\n        if (!part.image_url)\n          throw new Error('Responses image output requires a URL')\n        return { type: 'image', url: part.image_url, detail: part.detail ?? undefined }\n      case 'input_file':\n        if (part.file_data != null && part.file_url == null)\n          return { type: 'file', data: part.file_data, name: part.filename ?? undefined }\n        if (part.file_url != null && part.file_data == null)\n          return { type: 'file', url: part.file_url, name: part.filename ?? undefined }\n        throw new Error('Responses file requires exactly one source')\n      case 'input_video': throw new Error('Video tool output is not supported by the conversation model')\n    }\n    throw new Error('Unsupported Responses tool output')\n  })\n}\n\ntype AssistantContent = Exclude<Extract<ItemParam, { role: 'assistant' }>['content'], string>[number]\n\nfunction readCitations(part: Extract<AssistantContent, { type: 'output_text' }>): Citation[] | undefined {\n  return part.annotations?.map(entry => ({\n    url: entry.url,\n    title: entry.title,\n    startIndex: entry.start_index,\n    endIndex: entry.end_index,\n  }))\n}\n\nfunction readOutput(items: ItemParam[]): ProjectionEntry[] {\n  return items.flatMap<ProjectionEntry>((item, index) => {\n    const id = `output-${index}`\n    if (item.type === 'function_call')","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/moeru-ai/airi/blob/438a067dde47aa0bdb46c2323d1fe293dc805218/packages/core-agent/src/runtime/responses.ts#L92-L128","documentation":"readToolResultContent switches over the part.type of Responses function_call_output parts. This fallback throw fires when a part's type matches none of the known cases (input_text, input_image, input_file, input_video). It guards against unknown or future OpenAI Responses content types the adapter cannot project into the portable conversation model.","triggerScenarios":"readOutput() -> readToolResultContent() receives a function_call_output whose output is an array containing a part whose type is not input_text/input_image/input_file/input_video — e.g. a newer API content type, a typo like 'input_texts', or a hand-constructed part object.","commonSituations":"Upstream Responses API added a new content part type after this adapter was written; a plugin or tool writes non-standard parts into conversation state; a persisted continuation from a newer library version is read by an older adapter.","solutions":["Identify the offending part.type from the conversation/continuation data and convert it to a supported type (input_text) before storing.","Upgrade @proj-airi/core-agent / the Responses adapter to a version that knows the new content part type.","As a workaround, sanitize function_call_output parts with a whitelist filter before pushing them into the conversation."],"exampleFix":"// before\nitems.push({ type: 'function_call_output', call_id: segment.callId, output: content })\n\n// after\nconst allowed = ['input_text', 'input_image', 'input_file']\nitems.push({ type: 'function_call_output', call_id: segment.callId, output: content.filter(p => allowed.includes(p.type)) })","handlingStrategy":"type-guard","validationCode":"const KNOWN = new Set(['input_text', 'input_image', 'input_file', 'input_video'])\nconst unknown = output.filter(p => !KNOWN.has(p?.type))\nif (unknown.length) console.warn('unknown tool output part types:', unknown.map(p => p.type))","typeGuard":"function isKnownToolOutputPart(part) {\n  return ['input_text', 'input_image', 'input_file', 'input_video'].includes(part?.type)\n}","tryCatchPattern":"try {\n  projection = readOutput(items)\n} catch (err) {\n  if (err.message === 'Unsupported Responses tool output') {\n    console.error('Unrecognized function_call_output part type; upgrade adapter or sanitize parts.')\n  } else throw err\n}","preventionTips":["Keep the adapter version aligned with the Responses API types you compile against.","Sanitize hand-built ItemParam arrays against the known part-type union.","Do not replay continuation data captured by a newer library version without upgrading."],"tags":["unexpected-response-shape","responses-api","adapter"],"backgroundTag":"unexpected-response-shape","analyzedSha":"438a067dde47aa0bdb46c2323d1fe293dc805218","analyzedAt":"2026-09-17T01:14:42.644Z","contentChangedAt":"2026-09-17T01:14:42.644Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}