From acdbb2fbaf4fe3f16fd29bd11afb533ccfd2834a Mon Sep 17 00:00:00 2001 From: Enrico Ros Date: Sun, 3 May 2026 22:32:40 -0700 Subject: [PATCH] AIX: ContentReassembler: verbose post termination issues --- src/modules/aix/client/ContentReassembler.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/modules/aix/client/ContentReassembler.ts b/src/modules/aix/client/ContentReassembler.ts index 9293ea77a..af1ddfbb6 100644 --- a/src/modules/aix/client/ContentReassembler.ts +++ b/src/modules/aix/client/ContentReassembler.ts @@ -907,6 +907,12 @@ export class ContentReassembler { * Stores raw termination data from the wire - classification deferred to finalizeReassembly() */ private onCGEnd({ terminationReason, tokenStopReason, tokenStopError }: Extract): void { + // Diagnostic: detect late 'end' particles overriding a prior termination (parser bug, replayed wire, or upstream advisory after a clean end). + // Behavior unchanged - we still apply the override - but the warning makes the override visible client-side, mirroring the server-side + // 'setDialectEnded ... (overriding)' warning in ChatGenerateTransmitter and the existing setClientAborted/setClientExcepted warnings here. + if (this.S.terminationReason) + console.warn(`[DEV] [ContentReassembler] onCGEnd: overriding prior termination '${this.S.terminationReason}' with '${terminationReason}' (wire stop: ${this.S.dialectStopReason ?? 'none'} -> ${tokenStopReason ?? 'none'})`); + this.S.terminationReason = terminationReason; this.S.dialectStopReason = tokenStopReason; // Vendor-composed stop error, surfaced as a complementary error fragment alongside the generic classification message @@ -993,6 +999,11 @@ export class ContentReassembler { } private onCGIssue({ issueId: _issueId /* Redundant as we add an Error Fragment already */, issueText, issueHint }: Extract & { issueHint?: DMessageErrorPart['hint'] }): void { + // Diagnostic: detect issue particles arriving after a clean termination (e.g. OpenAI rate-limit advisory after response.completed). + // Behavior unchanged - the issue is still appended - but the warning surfaces that we are mutating a finished message. + if (this.S.terminationReason && this.S.terminationReason === 'done-dialect') + console.warn(`[DEV] [ContentReassembler] onCGIssue: appending issue after clean '${this.S.terminationReason}' (wire stop: ${this.S.dialectStopReason ?? 'none'}): ${issueText}`); + // NOTE: not sure I like the flow at all here // there seem to be some bad conditions when issues are raised while the active part is not text if (MERGE_ISSUES_INTO_TEXT_PART_IF_OPEN) {