feat: Passwordless cross-device authentication

- Arkitektur: docs/auth/passwordless-architecture.md
- Backend: iom/quixzoom-auth-service/ (FastAPI + Redis)
- Webb: quixzoom-market-pages/se/login/ (QR-kod + polling)
- App: iom/quixzoom-app/src/features/auth/ (push + deep links)

Flöde: QR-kod → app-godkännande → webb-inloggad
This commit is contained in:
Bernt
2026-07-07 07:11:50 +00:00
parent 4aa984ad74
commit 6989a98d75
61843 changed files with 5491611 additions and 872231 deletions
+9
View File
@@ -0,0 +1,9 @@
import { ResponseAudioDeltaEvent, ResponseAudioDoneEvent, ResponseAudioTranscriptDeltaEvent, ResponseAudioTranscriptDoneEvent, ResponseCodeInterpreterCallCodeDeltaEvent, ResponseCodeInterpreterCallCodeDoneEvent, ResponseCodeInterpreterCallCompletedEvent, ResponseCodeInterpreterCallInProgressEvent, ResponseCodeInterpreterCallInterpretingEvent, ResponseCompletedEvent, ResponseContentPartAddedEvent, ResponseContentPartDoneEvent, ResponseCreatedEvent, ResponseErrorEvent, ResponseFailedEvent, ResponseFileSearchCallCompletedEvent, ResponseFileSearchCallInProgressEvent, ResponseFileSearchCallSearchingEvent, ResponseFunctionCallArgumentsDeltaEvent as RawResponseFunctionCallArgumentsDeltaEvent, ResponseFunctionCallArgumentsDoneEvent, ResponseInProgressEvent, ResponseOutputItemAddedEvent, ResponseOutputItemDoneEvent, ResponseRefusalDeltaEvent, ResponseRefusalDoneEvent, ResponseTextDeltaEvent as RawResponseTextDeltaEvent, ResponseTextDoneEvent, ResponseIncompleteEvent, ResponseWebSearchCallCompletedEvent, ResponseWebSearchCallInProgressEvent, ResponseWebSearchCallSearchingEvent } from "../../resources/responses/responses.mjs";
export type ResponseFunctionCallArgumentsDeltaEvent = RawResponseFunctionCallArgumentsDeltaEvent & {
snapshot: string;
};
export type ResponseTextDeltaEvent = RawResponseTextDeltaEvent & {
snapshot: string;
};
export type ParsedResponseStreamEvent = ResponseAudioDeltaEvent | ResponseAudioDoneEvent | ResponseAudioTranscriptDeltaEvent | ResponseAudioTranscriptDoneEvent | ResponseCodeInterpreterCallCodeDeltaEvent | ResponseCodeInterpreterCallCodeDoneEvent | ResponseCodeInterpreterCallCompletedEvent | ResponseCodeInterpreterCallInProgressEvent | ResponseCodeInterpreterCallInterpretingEvent | ResponseCompletedEvent | ResponseContentPartAddedEvent | ResponseContentPartDoneEvent | ResponseCreatedEvent | ResponseErrorEvent | ResponseFileSearchCallCompletedEvent | ResponseFileSearchCallInProgressEvent | ResponseFileSearchCallSearchingEvent | ResponseFunctionCallArgumentsDeltaEvent | ResponseFunctionCallArgumentsDoneEvent | ResponseInProgressEvent | ResponseFailedEvent | ResponseIncompleteEvent | ResponseOutputItemAddedEvent | ResponseOutputItemDoneEvent | ResponseRefusalDeltaEvent | ResponseRefusalDoneEvent | ResponseTextDeltaEvent | ResponseTextDoneEvent | ResponseWebSearchCallCompletedEvent | ResponseWebSearchCallInProgressEvent | ResponseWebSearchCallSearchingEvent;
//# sourceMappingURL=EventTypes.d.mts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"EventTypes.d.mts","sourceRoot":"","sources":["../../src/lib/responses/EventTypes.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,EACvB,sBAAsB,EACtB,iCAAiC,EACjC,gCAAgC,EAChC,yCAAyC,EACzC,wCAAwC,EACxC,yCAAyC,EACzC,0CAA0C,EAC1C,4CAA4C,EAC5C,sBAAsB,EACtB,6BAA6B,EAC7B,4BAA4B,EAC5B,oBAAoB,EACpB,kBAAkB,EAClB,mBAAmB,EACnB,oCAAoC,EACpC,qCAAqC,EACrC,oCAAoC,EACpC,uCAAuC,IAAI,0CAA0C,EACrF,sCAAsC,EACtC,uBAAuB,EACvB,4BAA4B,EAC5B,2BAA2B,EAC3B,yBAAyB,EACzB,wBAAwB,EACxB,sBAAsB,IAAI,yBAAyB,EACnD,qBAAqB,EACrB,uBAAuB,EACvB,mCAAmC,EACnC,oCAAoC,EACpC,mCAAmC,EACpC,gDAA4C;AAE7C,MAAM,MAAM,uCAAuC,GAAG,0CAA0C,GAAG;IACjG,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG,yBAAyB,GAAG;IAC/D,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GACjC,uBAAuB,GACvB,sBAAsB,GACtB,iCAAiC,GACjC,gCAAgC,GAChC,yCAAyC,GACzC,wCAAwC,GACxC,yCAAyC,GACzC,0CAA0C,GAC1C,4CAA4C,GAC5C,sBAAsB,GACtB,6BAA6B,GAC7B,4BAA4B,GAC5B,oBAAoB,GACpB,kBAAkB,GAClB,oCAAoC,GACpC,qCAAqC,GACrC,oCAAoC,GACpC,uCAAuC,GACvC,sCAAsC,GACtC,uBAAuB,GACvB,mBAAmB,GACnB,uBAAuB,GACvB,4BAA4B,GAC5B,2BAA2B,GAC3B,yBAAyB,GACzB,wBAAwB,GACxB,sBAAsB,GACtB,qBAAqB,GACrB,mCAAmC,GACnC,oCAAoC,GACpC,mCAAmC,CAAC"}
+9
View File
@@ -0,0 +1,9 @@
import { ResponseAudioDeltaEvent, ResponseAudioDoneEvent, ResponseAudioTranscriptDeltaEvent, ResponseAudioTranscriptDoneEvent, ResponseCodeInterpreterCallCodeDeltaEvent, ResponseCodeInterpreterCallCodeDoneEvent, ResponseCodeInterpreterCallCompletedEvent, ResponseCodeInterpreterCallInProgressEvent, ResponseCodeInterpreterCallInterpretingEvent, ResponseCompletedEvent, ResponseContentPartAddedEvent, ResponseContentPartDoneEvent, ResponseCreatedEvent, ResponseErrorEvent, ResponseFailedEvent, ResponseFileSearchCallCompletedEvent, ResponseFileSearchCallInProgressEvent, ResponseFileSearchCallSearchingEvent, ResponseFunctionCallArgumentsDeltaEvent as RawResponseFunctionCallArgumentsDeltaEvent, ResponseFunctionCallArgumentsDoneEvent, ResponseInProgressEvent, ResponseOutputItemAddedEvent, ResponseOutputItemDoneEvent, ResponseRefusalDeltaEvent, ResponseRefusalDoneEvent, ResponseTextDeltaEvent as RawResponseTextDeltaEvent, ResponseTextDoneEvent, ResponseIncompleteEvent, ResponseWebSearchCallCompletedEvent, ResponseWebSearchCallInProgressEvent, ResponseWebSearchCallSearchingEvent } from "../../resources/responses/responses.js";
export type ResponseFunctionCallArgumentsDeltaEvent = RawResponseFunctionCallArgumentsDeltaEvent & {
snapshot: string;
};
export type ResponseTextDeltaEvent = RawResponseTextDeltaEvent & {
snapshot: string;
};
export type ParsedResponseStreamEvent = ResponseAudioDeltaEvent | ResponseAudioDoneEvent | ResponseAudioTranscriptDeltaEvent | ResponseAudioTranscriptDoneEvent | ResponseCodeInterpreterCallCodeDeltaEvent | ResponseCodeInterpreterCallCodeDoneEvent | ResponseCodeInterpreterCallCompletedEvent | ResponseCodeInterpreterCallInProgressEvent | ResponseCodeInterpreterCallInterpretingEvent | ResponseCompletedEvent | ResponseContentPartAddedEvent | ResponseContentPartDoneEvent | ResponseCreatedEvent | ResponseErrorEvent | ResponseFileSearchCallCompletedEvent | ResponseFileSearchCallInProgressEvent | ResponseFileSearchCallSearchingEvent | ResponseFunctionCallArgumentsDeltaEvent | ResponseFunctionCallArgumentsDoneEvent | ResponseInProgressEvent | ResponseFailedEvent | ResponseIncompleteEvent | ResponseOutputItemAddedEvent | ResponseOutputItemDoneEvent | ResponseRefusalDeltaEvent | ResponseRefusalDoneEvent | ResponseTextDeltaEvent | ResponseTextDoneEvent | ResponseWebSearchCallCompletedEvent | ResponseWebSearchCallInProgressEvent | ResponseWebSearchCallSearchingEvent;
//# sourceMappingURL=EventTypes.d.ts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"EventTypes.d.ts","sourceRoot":"","sources":["../../src/lib/responses/EventTypes.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,EACvB,sBAAsB,EACtB,iCAAiC,EACjC,gCAAgC,EAChC,yCAAyC,EACzC,wCAAwC,EACxC,yCAAyC,EACzC,0CAA0C,EAC1C,4CAA4C,EAC5C,sBAAsB,EACtB,6BAA6B,EAC7B,4BAA4B,EAC5B,oBAAoB,EACpB,kBAAkB,EAClB,mBAAmB,EACnB,oCAAoC,EACpC,qCAAqC,EACrC,oCAAoC,EACpC,uCAAuC,IAAI,0CAA0C,EACrF,sCAAsC,EACtC,uBAAuB,EACvB,4BAA4B,EAC5B,2BAA2B,EAC3B,yBAAyB,EACzB,wBAAwB,EACxB,sBAAsB,IAAI,yBAAyB,EACnD,qBAAqB,EACrB,uBAAuB,EACvB,mCAAmC,EACnC,oCAAoC,EACpC,mCAAmC,EACpC,+CAA4C;AAE7C,MAAM,MAAM,uCAAuC,GAAG,0CAA0C,GAAG;IACjG,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG,yBAAyB,GAAG;IAC/D,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GACjC,uBAAuB,GACvB,sBAAsB,GACtB,iCAAiC,GACjC,gCAAgC,GAChC,yCAAyC,GACzC,wCAAwC,GACxC,yCAAyC,GACzC,0CAA0C,GAC1C,4CAA4C,GAC5C,sBAAsB,GACtB,6BAA6B,GAC7B,4BAA4B,GAC5B,oBAAoB,GACpB,kBAAkB,GAClB,oCAAoC,GACpC,qCAAqC,GACrC,oCAAoC,GACpC,uCAAuC,GACvC,sCAAsC,GACtC,uBAAuB,GACvB,mBAAmB,GACnB,uBAAuB,GACvB,4BAA4B,GAC5B,2BAA2B,GAC3B,yBAAyB,GACzB,wBAAwB,GACxB,sBAAsB,GACtB,qBAAqB,GACrB,mCAAmC,GACnC,oCAAoC,GACpC,mCAAmC,CAAC"}
+3
View File
@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=EventTypes.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"EventTypes.js","sourceRoot":"","sources":["../../src/lib/responses/EventTypes.ts"],"names":[],"mappings":""}
+2
View File
@@ -0,0 +1,2 @@
export {};
//# sourceMappingURL=EventTypes.mjs.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"EventTypes.mjs","sourceRoot":"","sources":["../../src/lib/responses/EventTypes.ts"],"names":[],"mappings":""}
+10
View File
@@ -0,0 +1,10 @@
import { type Response, type ResponseStreamEvent } from "../../resources/responses/responses.mjs";
/**
* Applies a streaming event to a response snapshot.
*
* Always use the returned snapshot. Incremental events update the supplied snapshot
* in place, while response lifecycle events return a detached replacement. Event
* payloads are cloned, so retaining or replaying the raw events is safe.
*/
export declare function accumulateResponse(event: ResponseStreamEvent, snapshot?: Response): Response;
//# sourceMappingURL=ResponseAccumulator.d.mts.map
@@ -0,0 +1 @@
{"version":3,"file":"ResponseAccumulator.d.mts","sourceRoot":"","sources":["../../src/lib/responses/ResponseAccumulator.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,QAAQ,EAEb,KAAK,mBAAmB,EACzB,gDAA4C;AAI7C;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,mBAAmB,EAAE,QAAQ,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAgX5F"}
+10
View File
@@ -0,0 +1,10 @@
import { type Response, type ResponseStreamEvent } from "../../resources/responses/responses.js";
/**
* Applies a streaming event to a response snapshot.
*
* Always use the returned snapshot. Incremental events update the supplied snapshot
* in place, while response lifecycle events return a detached replacement. Event
* payloads are cloned, so retaining or replaying the raw events is safe.
*/
export declare function accumulateResponse(event: ResponseStreamEvent, snapshot?: Response): Response;
//# sourceMappingURL=ResponseAccumulator.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"ResponseAccumulator.d.ts","sourceRoot":"","sources":["../../src/lib/responses/ResponseAccumulator.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,QAAQ,EAEb,KAAK,mBAAmB,EACzB,+CAA4C;AAI7C;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,mBAAmB,EAAE,QAAQ,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAgX5F"}
+402
View File
@@ -0,0 +1,402 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.accumulateResponse = accumulateResponse;
const error_1 = require("../../error.js");
const ResponsesParser_1 = require("../ResponsesParser.js");
/**
* Applies a streaming event to a response snapshot.
*
* Always use the returned snapshot. Incremental events update the supplied snapshot
* in place, while response lifecycle events return a detached replacement. Event
* payloads are cloned, so retaining or replaying the raw events is safe.
*/
function accumulateResponse(event, snapshot) {
if (!snapshot) {
if (event.type !== 'response.created') {
throw new error_1.OpenAIError(`When snapshot hasn't been set yet, expected 'response.created' event, got ${event.type}`);
}
return cloneResponse(event.response);
}
switch (event.type) {
case 'response.output_item.added': {
snapshot.output.push(structuredClone(event.item));
if (event.item.type === 'message') {
(0, ResponsesParser_1.addOutputText)(snapshot);
}
break;
}
case 'response.output_item.done': {
getOutput(snapshot, event.output_index);
snapshot.output[event.output_index] = structuredClone(event.item);
if (event.item.type === 'message') {
(0, ResponsesParser_1.addOutputText)(snapshot);
}
break;
}
case 'response.content_part.added': {
const output = getOutput(snapshot, event.output_index);
const type = output.type;
const part = event.part;
if (type === 'message' && part.type !== 'reasoning_text') {
output.content.push(structuredClone(part));
if (part.type === 'output_text') {
(0, ResponsesParser_1.addOutputText)(snapshot);
}
}
else if (type === 'reasoning' && part.type === 'reasoning_text') {
if (!output.content) {
output.content = [];
}
output.content.push(structuredClone(part));
}
break;
}
case 'response.content_part.done': {
const output = getOutput(snapshot, event.output_index);
const part = event.part;
if (output.type === 'message' && part.type !== 'reasoning_text') {
getContent(output.content, event.content_index);
output.content[event.content_index] = structuredClone(part);
if (part.type === 'output_text') {
(0, ResponsesParser_1.addOutputText)(snapshot);
}
}
else if (output.type === 'reasoning' && part.type === 'reasoning_text') {
const content = output.content;
if (!content) {
throw new error_1.OpenAIError(`missing content at index ${event.content_index}`);
}
getContent(content, event.content_index);
content[event.content_index] = structuredClone(part);
}
break;
}
case 'response.output_text.delta': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'message') {
const content = getContent(output.content, event.content_index);
if (content.type !== 'output_text') {
throw new error_1.OpenAIError(`expected content to be 'output_text', got ${content.type}`);
}
content.text += event.delta;
snapshot.output_text += event.delta;
}
break;
}
case 'response.output_text.done': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'message') {
const content = getContent(output.content, event.content_index);
if (content.type !== 'output_text') {
throw new error_1.OpenAIError(`expected content to be 'output_text', got ${content.type}`);
}
content.text = event.text;
(0, ResponsesParser_1.addOutputText)(snapshot);
}
break;
}
case 'response.output_text.annotation.added': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'message') {
const content = getContent(output.content, event.content_index);
if (content.type !== 'output_text') {
throw new error_1.OpenAIError(`expected content to be 'output_text', got ${content.type}`);
}
content.annotations[event.annotation_index] = structuredClone(event.annotation);
}
break;
}
case 'response.refusal.delta': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'message') {
const content = getContent(output.content, event.content_index);
if (content.type !== 'refusal') {
throw new error_1.OpenAIError(`expected content to be 'refusal', got ${content.type}`);
}
content.refusal += event.delta;
}
break;
}
case 'response.refusal.done': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'message') {
const content = getContent(output.content, event.content_index);
if (content.type !== 'refusal') {
throw new error_1.OpenAIError(`expected content to be 'refusal', got ${content.type}`);
}
content.refusal = event.refusal;
}
break;
}
case 'response.function_call_arguments.delta': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'function_call') {
output.arguments += event.delta;
}
break;
}
case 'response.function_call_arguments.done': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'function_call') {
output.arguments = event.arguments;
}
break;
}
case 'response.reasoning_text.delta': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'reasoning') {
if (!output.content) {
throw new error_1.OpenAIError(`missing content at index ${event.content_index}`);
}
const content = getContent(output.content, event.content_index);
if (content.type !== 'reasoning_text') {
throw new error_1.OpenAIError(`expected content to be 'reasoning_text', got ${content.type}`);
}
content.text += event.delta;
}
break;
}
case 'response.reasoning_text.done': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'reasoning') {
if (!output.content) {
throw new error_1.OpenAIError(`missing content at index ${event.content_index}`);
}
const content = getContent(output.content, event.content_index);
if (content.type !== 'reasoning_text') {
throw new error_1.OpenAIError(`expected content to be 'reasoning_text', got ${content.type}`);
}
content.text = event.text;
}
break;
}
case 'response.reasoning_summary_part.added': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'reasoning') {
output.summary.push(structuredClone(event.part));
}
break;
}
case 'response.reasoning_summary_part.done': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'reasoning') {
getContent(output.summary, event.summary_index);
output.summary[event.summary_index] = structuredClone(event.part);
}
break;
}
case 'response.reasoning_summary_text.delta': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'reasoning') {
const part = getContent(output.summary, event.summary_index);
part.text += event.delta;
}
break;
}
case 'response.reasoning_summary_text.done': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'reasoning') {
const part = getContent(output.summary, event.summary_index);
part.text = event.text;
}
break;
}
case 'response.custom_tool_call_input.delta': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'custom_tool_call') {
output.input += event.delta;
}
break;
}
case 'response.custom_tool_call_input.done': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'custom_tool_call') {
output.input = event.input;
}
break;
}
case 'response.mcp_call_arguments.delta': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'mcp_call') {
output.arguments += event.delta;
}
break;
}
case 'response.mcp_call_arguments.done': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'mcp_call') {
output.arguments = event.arguments;
}
break;
}
case 'response.code_interpreter_call_code.delta': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'code_interpreter_call') {
output.code = (output.code ?? '') + event.delta;
}
break;
}
case 'response.code_interpreter_call_code.done': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'code_interpreter_call') {
output.code = event.code;
}
break;
}
case 'response.code_interpreter_call.in_progress': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'code_interpreter_call') {
output.status = 'in_progress';
}
break;
}
case 'response.code_interpreter_call.interpreting': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'code_interpreter_call') {
output.status = 'interpreting';
}
break;
}
case 'response.code_interpreter_call.completed': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'code_interpreter_call') {
output.status = 'completed';
}
break;
}
case 'response.file_search_call.in_progress': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'file_search_call') {
output.status = 'in_progress';
}
break;
}
case 'response.file_search_call.searching': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'file_search_call') {
output.status = 'searching';
}
break;
}
case 'response.file_search_call.completed': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'file_search_call') {
output.status = 'completed';
}
break;
}
case 'response.web_search_call.in_progress': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'web_search_call') {
output.status = 'in_progress';
}
break;
}
case 'response.web_search_call.searching': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'web_search_call') {
output.status = 'searching';
}
break;
}
case 'response.web_search_call.completed': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'web_search_call') {
output.status = 'completed';
}
break;
}
case 'response.image_generation_call.in_progress': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'image_generation_call') {
output.status = 'in_progress';
}
break;
}
case 'response.image_generation_call.generating': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'image_generation_call') {
output.status = 'generating';
}
break;
}
case 'response.image_generation_call.completed': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'image_generation_call') {
output.status = 'completed';
}
break;
}
case 'response.mcp_call.in_progress': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'mcp_call') {
output.status = 'in_progress';
}
break;
}
case 'response.mcp_call.completed': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'mcp_call') {
output.status = 'completed';
}
break;
}
case 'response.mcp_call.failed': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'mcp_call') {
output.status = 'failed';
}
break;
}
case 'response.created':
case 'response.queued':
case 'response.in_progress':
case 'response.completed':
case 'response.failed':
case 'response.incomplete': {
snapshot = cloneResponse(event.response);
break;
}
case 'response.audio.delta':
case 'response.audio.done':
case 'response.audio.transcript.delta':
case 'response.audio.transcript.done':
case 'response.image_generation_call.partial_image':
case 'response.mcp_list_tools.in_progress':
case 'response.mcp_list_tools.completed':
case 'response.mcp_list_tools.failed':
case 'error': {
// These events do not contain state represented by the Response object.
break;
}
default: {
assertNever(event);
}
}
return snapshot;
}
function cloneResponse(response) {
const snapshot = structuredClone(response);
if (!Object.getOwnPropertyDescriptor(snapshot, 'output_text') || snapshot.output_text == null) {
(0, ResponsesParser_1.addOutputText)(snapshot);
}
return snapshot;
}
function getOutput(snapshot, outputIndex) {
const output = snapshot.output[outputIndex];
if (!output) {
throw new error_1.OpenAIError(`missing output at index ${outputIndex}`);
}
return output;
}
function getContent(content, contentIndex) {
const part = content[contentIndex];
if (!part) {
throw new error_1.OpenAIError(`missing content at index ${contentIndex}`);
}
return part;
}
function assertNever(value) {
throw new error_1.OpenAIError(`Unhandled response stream event: ${JSON.stringify(value)}`);
}
//# sourceMappingURL=ResponseAccumulator.js.map
File diff suppressed because one or more lines are too long
+399
View File
@@ -0,0 +1,399 @@
import { OpenAIError } from "../../error.mjs";
import { addOutputText } from "../ResponsesParser.mjs";
/**
* Applies a streaming event to a response snapshot.
*
* Always use the returned snapshot. Incremental events update the supplied snapshot
* in place, while response lifecycle events return a detached replacement. Event
* payloads are cloned, so retaining or replaying the raw events is safe.
*/
export function accumulateResponse(event, snapshot) {
if (!snapshot) {
if (event.type !== 'response.created') {
throw new OpenAIError(`When snapshot hasn't been set yet, expected 'response.created' event, got ${event.type}`);
}
return cloneResponse(event.response);
}
switch (event.type) {
case 'response.output_item.added': {
snapshot.output.push(structuredClone(event.item));
if (event.item.type === 'message') {
addOutputText(snapshot);
}
break;
}
case 'response.output_item.done': {
getOutput(snapshot, event.output_index);
snapshot.output[event.output_index] = structuredClone(event.item);
if (event.item.type === 'message') {
addOutputText(snapshot);
}
break;
}
case 'response.content_part.added': {
const output = getOutput(snapshot, event.output_index);
const type = output.type;
const part = event.part;
if (type === 'message' && part.type !== 'reasoning_text') {
output.content.push(structuredClone(part));
if (part.type === 'output_text') {
addOutputText(snapshot);
}
}
else if (type === 'reasoning' && part.type === 'reasoning_text') {
if (!output.content) {
output.content = [];
}
output.content.push(structuredClone(part));
}
break;
}
case 'response.content_part.done': {
const output = getOutput(snapshot, event.output_index);
const part = event.part;
if (output.type === 'message' && part.type !== 'reasoning_text') {
getContent(output.content, event.content_index);
output.content[event.content_index] = structuredClone(part);
if (part.type === 'output_text') {
addOutputText(snapshot);
}
}
else if (output.type === 'reasoning' && part.type === 'reasoning_text') {
const content = output.content;
if (!content) {
throw new OpenAIError(`missing content at index ${event.content_index}`);
}
getContent(content, event.content_index);
content[event.content_index] = structuredClone(part);
}
break;
}
case 'response.output_text.delta': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'message') {
const content = getContent(output.content, event.content_index);
if (content.type !== 'output_text') {
throw new OpenAIError(`expected content to be 'output_text', got ${content.type}`);
}
content.text += event.delta;
snapshot.output_text += event.delta;
}
break;
}
case 'response.output_text.done': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'message') {
const content = getContent(output.content, event.content_index);
if (content.type !== 'output_text') {
throw new OpenAIError(`expected content to be 'output_text', got ${content.type}`);
}
content.text = event.text;
addOutputText(snapshot);
}
break;
}
case 'response.output_text.annotation.added': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'message') {
const content = getContent(output.content, event.content_index);
if (content.type !== 'output_text') {
throw new OpenAIError(`expected content to be 'output_text', got ${content.type}`);
}
content.annotations[event.annotation_index] = structuredClone(event.annotation);
}
break;
}
case 'response.refusal.delta': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'message') {
const content = getContent(output.content, event.content_index);
if (content.type !== 'refusal') {
throw new OpenAIError(`expected content to be 'refusal', got ${content.type}`);
}
content.refusal += event.delta;
}
break;
}
case 'response.refusal.done': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'message') {
const content = getContent(output.content, event.content_index);
if (content.type !== 'refusal') {
throw new OpenAIError(`expected content to be 'refusal', got ${content.type}`);
}
content.refusal = event.refusal;
}
break;
}
case 'response.function_call_arguments.delta': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'function_call') {
output.arguments += event.delta;
}
break;
}
case 'response.function_call_arguments.done': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'function_call') {
output.arguments = event.arguments;
}
break;
}
case 'response.reasoning_text.delta': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'reasoning') {
if (!output.content) {
throw new OpenAIError(`missing content at index ${event.content_index}`);
}
const content = getContent(output.content, event.content_index);
if (content.type !== 'reasoning_text') {
throw new OpenAIError(`expected content to be 'reasoning_text', got ${content.type}`);
}
content.text += event.delta;
}
break;
}
case 'response.reasoning_text.done': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'reasoning') {
if (!output.content) {
throw new OpenAIError(`missing content at index ${event.content_index}`);
}
const content = getContent(output.content, event.content_index);
if (content.type !== 'reasoning_text') {
throw new OpenAIError(`expected content to be 'reasoning_text', got ${content.type}`);
}
content.text = event.text;
}
break;
}
case 'response.reasoning_summary_part.added': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'reasoning') {
output.summary.push(structuredClone(event.part));
}
break;
}
case 'response.reasoning_summary_part.done': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'reasoning') {
getContent(output.summary, event.summary_index);
output.summary[event.summary_index] = structuredClone(event.part);
}
break;
}
case 'response.reasoning_summary_text.delta': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'reasoning') {
const part = getContent(output.summary, event.summary_index);
part.text += event.delta;
}
break;
}
case 'response.reasoning_summary_text.done': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'reasoning') {
const part = getContent(output.summary, event.summary_index);
part.text = event.text;
}
break;
}
case 'response.custom_tool_call_input.delta': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'custom_tool_call') {
output.input += event.delta;
}
break;
}
case 'response.custom_tool_call_input.done': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'custom_tool_call') {
output.input = event.input;
}
break;
}
case 'response.mcp_call_arguments.delta': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'mcp_call') {
output.arguments += event.delta;
}
break;
}
case 'response.mcp_call_arguments.done': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'mcp_call') {
output.arguments = event.arguments;
}
break;
}
case 'response.code_interpreter_call_code.delta': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'code_interpreter_call') {
output.code = (output.code ?? '') + event.delta;
}
break;
}
case 'response.code_interpreter_call_code.done': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'code_interpreter_call') {
output.code = event.code;
}
break;
}
case 'response.code_interpreter_call.in_progress': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'code_interpreter_call') {
output.status = 'in_progress';
}
break;
}
case 'response.code_interpreter_call.interpreting': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'code_interpreter_call') {
output.status = 'interpreting';
}
break;
}
case 'response.code_interpreter_call.completed': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'code_interpreter_call') {
output.status = 'completed';
}
break;
}
case 'response.file_search_call.in_progress': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'file_search_call') {
output.status = 'in_progress';
}
break;
}
case 'response.file_search_call.searching': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'file_search_call') {
output.status = 'searching';
}
break;
}
case 'response.file_search_call.completed': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'file_search_call') {
output.status = 'completed';
}
break;
}
case 'response.web_search_call.in_progress': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'web_search_call') {
output.status = 'in_progress';
}
break;
}
case 'response.web_search_call.searching': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'web_search_call') {
output.status = 'searching';
}
break;
}
case 'response.web_search_call.completed': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'web_search_call') {
output.status = 'completed';
}
break;
}
case 'response.image_generation_call.in_progress': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'image_generation_call') {
output.status = 'in_progress';
}
break;
}
case 'response.image_generation_call.generating': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'image_generation_call') {
output.status = 'generating';
}
break;
}
case 'response.image_generation_call.completed': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'image_generation_call') {
output.status = 'completed';
}
break;
}
case 'response.mcp_call.in_progress': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'mcp_call') {
output.status = 'in_progress';
}
break;
}
case 'response.mcp_call.completed': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'mcp_call') {
output.status = 'completed';
}
break;
}
case 'response.mcp_call.failed': {
const output = getOutput(snapshot, event.output_index);
if (output.type === 'mcp_call') {
output.status = 'failed';
}
break;
}
case 'response.created':
case 'response.queued':
case 'response.in_progress':
case 'response.completed':
case 'response.failed':
case 'response.incomplete': {
snapshot = cloneResponse(event.response);
break;
}
case 'response.audio.delta':
case 'response.audio.done':
case 'response.audio.transcript.delta':
case 'response.audio.transcript.done':
case 'response.image_generation_call.partial_image':
case 'response.mcp_list_tools.in_progress':
case 'response.mcp_list_tools.completed':
case 'response.mcp_list_tools.failed':
case 'error': {
// These events do not contain state represented by the Response object.
break;
}
default: {
assertNever(event);
}
}
return snapshot;
}
function cloneResponse(response) {
const snapshot = structuredClone(response);
if (!Object.getOwnPropertyDescriptor(snapshot, 'output_text') || snapshot.output_text == null) {
addOutputText(snapshot);
}
return snapshot;
}
function getOutput(snapshot, outputIndex) {
const output = snapshot.output[outputIndex];
if (!output) {
throw new OpenAIError(`missing output at index ${outputIndex}`);
}
return output;
}
function getContent(content, contentIndex) {
const part = content[contentIndex];
if (!part) {
throw new OpenAIError(`missing content at index ${contentIndex}`);
}
return part;
}
function assertNever(value) {
throw new OpenAIError(`Unhandled response stream event: ${JSON.stringify(value)}`);
}
//# sourceMappingURL=ResponseAccumulator.mjs.map
File diff suppressed because one or more lines are too long
+19
View File
@@ -0,0 +1,19 @@
import type { ResponseInputItem, ResponseOutputItem } from "../../resources/responses/responses.mjs";
export type ResponseInputItemLike = ResponseInputItem | ResponseOutputItem;
/**
* Normalizes a mixed array of stored response history items into clean
* `ResponseInputItem`s that can be sent back to `responses.create()`. Known items
* that cannot be replayed without changing their meaning are omitted.
*
* @throws {TypeError} If an item type is not supported by the installed SDK.
*/
export declare function toResponseInputItems(items: Iterable<ResponseInputItemLike>): ResponseInputItem[];
/**
* Normalizes a stored response history item into a clean `ResponseInputItem`, or
* returns `null` when a known item cannot be replayed without changing its
* meaning.
*
* @throws {TypeError} If the item type is not supported by the installed SDK.
*/
export declare function toResponseInputItem(item: ResponseInputItemLike): ResponseInputItem | null;
//# sourceMappingURL=ResponseInputItems.d.mts.map
@@ -0,0 +1 @@
{"version":3,"file":"ResponseInputItems.d.mts","sourceRoot":"","sources":["../../src/lib/responses/ResponseInputItems.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,iBAAiB,EACjB,kBAAkB,EACnB,gDAA4C;AAE7C,MAAM,MAAM,qBAAqB,GAAG,iBAAiB,GAAG,kBAAkB,CAAC;AAO3E;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,QAAQ,CAAC,qBAAqB,CAAC,GAAG,iBAAiB,EAAE,CAShG;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,qBAAqB,GAAG,iBAAiB,GAAG,IAAI,CA0EzF"}
+19
View File
@@ -0,0 +1,19 @@
import type { ResponseInputItem, ResponseOutputItem } from "../../resources/responses/responses.js";
export type ResponseInputItemLike = ResponseInputItem | ResponseOutputItem;
/**
* Normalizes a mixed array of stored response history items into clean
* `ResponseInputItem`s that can be sent back to `responses.create()`. Known items
* that cannot be replayed without changing their meaning are omitted.
*
* @throws {TypeError} If an item type is not supported by the installed SDK.
*/
export declare function toResponseInputItems(items: Iterable<ResponseInputItemLike>): ResponseInputItem[];
/**
* Normalizes a stored response history item into a clean `ResponseInputItem`, or
* returns `null` when a known item cannot be replayed without changing its
* meaning.
*
* @throws {TypeError} If the item type is not supported by the installed SDK.
*/
export declare function toResponseInputItem(item: ResponseInputItemLike): ResponseInputItem | null;
//# sourceMappingURL=ResponseInputItems.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"ResponseInputItems.d.ts","sourceRoot":"","sources":["../../src/lib/responses/ResponseInputItems.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,iBAAiB,EACjB,kBAAkB,EACnB,+CAA4C;AAE7C,MAAM,MAAM,qBAAqB,GAAG,iBAAiB,GAAG,kBAAkB,CAAC;AAO3E;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,QAAQ,CAAC,qBAAqB,CAAC,GAAG,iBAAiB,EAAE,CAShG;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,qBAAqB,GAAG,iBAAiB,GAAG,IAAI,CA0EzF"}
+102
View File
@@ -0,0 +1,102 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.toResponseInputItems = toResponseInputItems;
exports.toResponseInputItem = toResponseInputItem;
/**
* Normalizes a mixed array of stored response history items into clean
* `ResponseInputItem`s that can be sent back to `responses.create()`. Known items
* that cannot be replayed without changing their meaning are omitted.
*
* @throws {TypeError} If an item type is not supported by the installed SDK.
*/
function toResponseInputItems(items) {
const inputItems = [];
for (const item of items) {
const inputItem = toResponseInputItem(item);
if (inputItem) {
inputItems.push(inputItem);
}
}
return inputItems;
}
/**
* Normalizes a stored response history item into a clean `ResponseInputItem`, or
* returns `null` when a known item cannot be replayed without changing its
* meaning.
*
* @throws {TypeError} If the item type is not supported by the installed SDK.
*/
function toResponseInputItem(item) {
switch (item.type) {
case 'additional_tools': {
if (item.role !== 'developer') {
return null;
}
return stripCreatedBy(item);
}
case 'shell_call_output': {
const output = item.output.map((chunk) => stripCreatedBy(chunk));
return {
...stripCreatedBy(item),
output,
};
}
case 'computer_call_output': {
const { created_by: _createdBy, ...withoutCreatedBy } = item;
if (withoutCreatedBy.status === 'failed') {
return null;
}
return withoutCreatedBy;
}
case 'custom_tool_call_output': {
if ('status' in item && item.status !== 'completed') {
return null;
}
const { created_by: _createdBy, status: _status, ...inputItem } = item;
return inputItem;
}
case 'apply_patch_call':
case 'apply_patch_call_output':
case 'code_interpreter_call':
case 'compaction':
case 'compaction_trigger':
case 'computer_call':
case 'custom_tool_call':
case 'file_search_call':
case 'function_call':
case 'function_call_output':
case 'image_generation_call':
case 'item_reference':
case 'local_shell_call':
case 'local_shell_call_output':
case 'mcp_approval_request':
case 'mcp_approval_response':
case 'mcp_call':
case 'mcp_list_tools':
case 'message':
case 'reasoning':
case 'shell_call':
case 'tool_search_call':
case 'tool_search_output':
case 'web_search_call':
case null:
case undefined: {
return stripCreatedBy(item);
}
default: {
return assertNever(item);
}
}
}
function stripCreatedBy(item) {
if (!('created_by' in item)) {
return item;
}
const { created_by: _createdBy, ...rest } = item;
return rest;
}
function assertNever(value) {
const type = value.type;
throw new TypeError(`Unsupported response item type: ${String(type)}`);
}
//# sourceMappingURL=ResponseInputItems.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"ResponseInputItems.js","sourceRoot":"","sources":["../../src/lib/responses/ResponseInputItems.ts"],"names":[],"mappings":"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"}
+98
View File
@@ -0,0 +1,98 @@
/**
* Normalizes a mixed array of stored response history items into clean
* `ResponseInputItem`s that can be sent back to `responses.create()`. Known items
* that cannot be replayed without changing their meaning are omitted.
*
* @throws {TypeError} If an item type is not supported by the installed SDK.
*/
export function toResponseInputItems(items) {
const inputItems = [];
for (const item of items) {
const inputItem = toResponseInputItem(item);
if (inputItem) {
inputItems.push(inputItem);
}
}
return inputItems;
}
/**
* Normalizes a stored response history item into a clean `ResponseInputItem`, or
* returns `null` when a known item cannot be replayed without changing its
* meaning.
*
* @throws {TypeError} If the item type is not supported by the installed SDK.
*/
export function toResponseInputItem(item) {
switch (item.type) {
case 'additional_tools': {
if (item.role !== 'developer') {
return null;
}
return stripCreatedBy(item);
}
case 'shell_call_output': {
const output = item.output.map((chunk) => stripCreatedBy(chunk));
return {
...stripCreatedBy(item),
output,
};
}
case 'computer_call_output': {
const { created_by: _createdBy, ...withoutCreatedBy } = item;
if (withoutCreatedBy.status === 'failed') {
return null;
}
return withoutCreatedBy;
}
case 'custom_tool_call_output': {
if ('status' in item && item.status !== 'completed') {
return null;
}
const { created_by: _createdBy, status: _status, ...inputItem } = item;
return inputItem;
}
case 'apply_patch_call':
case 'apply_patch_call_output':
case 'code_interpreter_call':
case 'compaction':
case 'compaction_trigger':
case 'computer_call':
case 'custom_tool_call':
case 'file_search_call':
case 'function_call':
case 'function_call_output':
case 'image_generation_call':
case 'item_reference':
case 'local_shell_call':
case 'local_shell_call_output':
case 'mcp_approval_request':
case 'mcp_approval_response':
case 'mcp_call':
case 'mcp_list_tools':
case 'message':
case 'reasoning':
case 'shell_call':
case 'tool_search_call':
case 'tool_search_output':
case 'web_search_call':
case null:
case undefined: {
return stripCreatedBy(item);
}
default: {
return assertNever(item);
}
}
}
function stripCreatedBy(item) {
if (!('created_by' in item)) {
return item;
}
const { created_by: _createdBy, ...rest } = item;
return rest;
}
function assertNever(value) {
const type = value.type;
throw new TypeError(`Unsupported response item type: ${String(type)}`);
}
//# sourceMappingURL=ResponseInputItems.mjs.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"ResponseInputItems.mjs","sourceRoot":"","sources":["../../src/lib/responses/ResponseInputItems.ts"],"names":[],"mappings":"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"}
+59
View File
@@ -0,0 +1,59 @@
import { ResponseTextConfig, type ParsedResponse, type ResponseCreateParamsBase, type ResponseStreamEvent } from "../../resources/responses/responses.mjs";
import { RequestOptions } from "../../internal/request-options.mjs";
import OpenAI from "../../index.mjs";
import { type BaseEvents, EventStream } from "../EventStream.mjs";
import { type ResponseFunctionCallArgumentsDeltaEvent, type ResponseTextDeltaEvent } from "./EventTypes.mjs";
import { ParseableToolsParams } from "../ResponsesParser.mjs";
export type ResponseStreamParams = ResponseCreateAndStreamParams | ResponseStreamByIdParams;
export type ResponseCreateAndStreamParams = Omit<ResponseCreateParamsBase, 'stream'> & {
stream?: true;
};
export type ResponseStreamByIdParams = {
/**
* The ID of the response to stream.
*/
response_id: string;
/**
* If provided, the stream will start after the event with the given sequence number.
*/
starting_after?: number;
/**
* Configuration options for a text response from the model. Can be plain text or
* structured JSON data. Learn more:
*
* - [Text inputs and outputs](https://platform.openai.com/docs/guides/text)
* - [Structured Outputs](https://platform.openai.com/docs/guides/structured-outputs)
*/
text?: ResponseTextConfig;
/**
* An array of tools the model may call while generating a response. When continuing a stream, provide
* the same tools as the original request.
*/
tools?: ParseableToolsParams;
};
type ResponseEvents = BaseEvents & Omit<{
[K in ResponseStreamEvent['type']]: (event: Extract<ResponseStreamEvent, {
type: K;
}>) => void;
}, 'response.output_text.delta' | 'response.function_call_arguments.delta'> & {
event: (event: ResponseStreamEvent) => void;
'response.output_text.delta': (event: ResponseTextDeltaEvent) => void;
'response.function_call_arguments.delta': (event: ResponseFunctionCallArgumentsDeltaEvent) => void;
};
export type ResponseStreamingParams = Omit<ResponseCreateParamsBase, 'stream'> & {
stream?: true;
};
export declare class ResponseStream<ParsedT = null> extends EventStream<ResponseEvents> implements AsyncIterable<ResponseStreamEvent> {
#private;
constructor(params: ResponseStreamingParams | null);
static createResponse<ParsedT>(client: OpenAI, params: ResponseStreamParams, options?: RequestOptions): ResponseStream<ParsedT>;
protected _createOrRetrieveResponse(client: OpenAI, params: ResponseStreamParams, options?: RequestOptions): Promise<ParsedResponse<ParsedT>>;
[Symbol.asyncIterator](this: ResponseStream<ParsedT>): AsyncIterator<ResponseStreamEvent>;
/**
* @returns a promise that resolves with the final Response, or rejects
* if an error occurred or the stream ended prematurely without producing a REsponse.
*/
finalResponse(): Promise<ParsedResponse<ParsedT>>;
}
export {};
//# sourceMappingURL=ResponseStream.d.mts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"ResponseStream.d.mts","sourceRoot":"","sources":["../../src/lib/responses/ResponseStream.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,KAAK,cAAc,EAEnB,KAAK,wBAAwB,EAE7B,KAAK,mBAAmB,EACzB,gDAA4C;AAC7C,OAAO,EAAE,cAAc,EAAE,2CAAuC;AAEhE,OAAO,MAAM,wBAAoB;AACjC,OAAO,EAAE,KAAK,UAAU,EAAE,WAAW,EAAE,2BAAuB;AAC9D,OAAO,EAAE,KAAK,uCAAuC,EAAE,KAAK,sBAAsB,EAAE,yBAAqB;AAEzG,OAAO,EAAsB,oBAAoB,EAAE,+BAA2B;AAG9E,MAAM,MAAM,oBAAoB,GAAG,6BAA6B,GAAG,wBAAwB,CAAC;AAE5F,MAAM,MAAM,6BAA6B,GAAG,IAAI,CAAC,wBAAwB,EAAE,QAAQ,CAAC,GAAG;IACrF,MAAM,CAAC,EAAE,IAAI,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACrC;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,kBAAkB,CAAC;IAE1B;;;OAGG;IACH,KAAK,CAAC,EAAE,oBAAoB,CAAC;CAC9B,CAAC;AAEF,KAAK,cAAc,GAAG,UAAU,GAC9B,IAAI,CACF;KACG,CAAC,IAAI,mBAAmB,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,mBAAmB,EAAE;QAAE,IAAI,EAAE,CAAC,CAAA;KAAE,CAAC,KAAK,IAAI;CAC/F,EACD,4BAA4B,GAAG,wCAAwC,CACxE,GAAG;IACF,KAAK,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,CAAC;IAC5C,4BAA4B,EAAE,CAAC,KAAK,EAAE,sBAAsB,KAAK,IAAI,CAAC;IACtE,wCAAwC,EAAE,CAAC,KAAK,EAAE,uCAAuC,KAAK,IAAI,CAAC;CACpG,CAAC;AAEJ,MAAM,MAAM,uBAAuB,GAAG,IAAI,CAAC,wBAAwB,EAAE,QAAQ,CAAC,GAAG;IAC/E,MAAM,CAAC,EAAE,IAAI,CAAC;CACf,CAAC;AAEF,qBAAa,cAAc,CAAC,OAAO,GAAG,IAAI,CACxC,SAAQ,WAAW,CAAC,cAAc,CAClC,YAAW,aAAa,CAAC,mBAAmB,CAAC;;gBAMjC,MAAM,EAAE,uBAAuB,GAAG,IAAI;IAKlD,MAAM,CAAC,cAAc,CAAC,OAAO,EAC3B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,oBAAoB,EAC5B,OAAO,CAAC,EAAE,cAAc,GACvB,cAAc,CAAC,OAAO,CAAC;cAqFV,yBAAyB,CACvC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,oBAAoB,EAC5B,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;IA8BnC,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,IAAI,EAAE,cAAc,CAAC,OAAO,CAAC,GAAG,aAAa,CAAC,mBAAmB,CAAC;IA6DzF;;;OAGG;IACG,aAAa,IAAI,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;CAMxD"}
+59
View File
@@ -0,0 +1,59 @@
import { ResponseTextConfig, type ParsedResponse, type ResponseCreateParamsBase, type ResponseStreamEvent } from "../../resources/responses/responses.js";
import { RequestOptions } from "../../internal/request-options.js";
import OpenAI from "../../index.js";
import { type BaseEvents, EventStream } from "../EventStream.js";
import { type ResponseFunctionCallArgumentsDeltaEvent, type ResponseTextDeltaEvent } from "./EventTypes.js";
import { ParseableToolsParams } from "../ResponsesParser.js";
export type ResponseStreamParams = ResponseCreateAndStreamParams | ResponseStreamByIdParams;
export type ResponseCreateAndStreamParams = Omit<ResponseCreateParamsBase, 'stream'> & {
stream?: true;
};
export type ResponseStreamByIdParams = {
/**
* The ID of the response to stream.
*/
response_id: string;
/**
* If provided, the stream will start after the event with the given sequence number.
*/
starting_after?: number;
/**
* Configuration options for a text response from the model. Can be plain text or
* structured JSON data. Learn more:
*
* - [Text inputs and outputs](https://platform.openai.com/docs/guides/text)
* - [Structured Outputs](https://platform.openai.com/docs/guides/structured-outputs)
*/
text?: ResponseTextConfig;
/**
* An array of tools the model may call while generating a response. When continuing a stream, provide
* the same tools as the original request.
*/
tools?: ParseableToolsParams;
};
type ResponseEvents = BaseEvents & Omit<{
[K in ResponseStreamEvent['type']]: (event: Extract<ResponseStreamEvent, {
type: K;
}>) => void;
}, 'response.output_text.delta' | 'response.function_call_arguments.delta'> & {
event: (event: ResponseStreamEvent) => void;
'response.output_text.delta': (event: ResponseTextDeltaEvent) => void;
'response.function_call_arguments.delta': (event: ResponseFunctionCallArgumentsDeltaEvent) => void;
};
export type ResponseStreamingParams = Omit<ResponseCreateParamsBase, 'stream'> & {
stream?: true;
};
export declare class ResponseStream<ParsedT = null> extends EventStream<ResponseEvents> implements AsyncIterable<ResponseStreamEvent> {
#private;
constructor(params: ResponseStreamingParams | null);
static createResponse<ParsedT>(client: OpenAI, params: ResponseStreamParams, options?: RequestOptions): ResponseStream<ParsedT>;
protected _createOrRetrieveResponse(client: OpenAI, params: ResponseStreamParams, options?: RequestOptions): Promise<ParsedResponse<ParsedT>>;
[Symbol.asyncIterator](this: ResponseStream<ParsedT>): AsyncIterator<ResponseStreamEvent>;
/**
* @returns a promise that resolves with the final Response, or rejects
* if an error occurred or the stream ended prematurely without producing a REsponse.
*/
finalResponse(): Promise<ParsedResponse<ParsedT>>;
}
export {};
//# sourceMappingURL=ResponseStream.d.ts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"ResponseStream.d.ts","sourceRoot":"","sources":["../../src/lib/responses/ResponseStream.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,KAAK,cAAc,EAEnB,KAAK,wBAAwB,EAE7B,KAAK,mBAAmB,EACzB,+CAA4C;AAC7C,OAAO,EAAE,cAAc,EAAE,0CAAuC;AAEhE,OAAO,MAAM,uBAAoB;AACjC,OAAO,EAAE,KAAK,UAAU,EAAE,WAAW,EAAE,0BAAuB;AAC9D,OAAO,EAAE,KAAK,uCAAuC,EAAE,KAAK,sBAAsB,EAAE,wBAAqB;AAEzG,OAAO,EAAsB,oBAAoB,EAAE,8BAA2B;AAG9E,MAAM,MAAM,oBAAoB,GAAG,6BAA6B,GAAG,wBAAwB,CAAC;AAE5F,MAAM,MAAM,6BAA6B,GAAG,IAAI,CAAC,wBAAwB,EAAE,QAAQ,CAAC,GAAG;IACrF,MAAM,CAAC,EAAE,IAAI,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACrC;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,kBAAkB,CAAC;IAE1B;;;OAGG;IACH,KAAK,CAAC,EAAE,oBAAoB,CAAC;CAC9B,CAAC;AAEF,KAAK,cAAc,GAAG,UAAU,GAC9B,IAAI,CACF;KACG,CAAC,IAAI,mBAAmB,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,mBAAmB,EAAE;QAAE,IAAI,EAAE,CAAC,CAAA;KAAE,CAAC,KAAK,IAAI;CAC/F,EACD,4BAA4B,GAAG,wCAAwC,CACxE,GAAG;IACF,KAAK,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,CAAC;IAC5C,4BAA4B,EAAE,CAAC,KAAK,EAAE,sBAAsB,KAAK,IAAI,CAAC;IACtE,wCAAwC,EAAE,CAAC,KAAK,EAAE,uCAAuC,KAAK,IAAI,CAAC;CACpG,CAAC;AAEJ,MAAM,MAAM,uBAAuB,GAAG,IAAI,CAAC,wBAAwB,EAAE,QAAQ,CAAC,GAAG;IAC/E,MAAM,CAAC,EAAE,IAAI,CAAC;CACf,CAAC;AAEF,qBAAa,cAAc,CAAC,OAAO,GAAG,IAAI,CACxC,SAAQ,WAAW,CAAC,cAAc,CAClC,YAAW,aAAa,CAAC,mBAAmB,CAAC;;gBAMjC,MAAM,EAAE,uBAAuB,GAAG,IAAI;IAKlD,MAAM,CAAC,cAAc,CAAC,OAAO,EAC3B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,oBAAoB,EAC5B,OAAO,CAAC,EAAE,cAAc,GACvB,cAAc,CAAC,OAAO,CAAC;cAqFV,yBAAyB,CACvC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,oBAAoB,EAC5B,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;IA8BnC,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,IAAI,EAAE,cAAc,CAAC,OAAO,CAAC,GAAG,aAAa,CAAC,mBAAmB,CAAC;IA6DzF;;;OAGG;IACG,aAAa,IAAI,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;CAMxD"}
+180
View File
@@ -0,0 +1,180 @@
"use strict";
var _ResponseStream_instances, _ResponseStream_params, _ResponseStream_currentResponseSnapshot, _ResponseStream_finalResponse, _ResponseStream_beginRequest, _ResponseStream_addEvent, _ResponseStream_endRequest;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ResponseStream = void 0;
const tslib_1 = require("../../internal/tslib.js");
const error_1 = require("../../error.js");
const EventStream_1 = require("../EventStream.js");
const ResponseAccumulator_1 = require("./ResponseAccumulator.js");
const ResponsesParser_1 = require("../ResponsesParser.js");
class ResponseStream extends EventStream_1.EventStream {
constructor(params) {
super();
_ResponseStream_instances.add(this);
_ResponseStream_params.set(this, void 0);
_ResponseStream_currentResponseSnapshot.set(this, void 0);
_ResponseStream_finalResponse.set(this, void 0);
tslib_1.__classPrivateFieldSet(this, _ResponseStream_params, params, "f");
}
static createResponse(client, params, options) {
const runner = new ResponseStream(params);
runner._run(() => runner._createOrRetrieveResponse(client, params, {
...options,
headers: { ...options?.headers, 'X-Stainless-Helper-Method': 'stream' },
}));
return runner;
}
async _createOrRetrieveResponse(client, params, options) {
this._listenForAbort(options?.signal);
tslib_1.__classPrivateFieldGet(this, _ResponseStream_instances, "m", _ResponseStream_beginRequest).call(this);
let stream;
let starting_after = null;
if ('response_id' in params) {
stream = await client.responses.retrieve(params.response_id, { stream: true }, { ...options, signal: this.controller.signal, stream: true });
starting_after = params.starting_after ?? null;
}
else {
stream = await client.responses.create({ ...params, stream: true }, { ...options, signal: this.controller.signal });
}
this._connected();
for await (const event of stream) {
tslib_1.__classPrivateFieldGet(this, _ResponseStream_instances, "m", _ResponseStream_addEvent).call(this, event, starting_after);
}
if (stream.controller.signal?.aborted) {
throw new error_1.APIUserAbortError();
}
return tslib_1.__classPrivateFieldGet(this, _ResponseStream_instances, "m", _ResponseStream_endRequest).call(this);
}
[(_ResponseStream_params = new WeakMap(), _ResponseStream_currentResponseSnapshot = new WeakMap(), _ResponseStream_finalResponse = new WeakMap(), _ResponseStream_instances = new WeakSet(), _ResponseStream_beginRequest = function _ResponseStream_beginRequest() {
if (this.ended)
return;
tslib_1.__classPrivateFieldSet(this, _ResponseStream_currentResponseSnapshot, undefined, "f");
}, _ResponseStream_addEvent = function _ResponseStream_addEvent(event, starting_after) {
if (this.ended)
return;
const maybeEmit = (name, event) => {
if (starting_after == null || event.sequence_number > starting_after) {
this._emit(name, event);
}
};
const response = (0, ResponseAccumulator_1.accumulateResponse)(event, tslib_1.__classPrivateFieldGet(this, _ResponseStream_currentResponseSnapshot, "f"));
tslib_1.__classPrivateFieldSet(this, _ResponseStream_currentResponseSnapshot, response, "f");
maybeEmit('event', event);
switch (event.type) {
case 'response.output_text.delta': {
const output = response.output[event.output_index];
if (!output) {
throw new error_1.OpenAIError(`missing output at index ${event.output_index}`);
}
if (output.type === 'message') {
const content = output.content[event.content_index];
if (!content) {
throw new error_1.OpenAIError(`missing content at index ${event.content_index}`);
}
if (content.type !== 'output_text') {
throw new error_1.OpenAIError(`expected content to be 'output_text', got ${content.type}`);
}
maybeEmit('response.output_text.delta', {
...event,
snapshot: content.text,
});
}
break;
}
case 'response.function_call_arguments.delta': {
const output = response.output[event.output_index];
if (!output) {
throw new error_1.OpenAIError(`missing output at index ${event.output_index}`);
}
if (output.type === 'function_call') {
maybeEmit('response.function_call_arguments.delta', {
...event,
snapshot: output.arguments,
});
}
break;
}
default:
maybeEmit(event.type, event);
break;
}
}, _ResponseStream_endRequest = function _ResponseStream_endRequest() {
if (this.ended) {
throw new error_1.OpenAIError(`stream has ended, this shouldn't happen`);
}
const snapshot = tslib_1.__classPrivateFieldGet(this, _ResponseStream_currentResponseSnapshot, "f");
if (!snapshot) {
throw new error_1.OpenAIError(`request ended without sending any events`);
}
tslib_1.__classPrivateFieldSet(this, _ResponseStream_currentResponseSnapshot, undefined, "f");
const parsedResponse = finalizeResponse(snapshot, tslib_1.__classPrivateFieldGet(this, _ResponseStream_params, "f"));
tslib_1.__classPrivateFieldSet(this, _ResponseStream_finalResponse, parsedResponse, "f");
return parsedResponse;
}, Symbol.asyncIterator)]() {
const pushQueue = [];
const readQueue = [];
let done = false;
this.on('event', (event) => {
const reader = readQueue.shift();
if (reader) {
reader.resolve(event);
}
else {
pushQueue.push(event);
}
});
this.on('end', () => {
done = true;
for (const reader of readQueue) {
reader.resolve(undefined);
}
readQueue.length = 0;
});
this.on('abort', (err) => {
done = true;
for (const reader of readQueue) {
reader.reject(err);
}
readQueue.length = 0;
});
this.on('error', (err) => {
done = true;
for (const reader of readQueue) {
reader.reject(err);
}
readQueue.length = 0;
});
return {
next: async () => {
if (!pushQueue.length) {
if (done) {
return { value: undefined, done: true };
}
return new Promise((resolve, reject) => readQueue.push({ resolve, reject })).then((event) => (event ? { value: event, done: false } : { value: undefined, done: true }));
}
const event = pushQueue.shift();
return { value: event, done: false };
},
return: async () => {
this.abort();
return { value: undefined, done: true };
},
};
}
/**
* @returns a promise that resolves with the final Response, or rejects
* if an error occurred or the stream ended prematurely without producing a REsponse.
*/
async finalResponse() {
await this.done();
const response = tslib_1.__classPrivateFieldGet(this, _ResponseStream_finalResponse, "f");
if (!response)
throw new error_1.OpenAIError('stream ended without producing a ChatCompletion');
return response;
}
}
exports.ResponseStream = ResponseStream;
function finalizeResponse(snapshot, params) {
return (0, ResponsesParser_1.maybeParseResponse)(snapshot, params);
}
//# sourceMappingURL=ResponseStream.js.map
File diff suppressed because one or more lines are too long
+176
View File
@@ -0,0 +1,176 @@
var _ResponseStream_instances, _ResponseStream_params, _ResponseStream_currentResponseSnapshot, _ResponseStream_finalResponse, _ResponseStream_beginRequest, _ResponseStream_addEvent, _ResponseStream_endRequest;
import { __classPrivateFieldGet, __classPrivateFieldSet } from "../../internal/tslib.mjs";
import { APIUserAbortError, OpenAIError } from "../../error.mjs";
import { EventStream } from "../EventStream.mjs";
import { accumulateResponse } from "./ResponseAccumulator.mjs";
import { maybeParseResponse } from "../ResponsesParser.mjs";
export class ResponseStream extends EventStream {
constructor(params) {
super();
_ResponseStream_instances.add(this);
_ResponseStream_params.set(this, void 0);
_ResponseStream_currentResponseSnapshot.set(this, void 0);
_ResponseStream_finalResponse.set(this, void 0);
__classPrivateFieldSet(this, _ResponseStream_params, params, "f");
}
static createResponse(client, params, options) {
const runner = new ResponseStream(params);
runner._run(() => runner._createOrRetrieveResponse(client, params, {
...options,
headers: { ...options?.headers, 'X-Stainless-Helper-Method': 'stream' },
}));
return runner;
}
async _createOrRetrieveResponse(client, params, options) {
this._listenForAbort(options?.signal);
__classPrivateFieldGet(this, _ResponseStream_instances, "m", _ResponseStream_beginRequest).call(this);
let stream;
let starting_after = null;
if ('response_id' in params) {
stream = await client.responses.retrieve(params.response_id, { stream: true }, { ...options, signal: this.controller.signal, stream: true });
starting_after = params.starting_after ?? null;
}
else {
stream = await client.responses.create({ ...params, stream: true }, { ...options, signal: this.controller.signal });
}
this._connected();
for await (const event of stream) {
__classPrivateFieldGet(this, _ResponseStream_instances, "m", _ResponseStream_addEvent).call(this, event, starting_after);
}
if (stream.controller.signal?.aborted) {
throw new APIUserAbortError();
}
return __classPrivateFieldGet(this, _ResponseStream_instances, "m", _ResponseStream_endRequest).call(this);
}
[(_ResponseStream_params = new WeakMap(), _ResponseStream_currentResponseSnapshot = new WeakMap(), _ResponseStream_finalResponse = new WeakMap(), _ResponseStream_instances = new WeakSet(), _ResponseStream_beginRequest = function _ResponseStream_beginRequest() {
if (this.ended)
return;
__classPrivateFieldSet(this, _ResponseStream_currentResponseSnapshot, undefined, "f");
}, _ResponseStream_addEvent = function _ResponseStream_addEvent(event, starting_after) {
if (this.ended)
return;
const maybeEmit = (name, event) => {
if (starting_after == null || event.sequence_number > starting_after) {
this._emit(name, event);
}
};
const response = accumulateResponse(event, __classPrivateFieldGet(this, _ResponseStream_currentResponseSnapshot, "f"));
__classPrivateFieldSet(this, _ResponseStream_currentResponseSnapshot, response, "f");
maybeEmit('event', event);
switch (event.type) {
case 'response.output_text.delta': {
const output = response.output[event.output_index];
if (!output) {
throw new OpenAIError(`missing output at index ${event.output_index}`);
}
if (output.type === 'message') {
const content = output.content[event.content_index];
if (!content) {
throw new OpenAIError(`missing content at index ${event.content_index}`);
}
if (content.type !== 'output_text') {
throw new OpenAIError(`expected content to be 'output_text', got ${content.type}`);
}
maybeEmit('response.output_text.delta', {
...event,
snapshot: content.text,
});
}
break;
}
case 'response.function_call_arguments.delta': {
const output = response.output[event.output_index];
if (!output) {
throw new OpenAIError(`missing output at index ${event.output_index}`);
}
if (output.type === 'function_call') {
maybeEmit('response.function_call_arguments.delta', {
...event,
snapshot: output.arguments,
});
}
break;
}
default:
maybeEmit(event.type, event);
break;
}
}, _ResponseStream_endRequest = function _ResponseStream_endRequest() {
if (this.ended) {
throw new OpenAIError(`stream has ended, this shouldn't happen`);
}
const snapshot = __classPrivateFieldGet(this, _ResponseStream_currentResponseSnapshot, "f");
if (!snapshot) {
throw new OpenAIError(`request ended without sending any events`);
}
__classPrivateFieldSet(this, _ResponseStream_currentResponseSnapshot, undefined, "f");
const parsedResponse = finalizeResponse(snapshot, __classPrivateFieldGet(this, _ResponseStream_params, "f"));
__classPrivateFieldSet(this, _ResponseStream_finalResponse, parsedResponse, "f");
return parsedResponse;
}, Symbol.asyncIterator)]() {
const pushQueue = [];
const readQueue = [];
let done = false;
this.on('event', (event) => {
const reader = readQueue.shift();
if (reader) {
reader.resolve(event);
}
else {
pushQueue.push(event);
}
});
this.on('end', () => {
done = true;
for (const reader of readQueue) {
reader.resolve(undefined);
}
readQueue.length = 0;
});
this.on('abort', (err) => {
done = true;
for (const reader of readQueue) {
reader.reject(err);
}
readQueue.length = 0;
});
this.on('error', (err) => {
done = true;
for (const reader of readQueue) {
reader.reject(err);
}
readQueue.length = 0;
});
return {
next: async () => {
if (!pushQueue.length) {
if (done) {
return { value: undefined, done: true };
}
return new Promise((resolve, reject) => readQueue.push({ resolve, reject })).then((event) => (event ? { value: event, done: false } : { value: undefined, done: true }));
}
const event = pushQueue.shift();
return { value: event, done: false };
},
return: async () => {
this.abort();
return { value: undefined, done: true };
},
};
}
/**
* @returns a promise that resolves with the final Response, or rejects
* if an error occurred or the stream ended prematurely without producing a REsponse.
*/
async finalResponse() {
await this.done();
const response = __classPrivateFieldGet(this, _ResponseStream_finalResponse, "f");
if (!response)
throw new OpenAIError('stream ended without producing a ChatCompletion');
return response;
}
}
function finalizeResponse(snapshot, params) {
return maybeParseResponse(snapshot, params);
}
//# sourceMappingURL=ResponseStream.mjs.map
File diff suppressed because one or more lines are too long