Skip to content

Commit c9caa78

Browse files
committed
fix(ws-stream): clarify previous_response_id reporting and fix lint
The full_context branch strips previous_response_id from the wire payload but the debug record was reporting it under the same field as the incremental (chained) case, so on-call could not tell whether the chain landed or was dropped intentionally. Split the field: previousResponseId is set only when the chain went on the wire, and a new requestedPreviousResponseIdStripped surfaces 'requested but stripped' unambiguously. The completion-lineage log mirrors the split with chainedPreviousResponseId vs requestedPreviousResponseIdStripped. Replaces [...messages].reverse().find(...) in summarizeWsContextLineage with messages.findLast(...) (one allocation, ES2023, satisfies unicorn/no-array-reverse). Updates the existing full_context planner test to lock in the contract that the debug record cannot advertise a chain when the wire payload does not carry one.
1 parent 3a97ff5 commit c9caa78

3 files changed

Lines changed: 39 additions & 6 deletions

File tree

src/agents/openai-ws-request.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,10 @@ export type WsInputItemDebugSummary = {
5454

5555
export type PlannedWsRequestDebug = {
5656
mode: "full_context" | "incremental";
57+
/** Set only when the wire payload actually carries previous_response_id (incremental mode). */
5758
previousResponseId?: string;
59+
/** Set when previous_response_id was requested but stripped before send (full_context mode). */
60+
requestedPreviousResponseIdStripped?: string;
5861
baselineLength: number;
5962
fullInputLength: number;
6063
suffixLength: number;
@@ -154,9 +157,19 @@ function buildRequestDebug(params: {
154157
fullInputItems: InputItem[];
155158
suffixItems: InputItem[];
156159
}): PlannedWsRequestDebug {
160+
// In full_context mode the planner strips previous_response_id from the wire
161+
// payload, so the debug record must not advertise a chain that did not go on
162+
// the wire. The "requested but stripped" id is reported under a distinct
163+
// field so on-call can tell "chain landed" from "chain dropped intentionally".
164+
const previousResponseIdField =
165+
params.mode === "incremental" && params.previousResponseId
166+
? { previousResponseId: params.previousResponseId }
167+
: params.mode === "full_context" && params.previousResponseId
168+
? { requestedPreviousResponseIdStripped: params.previousResponseId }
169+
: {};
157170
return {
158171
mode: params.mode,
159-
...(params.previousResponseId ? { previousResponseId: params.previousResponseId } : {}),
172+
...previousResponseIdField,
160173
baselineLength: params.baselineLength,
161174
fullInputLength: params.fullInputItems.length,
162175
suffixLength: params.suffixItems.length,

src/agents/openai-ws-stream.test.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1863,9 +1863,13 @@ describe("planOpenAIWebSocketRequestPayload", () => {
18631863
expect(plan.mode).toBe("full_context");
18641864
expect(plan.payload.previous_response_id).toBeUndefined();
18651865
expect(plan.payload.input).toEqual(fullPayload.input);
1866+
// The wire payload strips previous_response_id in full_context mode, so
1867+
// the debug record must not advertise a chain that did not go on the wire.
1868+
// The "requested but stripped" id is reported under a distinct field.
1869+
expect(plan.debug.previousResponseId).toBeUndefined();
18661870
expect(plan.debug).toMatchObject({
18671871
mode: "full_context",
1868-
previousResponseId: "resp_prev",
1872+
requestedPreviousResponseIdStripped: "resp_prev",
18691873
baselineLength: 2,
18701874
fullInputLength: 3,
18711875
suffixLength: 3,

src/agents/openai-ws-stream.ts

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ function summarizeWsContextLineage(messages: ReadonlyArray<unknown>): WsContextL
9292
const tail = messages.at(-1);
9393
const tailRecord =
9494
tail && typeof tail === "object" ? (tail as Record<string, unknown>) : undefined;
95-
const latestUser = [...messages].reverse().find((message) => {
95+
const latestUser = messages.findLast((message) => {
9696
if (!message || typeof message !== "object") {
9797
return false;
9898
}
@@ -135,7 +135,10 @@ function logWsCompletionLineage(params: {
135135
sessionId: string;
136136
requestId: string;
137137
requestMode: PlannedWsRequestDebug["mode"];
138-
requestedPreviousResponseId?: string;
138+
/** Set only when previous_response_id actually went on the wire (incremental). */
139+
chainedPreviousResponseId?: string;
140+
/** Set when previous_response_id was requested but stripped before send (full_context). */
141+
requestedPreviousResponseIdStripped?: string;
139142
acceptedResponseId: string;
140143
managerPreviousResponseId?: string | null;
141144
acceptedInputItemCount: number;
@@ -145,7 +148,12 @@ function logWsCompletionLineage(params: {
145148
`[ws-stream] session=${params.sessionId} request=${params.requestId}: accepted response lineage ${JSON.stringify(
146149
{
147150
requestMode: params.requestMode,
148-
requestedPreviousResponseId: params.requestedPreviousResponseId,
151+
...(params.chainedPreviousResponseId
152+
? { chainedPreviousResponseId: params.chainedPreviousResponseId }
153+
: {}),
154+
...(params.requestedPreviousResponseIdStripped
155+
? { requestedPreviousResponseIdStripped: params.requestedPreviousResponseIdStripped }
156+
: {}),
149157
acceptedResponseId: params.acceptedResponseId,
150158
managerPreviousResponseId: params.managerPreviousResponseId ?? undefined,
151159
acceptedInputItemCount: params.acceptedInputItemCount,
@@ -1287,7 +1295,15 @@ export function createOpenAIWebSocketStreamFn(
12871295
sessionId,
12881296
requestId: requestLineageId,
12891297
requestMode: plannedPayload.debug.mode,
1290-
requestedPreviousResponseId: plannedPayload.debug.previousResponseId,
1298+
...(plannedPayload.debug.previousResponseId
1299+
? { chainedPreviousResponseId: plannedPayload.debug.previousResponseId }
1300+
: {}),
1301+
...(plannedPayload.debug.requestedPreviousResponseIdStripped
1302+
? {
1303+
requestedPreviousResponseIdStripped:
1304+
plannedPayload.debug.requestedPreviousResponseIdStripped,
1305+
}
1306+
: {}),
12911307
acceptedResponseId: event.response.id,
12921308
managerPreviousResponseId: session.manager.previousResponseId,
12931309
acceptedInputItemCount: session.lastResponseInputItems.length,

0 commit comments

Comments
 (0)