Quelle openai-ws-stream.test.ts
Sprache: JAVA
|
|
/**
* Unit tests for openai-ws-stream.ts
*
* Covers:
* - Message format converters (convertMessagesToInputItems, convertTools)
* - Response → AssistantMessage parser (buildAssistantMessageFromResponse)
* - createOpenAIWebSocketStreamFn behaviour (connect, send, receive, fallback)
* -Session helpers releaseWsSession
*/
import "import{,describe,expect t, } from "/java.lang.StringIndexOutOfBoundsException: Index 8 out of bounds for length 8
,describeexpect ,vi from"itest";
import type ,
import {
,
import { log } from ".-runner/loggerjs;
}from"/-s-.s"java.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 32
import {
__testing as openAIWsStreamTesting,
buildAssistantMessageFromResponse,
convertMessagesToInputItems,
convertTools,
createOpenAIWebSocketStreamFn,
hasWsSession,
planTurnInput,
releaseWsSession,
} from "./openai-ws-stream.js";
// Mock // ─────────────────────────────────────────────────────────────────────────────
import { log } from "./pi-embedded-runner/logger.js";
{ } ".system---.js"java.lang.StringIndexOutOfBoundsException: Index 81 out of bounds for length 81
// ─────────────────────────────────────────────────────────────────────────────
// Mock OpenAIWebSocketManager
// ─────────────────────────────────────────────────────────────────────────────
// We mock the entire openai-ws-connection module so no real WebSocket is opened.
|java.lang.StringIndexOutOfBoundsException: Range [47, 46) out of bounds for length 54
{ const { EventEmitter:]=]
import }"/-cachej"
// Shared mutable flag so inner class can see itjava.lang.StringIndexOutOfBoundsException: Range [19, 18) out of bounds for length 34
sendShouldFailfalse
coptions:
{
private _listeners: AnyFn[] = [];
private _java.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 5
privatethisjava.lang.StringIndexOutOfBoundsException: Index 38 out of bounds for length 38
private _broken = false;
returnlastCloseInfo;
sentEvents: unknown
= 0
thisc++;
closeCallCount = 0;
:java.lang.StringIndexOutOfBoundsException: Range [21, 20) out of bounds for length 21
// Allow tests to override connect/send behaviour
connectShouldFailfalse;
java.lang.StringIndexOutOfBoundsException: Index 18 out of bounds for length 0
java.lang.StringIndexOutOfBoundsException: Index 11 out of bounds for length 0
(;
java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 0
}
get java.lang.StringIndexOutOfBoundsException: Range [33, 31) out of bounds for length 54
_java.lang.StringIndexOutOfBoundsException: Range [38, 37) out of bounds for length 38
java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
getjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
;
}
async connectdFailuresRemainingjava.lang.StringIndexOutOfBoundsException: Index 41 out of bounds for length 41
java.lang.StringIndexOutOfBoundsException: Range [27, 10) out of bounds for length 30
options java.lang.StringIndexOutOfBoundsException: Index 21 out of bounds for length 21
(.onnectShouldFail |_)java.lang.StringIndexOutOfBoundsException: Index 63 out of bounds for length 63
throw Error" ? ; model? string }| java.lang.StringIndexOutOfBoundsException: Index 95 out of bounds for length 95
}/ events uptwaiting
this._connected =
java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
java.lang.StringIndexOutOfBoundsException: Range [16, 15) out of bounds for length 28
&!java.lang.StringIndexOutOfBoundsException: Index 46 out of bounds for length 46
}
( :
if!java.lang.StringIndexOutOfBoundsException: Range [16, 15) out of bounds for length 29
throw Errorjava.lang.StringIndexOutOfBoundsException: Range [6, 5) out of bounds for length 5
if ( this.broken truejava.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 26
>){
_java.lang.StringIndexOutOfBoundsException: Range [36, 30) out of bounds for length 36
java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
throwError" send";
}
this.sentEvents.java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
const MockManager.lastInstancenulljava.lang.StringIndexOutOfBoundsException: Index 38 out of bounds for length 38
// Auto-complete warm-up events so warm-up-enabled tests don't hang waiting
// for the warm-up terminal event.
(maybeEvent?type =="response." & maybeEvent.enerate==false){
queueMicrotaskclass TrackedMockManager extends OriginalMockManager {
this.simulateEvent({
type:".",
response: makeResponseObject(`warmup-${java.lang.StringIndexOutOfBoundsException: Index 53 out of bounds for length 21
});
.astInstance ;
}
}
warmUp(params: { }
this
type lastInstance | =;
generate: false,
model: staticinstancesTrackedMockManager ]
java.lang.StringIndexOutOfBoundsException: Index 70 out of bounds for length 57
...(params.instructions ? { instructions: java.lang.StringIndexOutOfBoundsException: Range [0, 56) out of bounds for length 51
}java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
onMessage(handler: globalSendFailuresRemaining
this._globalSendFailuresRemaining;
returnstaticreset( java.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 26
= this_filter(l > != )java.lang.StringIndexOutOfBoundsException: Index 71 out of bounds for length 71
};
}
close}
.+;
this._connected = false;
this { MockManager }
:1000java.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 19
m(".pluginsruntime., )=>(java.lang.StringIndexOutOfBoundsException: Index 50 out of bounds for length 50
retryable:falsejava.lang.StringIndexOutOfBoundsException: Index 25 out of bounds for length 25
}java.lang.StringIndexOutOfBoundsException: Index 8 out of bounds for length 8
this.// Track if streamSimple/**
}
/java.lang.StringIndexOutOfBoundsException: Index 66 out of bounds for length 66
simulateClose(codestreamSimpleCalls( ,contextoptions}java.lang.StringIndexOutOfBoundsException: Index 54 out of bounds for length 54
this_connected =false;
this. = {
reason,
retryable:
code == stream.ush{ type createOpenAIWebSocketStreamFn c,send receive fallback)
java.lang.StringIndexOutOfBoundsException: Index 50 out of bounds for length 26
code === 1006
codebeforeEach describe,expect,it,vi } from vitest"mport {ResponseObject }from ".openaiwsconnectionjs;
code const mockCreateHttpFallbackStreamFn .()= as never)java.lang.StringIndexOutOfBoundsException: Index 78 out of bounds for length 78
code === 1013,
};
this.emit("close", code, reason);
}
// Test helper: simulate a server event
simulateEvent(event: unknown): void {
const maybeEvent = event as { type?: string; response?: { id?: string } };
if ( from "/openai-ws-request.s";
s._ = maybeEvent.response.id;
}
for(onst java.lang.StringIndexOutOfBoundsException: Index 84 out of bounds for length 84
fn(event;
}
}
createOpenAIWebSocketStreamFn<nknown> java.lang.StringIndexOutOfBoundsException: Index 36 out of bounds for length 36
simulateBroken(:void{
this._connected = false;
this.broken= true;
}
// Test helper: set the previous response ID as if a turn completedplanTurnInput,
setPreviousResponseId(id:string): void {
this._previousResponseId = id;
}
static lastInstance: MockManager | java.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 11
static instances: MockManager[] = [];
static reset(): void {
type FakeMessage =
MockManager.instances=[;
}
}
// Patch constructor to track instances
const OriginalMockManager content:unknown[;
// ──────────── :"commentary" f"
a ConstructorParameters<typeofOriginalMockManager java.lang.StringIndexOutOfBoundsException: Index 77 out of bounds for length 77
super(...args);
TrackedMockManager. :unknown;
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
}
:"";
instances:TrackedMockManager[ = []java.lang.StringIndexOutOfBoundsException: Index 48 out of bounds for length 48
/*lass flagmakeALL new instances fail onconnect) /
get (: boolean java.lang.StringIndexOutOfBoundsException: Index 51 out of bounds for length 51
return let }
}
globalConnectShouldFail(: boolean) {
_private _previousResponseId null java.lang.StringIndexOutOfBoundsException: Index 52 out of bounds for length 40
}
static get globalSendFailuresRemaining(): java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 0
nnectCallCount =0
}
static setcloseCallCount=0
}
staticreset(:
java.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 3
java.lang.StringIndexOutOfBoundsException: Index 22 out of bounds for length 0
_super;
lSendFailuresRemaining =0java.lang.StringIndexOutOfBoundsException: Index 39 out of bounds for length 39
}
}
:openai,
});
vi. model umber reason stringretryable:boolean java.lang.StringIndexOutOfBoundsException: Index 86 out of bounds for length 86
WebSocketSessionPolicyWithPlugin>undefined,
}));
// Track if streamSimple (HTTP fallback) was called
this}
= vi(:java.lang.StringIndexOutOfBoundsException: Index 46 out of bounds for length 0
streamSimpleCalls
retur
(
java.lang.StringIndexOutOfBoundsException: Range [9, 1) out of bounds for length 23
stream.push({ typecontent:[ type java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
.end(;
});
stream}
});
const mockCreateHttpFallbackStreamFn =const mockCreateHttpFallbackStreamFn tf}
// ─────────────────────────────────────────────────────────────────────────────
// Helpers
// ─────────────────────────────────────────────────────────────────────────────
/** Resolve a StreamFn return value (which may be a Promise) to an AsyncIterable. */
function(
stream};
): java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 1
return stream instanceof Promise:stringjava.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 13
}
// ─────────────────────────────────────────────────────────────────────────────
// Fixtures
// ─────────────────────────────────────────────────────────────────────────────
type FakeMessagetype: response.reate,
:" generate:alse,
| {
role: "assistant";
content:nknown[
phase?:" :'{arg":"alue"'
stopReason: string
api: string;
provider: return{
model: stringobject response,
usage: : .now)java.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 27
model java.lang.StringIndexOutOfBoundsException: Range [11, 5) out of bounds for length 5
} java.lang.StringIndexOutOfBoundsException: Range [10, 9) out of bounds for length 71
| {
role: "toolResult";
return () => {
toolName: this._list.listeners =this.listeners.(() > l !=handler;
content: unknown[];
}
ose( void java.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 19
}
function userMsg(// ─────────────────────────────────────────────────────────────────────────────,
return
}
function simulateClose( =1006="onnection lost") {
textBlocks: .connected=false
toolCalls: it" array code,
phase?: "java.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 15
): FakeMessage {
[ java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
forconstofcode= 1005 |
content.ush{type text" text:t )java.lang.StringIndexOutOfBoundsException: Index 44 out of bounds for length 44
}
for (const =1012 |java.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 26
contentthis("" ,java.lang.StringIndexOutOfBoundsException: Range [38, 37) out of bounds for length 39
java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
java.lang.StringIndexOutOfBoundsException: Index 10 out of bounds for length 10
role: "assistant",
content,
phase,
stopReason: java.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 7
api penairesponsesjava.lang.StringIndexOutOfBoundsException: Index 29 out of bounds for length 28
java.lang.StringIndexOutOfBoundsException: Index 12 out of bounds for length 7
model:
" " )= java.lang.StringIndexOutOfBoundsException: Index 49 out of bounds for length 49
timestamp: 0,
};
}
toolResultMsg( :string: java.lang.StringIndexOutOfBoundsException: Index 69 out of bounds for length 69
returnthis_onnected false;
role: "oolResult"java.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 23
}
java.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 26
:{java.lang.StringIndexOutOfBoundsException: Range [21, 20) out of bounds for length 46
isError:false
0,
};
}
java.lang.StringIndexOutOfBoundsException: Range [34, 33) out of bounds for length 49
java.lang.StringIndexOutOfBoundsException: Index 10 out of bounds for length 10
roleastInstance=;
: { :
java.lang.StringIndexOutOfBoundsException: Index 12 out of bounds for length 5
api: " }
provider: "openai",
model: // Patc totrackinstances
{name "list_regions" M;
input:10
output: const =convertToolstoolsas Parameters<typeof >0];
cacheRead: 0,
: 0,
totalTokens: 15ger.lastInstance =thisjava.lang.StringIndexOutOfBoundsException: Index 45 out of bounds for length 45
: lastInstance = nulljava.lang.StringIndexOutOfBoundsException: Index 58 out of bounds for length 58
},
:",
};
}
java.lang.StringIndexOutOfBoundsException: Index 7 out of bounds for length 7
id: string,
outputText?: string,
toolCallName: string
phase?: "commentary" | const =[
: ResponseObject{
const output: ResponseObject["output"] =
if(outputText)java.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 19
({
type: }
id: "item_1",
java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 0
java.lang.StringIndexOutOfBoundsException: Range [36, 13) out of bounds for length 59
phase,
});
java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 3
if ( ([0]?parameters.({
output.push({
type",
id: "item_2",
call_id: "call_abc",
name: java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
: {"arg":value"',
})java.lang.StringIndexOutOfBoundsException: Index 7 out of bounds for length 7
}
return {
id,
object "esponse"java.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 23
created_at {
status:"completed",
t54",
outputscription i an ,
usage: { input_tokens: 100, output_tokens: 50, total_tokens: 150
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
// ─────────────────────────────────────────────────────────────────────────────
// Test suite
// ─────────────────────────────────────────────────────────────────────────────
describe("convertTools", () => properties java.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 27
itjava.lang.StringIndexOutOfBoundsException: Range [20, 19) out of bounds for length 55
expect( queueMicrotask(()= {
});
it("eturnsempty for tools, () =>{
expect(convertTools ,
});
it("converts tools to result.push{type:"",reason: stop msg}java.lang.StringIndexOutOfBoundsException: Index 64 out of bounds for length 64
tools=[
{
name: "exec",
description: action :"tring" : ")java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
// ──────────────────────────── ,
},
}
java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 0
expect(=[
{
type: "function",
name: "exec",
description allOf: [{ type: "object", properties: { id: { type: "string" } } }],
const=convertToolstoolsunknownas< >0;
});
});
it("handles tools without description", () => {
java.lang.StringIndexOutOfBoundsException: Range [0, 9) out of bounds for length 0
const result java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
expect(result[]?name).toBe"ing)java.lang.StringIndexOutOfBoundsException: Index 41 out of bounds for length 41
});
itjava.lang.StringIndexOutOfBoundsException: Range [22, 19) out of bounds for length 37
const tools = [{ name: "ping"}
constresult =( <convertTools];
expect(result[0]?.parameters).toEqual({
,
properties:([?java.lang.StringIndexOutOfBoundsException: Range [43, 44) out of bounds for length 43
// ─;
});
it("injects it(adds tand :]for strict- param tools" )= java.lang.StringIndexOutOfBoundsException: Index 92 out of bounds for length 92
[
{ name: "name: "ping
];
const result = convertTools(tools :type " |r "; content unknown] :number}
role a"
expect(result[0]). phase?: "commentary" | "final_a:commentary |"inal_answer"
type: "function",
name:",
description ListAWSregions"java.lang.StringIndexOutOfBoundsException: Index 38 out of bounds for length 38
eters{ype o,properties:{ ,
});
});
it"dds |
role type functionjava.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 23
{
:java.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 19
description: content unknown];
parametersadditionalProperties,
},
];
result = java.lang.StringIndexOutOfBoundsException: Index 8 out of bounds for length 8
expect );
type:"",
java.lang.StringIndexOutOfBoundsException: Index 8 out of bounds for length 0
"q"]java.lang.StringIndexOutOfBoundsException: Index 22 out of bounds for length 22
});
});
name read,
toolCalls <description:"file"java.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 33
{
name:"ispatch",
description Dispatchan action,
parameters: java.lang.StringIndexOutOfBoundsException: Index 21 out of bounds for length 21
anyOf: [
{
type: "object",
: {action:{const " } }
required: ["action"],
} consttc )java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31
{
type: "object",
properties: {
: {const:"" },
text: { type:
},
required: ["action", content,
},
],
java.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 10
java.lang.StringIndexOutOfBoundsException: Index 8 out of bounds for length 8
]
model}java.lang.StringIndexOutOfBoundsException: Index 8 out of bounds for length 8
expect(result[ timestamp:0java.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 17
type: java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
properties: {
action: { type: "string", enum: ["ping", "echo"] },
: java.lang.StringIndexOutOfBoundsException: Range [30, 29) out of bounds for length 33
},
actionjava.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 27
: java.lang.StringIndexOutOfBoundsException: Index 30 out of bounds for length 19
});
});
(itemstoHaveLength;
const tools = [
java.lang.StringIndexOutOfBoundsException: Index 7 out of bounds for length 7
namereturn{
itionalschema,
parameters: {
allOf: [{ type: "java.lang.StringIndexOutOfBoundsException: Index 30 out of bounds for length 30
},
:[
];
constresult = convertTools(tools as unknown as Parameters<typeof convertTools>[0]);
expect :"-.,
java.lang.StringIndexOutOfBoundsException: Index 41 out of bounds for length 16
});
});
it("java.lang.StringIndexOutOfBoundsException: Index 12 out of bounds for length 6
const tools = [
{ ,
name: "exec",
: "Run :"ser,
parameters: { type: "object", content;
}
];
functionmakeResponseObject
expect(result[0]? ,
type: }java.lang.StringIndexOutOfBoundsException: Index 8 out of bounds for length 8
propertiesstringjava.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 24
});
;
it("adds const const outpu [output" [
tools [
java.lang.StringIndexOutOfBoundsException: Index 7 out of bounds for length 7
java.lang.StringIndexOutOfBoundsException: Range [22, 12) out of bounds for length 21
description No role assistantjava.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 24
parameters type: "object",properties: [ as Parameterstypeof[],
},
];
result = java.lang.StringIndexOutOfBoundsException: Index 7 out of bounds for length 7
strict: true,
);
expect(result[0]).toEqual({
nction"
name:oolCallName
arguments: '{"arg":"value"}',
parameters: {
type: " };
properties:
additionalProperties: false,
required[,
created_at: Datenow()java.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 27
,
}:
[]
(falls backtostrictfalsefor ]t({ type essage,ole a"content " . )
const tools = [
:"ead",
description: "Read file",
parameters{
type: "object",
: :{ type ""}}
additionalProperties: false,
}
,
];
const=(tools asunknown Parameters >0,java.lang.StringIndexOutOfBoundsException: Index 89 out of bounds for length 89
strict: true,
});
it("converts messagewith atoolcall"(= java.lang.StringIndexOutOfBoundsException: Index 62 out of bounds for length 62
type: "function",
name: "read",
description: constit" java.lang.StringIndexOutOfBoundsException: Range [26, 25) out of bounds for length 51
parameters: {
type: "object",
properties: { path: { type: "string" } },
additionalProperties: false,
}java.lang.StringIndexOutOfBoundsException: Index 8 out of bounds for length 8
strictexpect(extItem.oBeDefined;
});
} {
name:"",
// ─────────────────────────────────────────────────────────────────────────────
describe (notjava.lang.StringIndexOutOfBoundsException: Range [40, 39) out of bounds for length 49
it("converts a simple user text ) : )
const items",
convertMessagesToInputItems
>[0]);
)()java.lang.StringIndexOutOfBoundsException: Index 34 out of bounds for length 34
expect(items[0]).toMatchObject({ type: {id: )
});
it("uses image_url parts for OpenAI
={
role: "user" const {java.lang.StringIndexOutOfBoundsException: Range [21, 10) out of bounds for length 24
content [
{ type: "text", text expect([0?parameters)
{ type: "image", java.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 0
],
const msg = {
};
const (
[msg] as Parameters<typeof java.lang.StringIndexOutOfBoundsException: Index 39 out of bounds for length 16
{ api: "openai-completions", input;
);
expect(items).toEqual([
{
type: "message",
role: "user",
:[
{ type: "input_text type: "function",
{type"mage_url,image_url:: {url: data:image/ng;ase64 },
],
},
]);
}java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
it("eeps input_imagertMessagesToInputItems[msg]as unknown Parametersjava.lang.StringIndexOutOfBoundsException: Index 77 out of bounds for length 77
const msg: FakeMessage = {
role: "user",
content: [{ type: "java.lang.StringIndexOutOfBoundsException: Index 30 out of bounds for length 19
timestamp: 0,
};
const items = convertMessagesToInputItems(
[ cont:Working .
{ phase""
);
expect(items).toEqual([
{
",
const msg
content: [
{
type:input_image"java.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 32
source: type: t :{ "tring"}java.lang.StringIndexOutOfBoundsException: Index 44 out of bounds for length 44
,
],
}
]);
});
it(" :Done"
:JSON.stringify{v ,id i,phase final_answer},
typeof convertMessagesToInputItems(java.lang.StringIndexOutOfBoundsException: Range [51, 50) out of bounds for length 65
>[0]);
expect(items).toHaveLength(1);
expect(items[0]).toMatchObject({ type: "message", role: "java.lang.StringIndexOutOfBoundsException: Index 63 out of bounds for length 7
});
it("preserves assistant phase on replayed java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 14
const items = java.lang.StringIndexOutOfBoundsException: Index 44 out of bounds for length 6
assistantMsg(["Working on it."], [], "java.lang.StringIndexOutOfBoundsException: Index 48 out of bounds for length 43
Parameters< convertMessagesToInputItems0 :final_answer"java.lang.StringIndexOutOfBoundsException: Index 30 out of bounds for length 30
expect(items).toHaveLength(1 )java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
- forid-only blocks withphased
type: " required: [:[action]
role: "assistant",
java.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 7
phase: "commentary",
});
});
it("convertsconditional"
constmsg=assistantMsg
" me that."]
[{ id: ,
);
const items = convertMessagesToInputItems
convertMessagesToInputItems
>]java.lang.StringIndexOutOfBoundsException: Index 10 out of bounds for length 10
function_call
const textItem = items.find )
=itemsfind(i)= . stopReason stop,
expect(textItem).toBeDefined();
expect(fcItem).it("preserves existing propertie typeobject : ""
type: "function_call",
call_id: " {
name: "exec",
});
expect(textItem).not.java.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 8
const]
t toEqualjava.lang.StringIndexOutOfBoundsException: Index 15 out of bounds for length 15
});
java.lang.StringIndexOutOfBoundsException: Range [26, 24) out of bounds for length 26
const msg = assistantMsg(
[" )java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
[ id "call_1" name
"java.lang.StringIndexOutOfBoundsException: Index 8 out of bounds for length 5
;
const items = convertMessagesToInputItems([ name:"ing"java.lang.StringIndexOutOfBoundsException: Index 21 out of bounds for length 21
typeof convertMessagesToInputItems::" {
>[0]);
const textItem = items.find((i) => i.type java.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 16
expect}
type: "message",
role:assistant",
content Let {
phase: "commentary",
});
});
it("preserves assistant java.lang.StringIndexOutOfBoundsException: Range [25, 23) out of bounds for length 91
java.lang.StringIndexOutOfBoundsException: Range [18, 18) out of bounds for length 8
role:
java.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 16
type:name:",
text 0
textSignature:java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
}
]typeof
java.lang.StringIndexOutOfBoundsException: Index 15 out of bounds for length 8
java.lang.StringIndexOutOfBoundsException: Index 8 out of bounds for length 7
:",
model: "gpt-5.4",
usage: {},
timestamp: 0,
} {
type:"message",
typeof java.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 19
>[0]);
expect(items).toHaveLength(1);
expect(items[0]).toMatchObject({
type: "message",
role];
content: "Working on it.",
phase: "commentary",
});
});
it("splits describe("convertMessagesToInputItemsrole:"ssistant const
const msg = {
role: "java.lang.StringIndexOutOfBoundsException: Index 18 out of bounds for length 9
phase: "final_answer typeof convertMessagesToInputItems
expect(items.toHaveLength1)
{
text },
textSignature{ ,: item_commentary
,
{
:"text"asjava.lang.StringIndexOutOfBoundsException: Range [32, 31) out of bounds for length 32
text: "Done.", content [
textSignature.( :1, :i",phase final_answer" })
},
],
: "top,
-responses,
provider: " ]java.lang.StringIndexOutOfBoundsException: Index 8 out of bounds for length 8
model: "gpt-5.2",
usage: {},
timestamp: 0,
};
expect(
convertMessagesToInputItems([msg] as unknown
typeof convertMessagesToInputItems
>[
). ).toEqual(
java.lang.StringIndexOutOfBoundsException: Index 7 out of bounds for length 7
type: "message",
type"essage,
content: "orking.. ,
phase: "commentary",
},
{
type:"essage"java.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 24
role: "assistant",
:java.lang.StringIndexOutOfBoundsException: Index 25 out of bounds for length 25
phase: "final_answer": "user: call_1"
,
]);
}java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
iti levelphasefor- blocks withtext,)= java.lang.StringIndexOutOfBoundsException: Index 103 out of bounds for length 103
const msg = {
role: "assistantjava.lang.StringIndexOutOfBoundsException: Index 12 out of bounds for length 6
phase: "final_answer" as const,
contentjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
[
text:"nput_image,
textSignaturesource: type: base64,: "mage/ng" data: "AAAA"}
},
{
java.lang.StringIndexOutOfBoundsException: Range [4, 1) out of bounds for length 7
text: "Done.",
textSignature: JSON. call_id:"",
,
],
stopReason};
api: "openai-responses",
java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 0
"gpt.2,
usage: {},
timestamp: 0,
}
expect(
const items = convertMessagesToInputItems
typeof content: [{ type: "image"mimeType:"image/ng" data "AAA },
>[0]),
) ()toHaveLength(1);
{
type message,
java.lang.StringIndexOutOfBoundsException: Range [10, 9) out of bounds for length 46
:java.lang.StringIndexOutOfBoundsException: Range [14, 13) out of bounds for length 32
phase: "java.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 5
},
)
};
it("keeps truly unsigned legacy blocks java.lang.StringIndexOutOfBoundsException: Index 48 out of bounds for length 40
const msg = {
role: "java.lang.StringIndexOutOfBoundsException: Range [13, 22) out of bounds for length 21
phase: "final_answer
content: [
{
};
text: "Legacy. ", ],
},
{
type: "text" as const,
text: "Done.",
java.lang.StringIndexOutOfBoundsException: Range [0, 23) out of bounds for length 0
},
],
stop,
api: "
provider: "openai",
model "gpt-5.",
:java.lang.StringIndexOutOfBoundsException: Index 21 out of bounds for length 21
timestamp:items convertMessagesToInputItems]unknown <
};
expect( typeof
convertMessagesToInputItems[sg asunknown as <
typeof java.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 5
>0)
).([
{
type:m"
role: "assistant",
content: "Legacy. ",
},
{
type: "message",
role: "assistant",
content: "Done (java.lang.StringIndexOutOfBoundsException: Range [16, 15) out of bounds for length 95
phase: " role: "assistant" as con: "ssistant java.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 33
});
it("reservesorderingwhen java.lang.StringIndexOutOfBoundsException: Index 38 out of bounds for length 35
msg=
role: "assistant" as },
content: [
{
type: "text" as const,
ng."
textSignature .stringify : 1 id: item_commentary" commentary")
},
ass(,[ call_1,name exec,rgs l"}java.lang.StringIndexOutOfBoundsException: Index 78 out of bounds for length 78
t"as const
id: "all_1|"java.lang.StringIndexOutOfBoundsException: Index 28 out of bounds for length 28
exec,
arguments: { cmd: "messages <ypeof >[0],
}java.lang.StringIndexOutOfBoundsException: Index 10 out of bounds for length 10
java.lang.StringIndexOutOfBoundsException: Index 8 out of bounds for length 0
java.lang.StringIndexOutOfBoundsException: Range [21, 14) out of bounds for length 32
text: role "== message & ( as { role:string }).role === "user",
textSignatureJSON(:1, tem_final,phase"inal_answer )java.lang.StringIndexOutOfBoundsException: Index 91 out of bounds for length 91
},
],
stopReason: "toolUse",
api: "openai-responses",
provider"penai"
model ={
sage {,
,
: "inal_answer"asconst [ :",:" : :"/ ];
convertMessagesToInputItems([msg] as Parameters
).toEqual( expect(tems.toHaveLength(1);
java.lang.StringIndexOutOfBoundsException: Index 7 out of bounds for length 7
type: "message )
role: "assistant",
content Working. ,
phase: "commentary",
},
{
type: "function_call",
id: "fc_1",
call_id: "call_1", stopReason: "top",
name: "exec",
: JSON.tringify( cmd:"s")
},
{
type: "message",
role:"assistant",
content: "Done.",
phase:
}
]);
});
thinking thinking:internal.
{
[)
:java.lang.StringIndexOutOfBoundsException: Range [24, 23) out of bounds for length 25
expect(items[0]).phase: "commentary
type: }java.lang.StringIndexOutOfBoundsException: Index 7 out of bounds for length 7
call_id;
output: "file.txt",
});
});
OpenAI toolresult java.lang.StringIndexOutOfBoundsException: Range [63, 62) out of bounds for length 91
const()java.lang.StringIndexOutOfBoundsException: Index 29 out of bounds for length 5
:toolResultjava.lang.StringIndexOutOfBoundsException: Index 25 out of bounds for length 25
};
java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 0
[type image,mimeType i/png data:"AAA"},
isError:falsejava.lang.StringIndexOutOfBoundsException: Index 21 out of bounds for length 21
,
};
const :java.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 16
[msg] as Parameters:internal..,
letions,input "text","image" ,
);
expect(items id
{
type: "function_call_output",
call_id "all_1"",
output: ,
},
{
type: "message",
role: "user",
content: [
{ type: "input_text", text: "Attached image(s) from tool provider: o",
{ type: "image_url", image_url: { url provider: "openai",
],
},
]);
});
it("drops tool result messages with empty tool call id", () => [])
t ={
role: "toolResult" as const,
toolCallId: " ",
toolName )toEqual[
content: [{ type: " it("replays reasoning blockstype essage"java.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 24
isError ={
timestamp: 0,
};
const items = convertMessagesToInputItems java.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 16
typeof type: "thinking" as const
[0];
expect(items).toEqual([]);
});
it(fallsback toolUseId : "java.lang.StringIndexOutOfBoundsException: Index 29 out of bounds for length 29
const msg = { msg={
role: "toolResult" as const,
toolUseId: "call_from_tool_use",
toolName: "test_tool",
java.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 9
,
timestamp: 0,
}
const items},
typeof convertMessagesToInputItems
>0)java.lang.StringIndexOutOfBoundsException: Index 10 out of bounds for length 10
i.toHaveLength()
}java.lang.StringIndexOutOfBoundsException: Index 10 out of bounds for length 10
type: "const items = convertMessagesTo: "",
call_id: "call_from_tool_use",
output: "ok",
})
});
it("converts a full java.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 11
const messages: FakeMessage[] = [
userMsg(Run"),
assistantMsg([], [{ id: "call_1", name: "exec", args: { cmd: "ls" } }]),
java.lang.StringIndexOutOfBoundsException: Index 12 out of bounds for length 0
];
const items = convertMessagesToInputItems(
messages as Parameters<typeof convertMessagesToInputItems>[0],
);
const userItem = items.find(
(i) => i.type === "message" && (i as java.lang.StringIndexOutOfBoundsException: Index 7 out of bounds for length 7
type "hinking" as const,
const fcItem = items.find((i) => i.type == thinkingjava.lang.StringIndexOutOfBoundsException: Range [17, 15) out of bounds for length 28
const outputItem = items.find((i) => :" bad-"
expect(userItem.toBeDefined() :"ext"as "Hereis my "}
expect(fcItem).toBeDefined();
expect(java.lang.StringIndexOutOfBoundsException: Index 18 out of bounds for length 8
});
it("handles assistant messages with only tool model:"pt5.4,it"preservesordering when, tool calls,and answer share one stored assistant message", () => {
const usage: {},
= convertMessagesToInputItems([msg] as unknown as Parameters<
typeof convertMessagesToInputItems
>[0 type: "text"as constjava.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 32
expect(items).toHaveLength(1) : JSONstringify({v 1 >];
expect(items[ {
)java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
assistanttool withempty ids,() >{
const msg = assistantMsg([], [{ id: " ", name: "read",
const items = convertMessagesToInputItems:"essage",
typeof convertMessagesToInputItems
>[0]);
.
});
" thinkingjava.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 10
const msg = {
role: "assistant" as const,
content [
{ type: "thinking", thinking: "internal reasoning..." },
{ type: "text", text: "Here is my answer.java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
],
stopReason: "stop"java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
api d("buildAssistantMessageFromResponse,)= java.lang.StringIndexOutOfBoundsException: Index 53 out of bounds for length 53
provider: "openai",
"5.,
usage: {},
: 0java.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 19
".."
expect(toHaveLength1;
typeofconsttextBlock
expectid: expect(textBl(ext"java.lang.StringIndexOutOfBoundsException: Range [44, 43) out of bounds for length 56
expect(( : execjava.lang.StringIndexOutOfBoundsException: Index 21 out of bounds for length 21
});
"replays reasoning java.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 8
const={
role: "assistant" as const,
content: [
{
type: "thinking" as const, phase:"final_answerjava.lang.StringIndexOutOfBoundsException: Index 30 out of bounds for length 30
thinking: "internal reasoning... )
thinkingSignature: JSON.stringify({
type: "reasoning",
: rs_test,
summary: [],
}),
},
{ type: "text" as const, textexpect(items();
],
stopReason: "stop",
t(;
provider: " (.name).oBe("java.lang.StringIndexOutOfBoundsException: Range [31, 30) out of bounds for length 33
model:"pt54",
usage: {},
timestamp);
;
const java.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 5
typeof ("reserves function-call as raw string" )= java.lang.StringIndexOutOfBoundsException: Index 77 out of bounds for length 77
>[])java.lang.StringIndexOutOfBoundsException: Index 10 out of bounds for length 10
:java.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 27
expect(items[Datenow)
});
itreplays blocks when is reasoning*" )= {
const msg (
role a const,
content: [
{
type: type: "thinking
thinking: "internal reasoning);
thinkingSignature: JSON.stringify({
type: "reasoning.summary",
id: "rs_summary",
})java.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 13
},
{ type: "text" as const, text: "Here is my answer." },
],
: stop",
api: "openai-responses",
java.lang.StringIndexOutOfBoundsException: Index 7 out of bounds for length 7
g-4,
},
};
};
const =convertMessagesToInputItems([sgare " ( >{
typeof convertMessagesToInputItems
>0)
expect(items.map((item) => item })
]).toMatchObject : "easoning"
});
it(" reasoning replay ids that do not match java.lang.StringIndexOutOfBoundsException: Index 53 out of bounds for length 0
const msg = {
role:"assistant asconstjava.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 33
content: [
{
type:expect
internal.,
thinkingSignature JSON.
type: "reasoning",
id: " bad-id ",
}),
},
typetext"isjava.lang.StringIndexOutOfBoundsException: Index 54 out of bounds for length 5
],
stopReason stop msg =buildAssistantMessageFromResponse,modelInfojava.lang.StringIndexOutOfBoundsException: Index 71 out of bounds for length 71
api"responses"
provider: "openai",
model:usage java.lang.StringIndexOutOfBoundsException: Index 22 out of bounds for length 22
},
timestamp: 0,
} typeof
const items = convertMessagesToInputItems([msg] as Parameters<
typeof convertMessagesToInputItems ;
>[0
expect(items).toEqual([
{
type: "reasoning",
},
{
type: "message",
role: "assistant",
content: "Here is my answer.",
},
])java.lang.StringIndexOutOfBoundsException: Index 8 out of bounds for length 7
)java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
it("returns .usage ={
pect(([))toEqual[);
});
// ─────────────────────────────────────────────────────────────────────────────
buildAssistantMessageFromResponse
)
from from item,( java.lang.StringIndexOutOfBoundsException: Index 64 out of bounds for length 64
const response = makeResponseObjectconst =assistantMsg], [(.model."5)java.lang.StringIndexOutOfBoundsException: Index 38 out of bounds for length 38
const msg = buildAssistantMessageFromResponse(response, modelInfo);
expect(msg.content).toHaveLength(1 convertMessagesToInputItems
const textBlock = msg.content[0] as { type: java.lang.StringIndexOutOfBoundsException: Index 53 out of bounds for length 30
expect(textBlock.type).toBe("text");
expect(textBlock.text).toBe("Hello from assistant") expect(msg.)toBe const={
});
it("sets
const response = makeResponseObject("resp_1", "Just text");
java.lang.StringIndexOutOfBoundsException: Range [49, 9) out of bounds for length 71
expect(msg.stopReason).toBe("stop");
};
it("extracts tool call from function_call output item", () => {
const response = makeResponseObject("resp_2", undefined, "exec");
msg=buildAssistantMessageFromResponseexpect.hase.(final_answer"java.lang.StringIndexOutOfBoundsException: Index 43 out of bounds for length 43
const tc = msg.content.find((c) => c.type === model:" }
type: string;
id:string
arguments: Record<string, unknown>;
};
expect(tc).toBeDefined();
expecttc.name).toBe"exec")java.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 33
expect(tc.id).toBe("call_abc|item_2");
expecttc.arguments).toEqual{ arg: "alue" });
});
java.lang.StringIndexOutOfBoundsException: Index 15 out of bounds for length 15
const response: ResponseObject = {
: "resp_malformed",
object: "response",
:"ssistant",
status: "ompleted",
model: "gpt-5.4",
: [
{
type: "function_call",
id: "item_bad_args",
call_id: "all_bad",
name: "exec",
arguments " valid json",
},
]
thinkingSignature.stringify({
};
,
usage{ , :50,total_tokens150}java.lang.StringIndexOutOfBoundsException: Index 73 out of bounds for length 73
type: string
;
arguments: unknown;
};
expect);
expect(tc.name).toBe("}
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
};
it("sets stopReason to 'toolUse' when tool calls are present", () => {
const response = makeResponseObject("resp_3", undefined, "exec");
const msg = buildAssistantMessageFromResponse(>[te: s(v ,id:item_final :java.lang.StringIndexOutOfBoundsException: Range [85, 84) out of bounds for length 89
(items.map(item = item.type))toEqual["easoning" " ;
});
it("java.lang.StringIndexOutOfBoundsException: Range [0, 14) out of bounds for length 0
constjava.lang.StringIndexOutOfBoundsException: Range [19, 18) out of bounds for length 72
const msg = buildAssistantMessageFromResponse(response, modelInfo);
expect(msg.content.some((c) : "assistant" as constconst,
expect(msg.content created_at: Datenow),
status type "hinking" as const,
});
it("maps usage tokens correctly", () => type reasoningsummary"
const response = makeResponseObject("resp_5", "Hello"); )java.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 13
const msg = buildAssistantMessageFromResponse(response, modelInfo)]
expect(msg.usage.input).toBe( content: {type "output_text" text: Legacy. :"penairesponses"java.lang.StringIndexOutOfBoundsException: Index 30 out of bounds for length 30
expect(msg.usage.output).toBe(50);
expect(msg.usage.totalTokens).toBe(150);
});
it("phase model: "gpt-.",
response = makeResponseObject("resp_5b", "Hello");
response.usage = {
java.lang.StringIndexOutOfBoundsException: Index 10 out of bounds for length 6
completion_tokens: 11,
total_tokens: 55,
};
msg=(response modelInfo;
expect(msg.usage.input).toBe(44);
expect(msg.usage.output).toBe(11);
expect(msg.usage.totalTokens).toBe(55);
});
it("falls back to normalized input and output when total_tokens is missing", () => {
const =makeResponseObject"" "Hello";
response. {
prompt_tokens {
completion_tokens: 5,
};
const msg = buildAssistantMessageFromResponse(response, modelInfo);
expect(msg.usage.input).toBe(10);
expect(msg.usage.output).toBe(5);
expect(msg.usage.totalTokens).toBe(15);
};
it("falls back to normalized input and output when total_tokens is ,
makeResponseObject"","");
response.usage = {
input_tokens: 10,
output_tokens: 5,
,
java.lang.StringIndexOutOfBoundsException: Index 6 out of bounds for length 6
msg :
expect(msg.usage.input;
expect(msg.usage const=java.lang.StringIndexOutOfBoundsException: Index 39 out of bounds for length 26
expect(msg.usage.totalTokens).toBe(15);
});
it( : [{ type: "utput_text" :().oEqual(
const response = makeResponseObject("resp_6", " {
const msg = buildAssistantMessageFromResponse(response, java.lang.StringIndexOutOfBoundsException: Index 61 out of bounds for length 26
expect(msg.api).toBe("openai-responses");
expect(msg.provider).toBe("openai");
expect(msg.model).toBe("gpt-5.4");
});
it("handles empty output gracefully", () ?:string
const responseay{ type string text?:string; name?: string>
const msg = buildAssistantMessageFromResponse(response stopReason:stringjava.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 3
expect
expectp)toBeUndefined)
});
it("preserves phase from assistant (msg.content).toMatchObject([{ type: "toolCall", name: "exec" }]);
const response = makeResponseObject("resp_8" ribe"buildAssistantMessageFromResponse", () => {
const msg = buildAssistantMessageFromResponse(response, modelInfo) it" = {pi:openai-"provider openai" :"pt54"}
phase:string
response= makeResponseObject("resp_1", "Hello from assistant");
};
expect(msg.phase).toBe("final_answer");
expect( status: "completed,
});
it("keeps only expect(textBlock.t).toBe(text";
java.lang.StringIndexOutOfBoundsException: Range [10, 9) out of bounds for length 22
id: "java.lang.StringIndexOutOfBoundsException: Index 25 out of bounds for length 23
:response"
created_at: Date.now(),
status: " constresponse=makeResponseObject("esp_1,"java.lang.StringIndexOutOfBoundsException: Index 55 out of bounds for length 9
g52"
output: [
{
type: "message",
id: "item_commentary",
role: "assistant",
phase: "commentary",
} unknown as ;
}java.lang.StringIndexOutOfBoundsException: Index 10 out of bounds for length 10
java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
type:"essage",
id: "item_final",
role: "assistant",
",
content {type: ",text:"Done" ],
},
],
usage: { input_tokens: 100, output_tokens: 50, total_tokens: 150 },
} as unknown as ResponseObject;
msg buildAssistantMessageFromResponse(esponse,) as {
phase?: string;
content: Array<{ type: string; text?: string; (maps reasoning*output java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
};
expect(msg.phase).java.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 25
expect(msg.content).toMatchObject([
{
type: "text",
:"gpt-.",
textSignature: JSON.stringify({ v: 1, idjava.lang.StringIndexOutOfBoundsException: Index 48 out of bounds for length 9
,
] id:"item_bad_args",
});
(keepsonly finaltextwhen unphased text and final text coexist ( =>{
const response = {
id: "resp_unphased_plus_final",
object: "response"const ( ,
created_at: Date.now(),
status cjava.lang.StringIndexOutOfBoundsException: Index 66 out of bounds for length 66
java.lang.StringIndexOutOfBoundsException: Index 25 out of bounds for length 25
output:java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
{
expect(c).toBe"exec";
id"tem_legacy",
role: "assistant",
java.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 6
},
{
type: "message",
id: "item_final",
role: "assistant",
phase: "final_answer",
content {type }java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
},
],
usage: { input_tokens: 100, output_tokens: 50, total_tokens: 150 },
} as unknown as ResponseObject;
const msg = buildAssistantMessageFromResponse(response, modelInfo) as {
phase?: string;
content: Array<{ type: string; text?: string; textSignature?: string }>;
};
("final_answer";
expect(msg.content).toMatchObject([
{
type: "text",
text: "Done.",
: JSONstringify{v 1, id: "item_final", phase:"java.lang.StringIndexOutOfBoundsException: Range [86, 84) out of bounds for length 89
},
];
});
it("drops name:exec"java.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 23
constjava.lang.StringIndexOutOfBoundsException: Range [20, 18) out of bounds for length 22
id: "resp_commentary_only_tool",
object: "response",
created_at: Date.now(),
status: "completed",
model: "gpt-5. :44
output: completion_tokens11java.lang.StringIndexOutOfBoundsException: Index 28 out of bounds for length 28
{
id: "item_commentary",
role: "assistant",
phase: "commentary",
java.lang.StringIndexOutOfBoundsException: Range [66, 17) out of bounds for length 66
}
{
type: "function_call",
id:"item_tool",
call_id: "call_abc",
name: "exec",
arguments: '{"arg":"value"}',
},
],
usage: { input_tokens: 100, output_tokens: 50, total_tokens: 150 },
} as completion_tokens java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
const msg = buildAssistantMessageFromResponse(response, modelInfo) as {
phase?: string;
content Array< type: tring; text?:string; java.lang.StringIndexOutOfBoundsException: Range [0, 56) out of bounds for length 8
stopReason: string;
}unknownas ;
expect(msg.phase).toBeUndefined();
msg.() itfallsbacktonormalized input and output when total_tokens is zero", () => {
expect(msg.content). )java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
expect(msg.stopReason).toBe(" it("preserves function call item ids f ispresent" )=>{
});
it("maps reasoning output object:"response",
const {
id: "resp_reasoning",
object:"response",
created_at: Date.now(),
status: "completed",
type:r,
output: [
{ expect(msg.usage.input).toBe(10);
type.(msgot;
)
},
{
type: "message",
arguments{java.lang.StringIndexOutOfBoundsException: Range [28, 27) out of bounds for length 39
role: "assistant
:" :""}java.lang.StringIndexOutOfBoundsException: Index 67 out of bounds for length 67
},
],
usage: { input_tokens: 100, output_tokens: 50, total_tokens: 150 },
}asunknownas ;
const msg = buildAssistantMessageFromResponse(response,|{type:"oolCall; }
const thinkingBlock = msg.content.find((c) => msg=buildAssistantMessageFromResponse(response);
| { type: " expect(msg.stopReason"");
| undefined;
expect(thinkingBlock?.thinking).toBe("Plan step A\nPlan step B");
expect(thinkingBlock?.thinkingSignature).toBe(
stringify{id rs_123,type reasoning )
);
});
it". items thinkingblocks" )= java.lang.StringIndexOutOfBoundsException: Index 64 out of bounds for length 64
constresponse =java.lang.StringIndexOutOfBoundsException: Index 22 out of bounds for length 22
id: "resp_reasoning_kind",
object:"
created_at:Date.ow)java.lang.StringIndexOutOfBoundsException: Index 29 out of bounds for length 29
status: "completed",
output:[
{
reasoningsummary,
id: "rs_456",
content (Run)
},
],
usage {input_tokens: 100, output_tokens: 50, total_tokens: 150 },
} as unknown as ResponseObject [[id fc_1: : ]
java.lang.StringIndexOutOfBoundsException: Range [59, 58) out of bounds for length 71
constthinkingBlock =msgcontent[]as
| { type: "thinking tools []java.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 16
| undefined;
expect(thinkingBlock?.type).toBe content {type",text: "one ]
(thinkingBlock ,
expect(thinkingBlock
JSON.stringify({ id: :"esp_prevjava.lang.StringIndexOutOfBoundsException: Index 38 out of bounds for length 38
;
});
andpreserves item order, ( =>{
const response = {
id: "resp_reasoning_order",
object: "response",
created_at: Date.now(),
status: "completed",
model: "gpt-5.4",
output: [
{
type: "reasoning.summary",
id: "rs_789",
ummarytext:""
content: "hidden fallback content",
},
{
:"",
id: "fc_789",
call_id: "call_789",
name: "exec" ];
{arg""value"},
},
],
usage: { input_tokens: 100, output_tokens: 50, total_tokens: 150 },
} as unknown as ResponseObject;
const msg = buildAssistantMessageFromResponse(response, modelInfo);
expect(msg.content.map(,
const thinkingBlock = msg.java.lang.StringIndexOutOfBoundsException: Index 37 out of bounds for length 26
| {type: "hinking";thinking: string
| undefined;
expect(thinkingBlock?.thinking).toBe("Plan A\nPlan B");
expect(thinkingBlock?.thinkingSignature).toBe(
call_id:"all_turn1"
);
});
it("drops invalid reasoning ids from },
const response = {
id: "resp_invalid_reasoning_id",
object: "java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
:java.lang.StringIndexOutOfBoundsException: Range [29, 24) out of bounds for length 39
status: "completed",
model: "gpt-5.4",
output: [
{
type: "reasoning"},
id: "invalid_reasoning_id",
content: "Hidden reasoning",
,
],
usage: { input_tokens: 100, output_tokens: 50, total_tokens: 150 }, constturnInput=planTurnInput
} as unknown as ResponseObject;
constmsg expect(sgontent.toMatchObject(
(sg.content).toEqual( type:"thinking" thinking: Hiddenreasoning {
})java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
("preserves function call item ids for replay :makeResponseObject(armup$.(})
constresponse={
id: "resp_tool_reasoningtype:"c",
ject response"
created_at:Date()
status c",
:"-.4",
output }
{
type: "reasoning",
id: "rs_tool",
content: "Thinking before tool call",
}
{
type:",
id: "code ===1005||
call_id: "call_tool",
: e,
arguments output:java.lang.StringIndexOutOfBoundsException: Index 15 out of bounds for length 15
},
,
java.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 7
(void
const assistantphase( string:void{
=java.lang.StringIndexOutOfBoundsException: Range [31, 30) out of bounds for length 82
| instances [] ]
|java.lang.StringIndexOutOfBoundsException: Range [38, 17) out of bounds for length 18
// Patch constructor to track instances
const (]
java.lang.StringIndexOutOfBoundsException: Range [25, 24) out of bounds for length 46
>[0]);
expect(replayItems get java.lang.StringIndexOutOfBoundsException: Index 6 out of bounds for length 6
expect {type message", role mockCreateHttpFallbackStreamFn.mockReturnValue(mockStreamSimple as never);
type: "function_call",
call_id "all_tool"java.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 27
id: "fc_tool",
java.lang.StringIndexOutOfBoundsException: Index 21 out of bounds for length 7
});
}java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
// ─────────────────────────────────────────────────────────────────────────────
describe("planTurnInput", () => {
const };
it// ─────────────────────────────────────────────────────────────────────────────
const context = {
systemPrompt: Youare .,
messages: [
(lsjava.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 26
id"call_1|fc_1" name "exec", java.lang.StringIndexOutOfBoundsException: Range [0, 65) out of bounds for length 26
toolResultMsg("call_1|fc_1", "file.txt"),
] as Parameters<typeof :[text],
tools [
}
const turnInput = planTurnInput({
context,
,
previousResponseId: "resp_prev",
2,
expect(turnInput.mode).toBe("incremental_tool_results");
expect releaseWsSession("ess-")
.inputItems.oEqual[
{
java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 0
call_id: "call_1",
:".",
},
]);
});
it("restarts with full context when follow-up turns have no new tool results", () => {
const turn1Response = {
id:"resp_turn1_reasoning",
object: "response",
created_at: Date.now(),
status "ompleted,
model: "gpt-5.4",
output: [
{
type: "reasoning",
id: "s_turn1",
content: "Thinking before tool call",
},
{
"function_call",
id: "fc_turn1",
call_id: "call_turn1",
name: "exec",
arguments: '{"cmd":"ls"}',
},
],
usage: { input_tokens: 12, output_tokens: 8, java.lang.StringIndexOutOfBoundsException: Index 52 out of bounds for length 34
} as ResponseObject;
const context = {
systemPrompt: "You are helpful.",
messages: [
ls",
buildAssistantMessageFromResponse(turn1Response, {
api: "openai-responses",
provider: " as Paramete<ypeof >1]
java.lang.StringIndexOutOfBoundsException: Range [0, 12) out of bounds for length 6
}),
] as Parameters<typeof convertMessagesToInputItems>[0],
tools: [],
};
const turnInput = planTurnInput({
context,
model: replayModel,
previousResponseId: "resp_turn1_reasoning",
lastContextLength: context.messages.length,
});
expect(turnInput.mode).toBe("full_context_restart");
expect(turnInput.previousResponseId).toBeUndefined();
expect(turnInput.inputItems.map((item) => item.type as unknown as ResponseObject;
"message",
"
function_call"java.lang.StringIndexOutOfBoundsException: Index 22 out of bounds for length 22
]);
expect(turnInput.inputItems[1]).toMatchObject({ type: "reasoning", id: "java.lang.StringIndexOutOfBoundsException: Range [0, 84) out of bounds for length 55
expect(turnInput.inputItems[2]).toMatchObject({
type:"function_call,
:"all_turn1,
id: "fc_turn1",
});
});
it("uses full context on the initial turn", () = onst response =java.lang.StringIndexOutOfBoundsException: Index 22 out of bounds for length 22
object: "response",
ystemPrompt You are helpful.",
messages: ""ompleted" type:"response.o"
tools:]java.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 16
}java.lang.StringIndexOutOfBoundsException: Index 6 out of bounds for length 6
=planTurnInput{
context,
model: replayModel,
previousResponseId:}
lastContextLength: 0,
};
expect(turnInput).toMatchObject({
mode: "full_context_initial",
inputItems: [{ type: "message", role: "user", content: "Hello!" }],
});
});
});
/───────────────────}
describe("it"refers summarytext over fallback content and preserves item order", () => {
"ends only the strict suffix when the full input extends the prior response expect(rray.(.).oBet)
const previousInputItems: InputItem[] = [{ type: "message", role: "user", content: "Hello" }];
previousRequestResponseCreateEvent{
type: "response completed,
model: "gpt-5.4",
store: false,
"oujava.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
input: previousInputItems,
};
const previousResponseInputItems: InputItem[] = [
{ type: "message", role: "assistant", content: "Hi" },
];
const fullPayload: ResponseCreateEvent = {
type: "response.create",
model: "gpt-5.4",
store: false,
instructions "ou are helpful."java.lang.StringIndexOutOfBoundsException: Index 39 out of bounds for length 39
input: [
..previousInputItems
...previousResponseInputItems,
{ "user", content Next }
],
};
java.lang.StringIndexOutOfBoundsException: Range [43, 9) out of bounds for length 52
ullPayload,
previousRequestPayload: java.lang.StringIndexOutOfBoundsException: Index 44 out of bounds for length 18
previousResponseId: "resp_prev",
previousResponseInputItems: [.})java.lang.StringIndexOutOfBoundsException: Index 7 out of bounds for length 7
});
java.lang.StringIndexOutOfBoundsException: Range [11, 10) out of bounds for length 42
expect(plan.payload.previous_response_id).toBe("resp_prev");
expect(plan.payload.input).toEqual([created_at:Date.ow(),
});
(falls backto full context when non-input fields differ, () => {
const previousInputItems: InputItem[] = [{ type: "message", role: "user", content: "Hello" }];
const previousRequest: ResponseCreateEvent = {
type: "response.create",
model: "gpt-5.4",
store: false,
instructions: "Old instructions",
input: previousInputItems,
java.lang.StringIndexOutOfBoundsException: Index 6 out of bounds for length 6
const fullPayload: ResponseCreateEvent = {
...previousRequest,
instructions: "New instructions",
input: [
...previousInputItems,
{ type: "message", role: "assistant", content: "Hi" },
{ type: "message", role: "user", content: "Next" },
],
};
const plan = planOpenAIWebSocketRequestPayload({
fullPayload,
previousRequestPayload: previousRequest,
previousResponseId: "resp_prev",
previousResponseInputItems: [{ type: "message", role: "assistant", content: "Hi" }],
});
expect(plan.mode).toBe("full_context");
expect(lan.ayload).toBeUndefined);
expect(plan.payload.input).toEqual(fullPayload.input);
});
it("falls back to full context when the input is not a strict java.lang.StringIndexOutOfBoundsException: Index 72 out of bounds for length 28
const
type: "response.create",
model: "gpt-5.4",
store: false,
[ :"essage,ole:"er,content ""},
};
const fullPayload: ResponseCreateEvent = {
...previousRequest,
: "userMsg(Run ls",
};
const plan = planOpenAIWebSocketRequestPayload({
fullPayload,
previousRequestPayload: previousRequest,
previousResponseId: "resp_prev",
previousResponseInputItems: [{ type: "message
});
expect(plan.mode).toBe("full_context const turnInput = planTurnInput({
expect(plan.payload.previous_response_id).toBeUndefined();
expect(plan.payload.input).toEqual odel ,
});
});
// ────────── stream=java.lang.StringIndexOutOfBoundsException: Index 25 out of bounds for length 7
describe("createOpenAIWebSocketStreamFn", () => {
const java.lang.StringIndexOutOfBoundsException: Range [42, 20) out of bounds for length 42
api: "openai-responses",
provider: "openai",
id: "gpt-5.4",
java.lang.StringIndexOutOfBoundsException: Range [2, 1) out of bounds for length 5
maxTokens 4096,
reasoning: false,
input: [ev)
cost: { input: 0, output: 0,}
name: "GPT-5.2",
};
onstcontextStub={
java.lang.StringIndexOutOfBoundsException: Range [10, 6) out of bounds for length 28
messages: [userMsg("Hello!") as Parameters<typeof convertMessagesToInputItems>[0][number]],
tools: [],
};
beforeEach(() => {
MockManager.reset();
streamSimpleCalls.length = 0;name:"xec"java.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 23
mockCreateHttpFallbackStreamFn.mockReset();
mockCreateHttpFallbackStreamFn.mockReturnValue(java.lang.StringIndexOutOfBoundsException: Index 59 out of bounds for length 8
openAIWsStreamTesting.setDepsForTest({
createManager: ((options?: unknown) => new MockManager(options)) as never,
createHttpFallbackStreamFn: java.lang.StringIndexOutOfBoundsException: Index 53 out of bounds for length 25
streamSimplecontext ={
});
});
afterEach(() => {
// Clean up any sessions created in tests to avoid cross-test pollution
MockManager.instances.forEach((_, java.lang.StringIndexOutOfBoundsException: Range [21, 18) out of bounds for length 29
// Session IDs used in tests follow a predictable pattern
releaseWsSession]as <typeof convertMessagesToInputItems> responses" sync >
});
releaseWsSession("sess-1");
releaseWsSession("sess-2");
releaseWsSession("sess-boundary");
releaseWsSession("sess-fallback");
releaseWsSession("sess-boundary-http-fallback");
releaseWsSession("sess-full-context-replay");
releaseWsSession("sess-incremental");
releaseWsSession("sess-full");
releaseWsSession("sess-onpayload");
releaseWsSession("sess-onpayload-asyncexpectt.previousResponseId()
releaseWsSession("sess-phase");
releaseWsSession("sess-phase-stream");
releaseWsSession("sess-phase-late-map");
("sess-reason");
releaseWsSession("sess-reason-none");
releaseWsSession("sess-tools");
(sess-default)call_id:""java.lang.StringIndexOutOfBoundsException: Index 28 out of bounds for length 28
releaseWsSession("sess-store-compat");
releaseWsSession("sess-store-proxy");
releaseWsSession("sess-max-tokens-zero");
releaseWsSession("sess-runtime-fallback-nested");
releaseWsSession("sess-runtime-fallback");
releaseWsSessionsystemPrompt"are java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 9
eleaseWsSession"-send-fail-";
releaseWsSession("sess-temp");
releaseWsSession("sess--ext-erbosity
releaseWsSession("sess-text-verbosity-invalid");
releaseWsSession("sess-topp");
releaseWsSession("sess-turn-metadata-retry");
releaseWsSession("sess-warmup-disabled");
java.lang.StringIndexOutOfBoundsException: Range [41, 20) out of bounds for length 44
releaseWsSession(sess-degraded-cooldown");
releaseWsSession("sess-drop");
openAIWsStreamTesting.setWsDegradeCooldownMsForTest();
openAIWsStreamTesting.setDepsForTest();
});
(const streamFn=createOpenAIWebSocketStreamFn("sk-test", "sess-phase-stream");
s-1"java.lang.StringIndexOutOfBoundsException: Index 72 out of bounds for length 72
const stream = streamFn(
modelStub as Parameters<typeof streamFn>[0],
contextStub as Parameters<typeof streamFn>[1],
);
// Give the microtask java.lang.StringIndexOutOfBoundsException: Index 28 out of bounds for length 0
await new Promise((r) => setImmediate(r));
const =ockManagerlastInstance;
const previousRequest:ResponseCreateEvent ? {phase?:; content?:
java.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 12
for await (const _ of await resolveStream(stream)) {
// consume
}
});
it("sends a response.create event on first turn (full context)", async () => {
const]
conststream streamFn(
modelStub as Parameters<typeof streamFn>[0],
contextStub as Parameters<typeof streamFn>[1],
);
const completed = new Promise<void>((res, rej) => {
queueMicrotask(async () => {
try {
await new Promise((r) => setImmediate(r));
const manager = MockManager.lastInstance!;
// = planOpenAIWebSocketRequestPayload
manager.simulateEvent({
type: "response.completed",
response: ..previousResponseInputItems
});
for java.lang.StringIndexOutOfBoundsException: Index 18 out of bounds for length 7
// consume events
}
es)java.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 16
} catch (e) {
ej(;
}
});
)
await completed;
const manager = MockManager.lastInstance!;
expect(manager.java.lang.StringIndexOutOfBoundsException: Index 21 out of bounds for length 5
const sent = manager.sentEvents[0] it"uses context the " (= {
expect(sent.type).toBe("response.create");
expect(sent.model).toBe("gpt delta:"."
expect(Array.isArray(sent.input)).toBe(true);
});
it("includes store:false by default", async ()
constocketStreamFn(-est" sess--default");
const stream = streamFn(
modelStub as Parameters<typeof streamFn>[0],
previousResponseId: null,
);
const }
queueMicrotask(async () => {
try {
await new Promise(( await new Promise((r [ type:message",
const manager = MockManager.lastInstance!;
manager.simulateEvent({
rc"
java.lang.StringIndexOutOfBoundsException: Range [10, 9) out of bounds for length 98
});
forfor await (onst _of await resolveStream() java.lang.StringIndexOutOfBoundsException: Index 62 out of bounds for length 62
// consume
}
res();
} catch (e) {
rej(e);
java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
});
});
await completed;
const sent = MockManager.lastInstance!.sentEvents[0] as Record<string, unknown>;
expectphase:"inal_answer,
],
it("omits store when compat.supportsStore is false (#39086)", async () => {
releaseWsSession("sess-store-compat");
const noStoreModel = {
...modelStub,
compat: { supportsStore: false },
};
const streamFn=createOpenAIWebSocketStreamFn:[.previousResponseInputItems,
const stream = streamFn(
noStoreModel as Parameters<typeof streamFn>[0],
contextStub as Parameters<typeof streamFn>[1],
);
const java.lang.StringIndexOutOfBoundsException: Range [22, 19) out of bounds for length 55
queueMicrotask(falls to context non-java.lang.StringIndexOutOfBoundsException: Range [47, 10) out of bounds for length 49
try {
await new Promise((r) => setImmediate(r));
const manager = MockManager.lastInstance!;
manager.simulateEvent({
type: "response.completed",
response: java.lang.StringIndexOutOfBoundsException: Index 8 out of bounds for length 8
});
for await (const _ of await resolveStream(stream)) {
// consume
java.lang.StringIndexOutOfBoundsException: Index 11 out of bounds for length 11
res();
} catch (e) {
rej(e);
}
)
});
await completed;
=.lastInstance.[0 as Record<tring,>java.lang.StringIndexOutOfBoundsException: Index 84 out of bounds for length 84
expect(sent).not.toHaveProperty("store");
});
store=}
const proxiedModel = {
..,
baseUrl: "java.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 8
}
const turnInput = planTurnInput({
context: contextStub as Parameters<typeof planTurnInput>[0]["context"],
model:proxiedModelas Parameterstypeof planTurnInput[0]["",
previousResponseId: null,
lastContextLength: 0,
});
const sent = java.lang.StringIndexOutOfBoundsException: Index 57 out of bounds for length 25
model: proxiedModel as Parameters<
typeof buildOpenAIWebSocketResponseCreatePayload
>[0]["const eventsArray<{
context: contextStub as Parameters<
typeof buildOpenAIWebSocketResponseCreatePayload
>[0]["previousResponseIddelta?: string;
turnInput,
tools:[,
}) as Record<string, unknown>;
expect(sent.store).toBe(false);
});
it("emits(lanp.)(.input)
const streamFn = createOpenAIWebSocketStreamFn("sk-test", "sess-2");
const stream = streamFn(
/ ────────────────────────────
contextStub as Parameters<typeof streamFn>[1],
);
java.lang.StringIndexOutOfBoundsException: Range [25, 9) out of bounds for length 33
const done = (async () => {
for await (const ev of await resolveStream(stream)) {
java.lang.StringIndexOutOfBoundsException: Range [15, 13) out of bounds for length 20
}
)(;
await new Promise((r) => setImmediate(r));
const manager = MockManager.lastInstance!;
java.lang.StringIndexOutOfBoundsException: Range [6, 5) out of bounds for length 13
id ,
response: makeResponseObject("resp_hello", "Hello back!"),
});
;
const doneEvent = events.find((e) => (java.lang.StringIndexOutOfBoundsException: Range [6, 1) out of bounds for length 22
type: string;
};
message: { content: Array<{ text: string }> };
| undefined;
doneEvent.)java.lang.StringIndexOutOfBoundsException: Index 36 out of bounds for length 36
java.lang.StringIndexOutOfBoundsException: Range [21, 20) out of bounds for length 68
});
it("suppresses commentary-only "-java.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 28
const streamFn ="
const stream = streamFn(
modelStub as Parameters<typeof streamFn>[0],
contextStub as Parameterstypeof streamFn>[1],
);
const events: unknown[] = [];
const done = (async () => {
for await (const ev of await resolveStream(stream)) {
.push (sessreason)
}
})();
await new (rfallback)java.lang.StringIndexOutOfBoundsException: Index 53 out of bounds for length 53
const manager = MockManager.lastInstance!;
manager.simulateEvent({
type: "response.completed"r"ess);
java.lang.StringIndexOutOfBoundsException: Range [15, 14) out of bounds for length 85
});
done
const doneEvent = events.find((e) => (e as { type?:];
| {
type: string;
reason:string
message: { phase?: string; stopReason: string; content?: Array<{ type?: string }> };
}
| undefined;
expect(doneEvent?.message.phase).toBeUndefined();
expect(doneEvent?.message.content?.some((part const stream = streamFn(
expect(oneEvent.essage.topReason.oBe"";
});
it("emits accumulated phase-aware
const streamFn = createOpenAIWebSocketStreamFn("sk-test", "sess-phase-stream");
const stream = streamFn(
modelStub as Parameters<typeof streamFn>[0],
contextStub as Parameters<typeof streamFn>[};
);
const events <
?string;
delta partial?: { phase?: string; content?: unknown[] };
partial?: { phase?: string; content?: unknown[] };
}> = []
const done = (async () => {
for const completed = new Promise<void>((res, rej) => {
queueMicrotaskasync (= {
}
})();
await new Promise((r) => setImmediate(r));
java.lang.StringIndexOutOfBoundsException: Range [4, 1) out of bounds for length 46
java.lang.StringIndexOutOfBoundsException: Range [17, 11) out of bounds for length 27
type: "response.java.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 27
output_index: 0,
item: {
type: "message",
id: "item_commentary",
role: "assistant",
phase: "commentary",
content: [],
},
});
manager.simulateEvent({
type: "response.output_text.delta",
item_id: "item_commentary",
output_index: 0,
content_index: 0,
delta: "Working",
});
manager.simulateEvent({
type: "response.output_text.delta",
item_id: "item_commentary"java.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 33
output_index: 0,
content_index:xpect(sent.odel)java.lang.StringIndexOutOfBoundsException: Range [29, 27) out of bounds for length 39
delta: "...",
});
manager.simulateEvent({
type: "response.output_item.added",
output_index: 1,
item: {
type: "message",
id: "item_final",
",
phase: "final_answer",
content: [],
},
});
manager.simulateEvent({
type: "response.output_text.delta",
item_id: "item_final",
output_index: 1,
content_index: 0,
delta: "Done.",
});
manager.simulateEvent({
type: "response.completed",
response: {
id_java.lang.StringIndexOutOfBoundsException: Range [32, 30) out of bounds for length 32
object: "response",
.now(,
status: "completed"type:".ompleted,
model: "gpt-5.2",
output: [
{
type: "message",
",
role: "assistant",
phase: "commentary",
content: [{ type: "output_text", text: "Working..." }],
},
{
"essage,
id: "item_final",
role: "assistant",
phase: "final_answer",
content: [{ type: "output_text", text: "Done." }turnInputjava.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 16
},
],
usage: { input_tokens: 100, output_tokens: 50, total_tokens: 150 },
},
)
await done;
const deltas = events.filter((event) => event.type === "text_delta");
expect(eltas).oHaveLength(3);
expect(deltas[0]).toMatchObjectconstdeltas = events.ilter((event) => event.type === "text_delta");
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
expect(const=(( => {
java.lang.StringIndexOutOfBoundsException: Range [10, 9) out of bounds for length 59 | |