fix(diagnostics): complete early model stream closes

This commit is contained in:
Vincent Koc
2026-04-25 18:36:46 -07:00
parent c7b336d83e
commit e40157013f
3 changed files with 11 additions and 5 deletions

View File

@@ -72,6 +72,9 @@ Docs: https://docs.openclaw.ai
### Fixes
- Diagnostics/OTEL: treat normal early model stream cleanup as a completed
model call instead of exporting a misleading `StreamAbandoned` error span.
Thanks @vincentkoc.
- ACP: wait for the configured runtime backend to become healthy before startup
identity reconciliation, avoiding transient acpx warnings during Gateway boot.
Fixes #40566.

View File

@@ -253,7 +253,7 @@ describe("wrapStreamFnWithDiagnosticModelCallEvents", () => {
expect(JSON.stringify([started.mock.calls, ended.mock.calls])).not.toContain(secretChunk);
});
it("emits error events when stream consumption stops early", async () => {
it("emits completed events when stream consumption stops early", async () => {
async function* stream() {
yield { type: "text", text: "first" };
yield { type: "text", text: "second" };
@@ -279,12 +279,15 @@ describe("wrapStreamFnWithDiagnosticModelCallEvents", () => {
}
});
expect(events.map((event) => event.type)).toEqual(["model.call.started", "model.call.error"]);
expect(events.map((event) => event.type)).toEqual([
"model.call.started",
"model.call.completed",
]);
expect(events[1]).toMatchObject({
type: "model.call.error",
type: "model.call.completed",
callId: "call-abandoned",
errorCategory: "StreamAbandoned",
durationMs: expect.any(Number),
});
expect(events[1]).not.toHaveProperty("errorCategory");
});
});

View File

@@ -252,7 +252,7 @@ async function* observeModelCallIterator<T>(
} finally {
if (!terminalEmitted) {
await safeReturnIterator(iterator);
emitModelCallError(eventBase, startedAt, { errorCategory: "StreamAbandoned" });
emitModelCallCompleted(eventBase, startedAt);
}
}
}