






















@@ -140,6 +140,103 @@ describe("openai transport stream", () => {
140140).rejects.toThrow(/did not deliver a first event within 1ms after HTTP streaming headers/);
141141});
142142143+it("observes detail-less Responses failures without leaking request ids", async () => {
144+const model = createAzureResponsesModel();
145+const event = {
146+type: "response.failed",
147+response: {
148+id: "resp_failed_123",
149+status: "failed",
150+model: "gpt-5.4-pro",
151+metadata: {
152+litellm_request_id: "litellm_req_plaintext_123",
153+api_key: "sk-observation-secret",
154+},
155+provider_request_id: "provider_req_plaintext_456",
156+status_details: {
157+provider_request_id: "provider_req_nested_789",
158+},
159+provider_error: {
160+request_id: "provider_error_req_nested_012",
161+headers: {
162+"x-request-id": ["header_req_plaintext_345", "header_req_plaintext_678"],
163+},
164+},
165+},
166+};
167+168+const observation = __testing.buildResponsesFailedNoDetailsObservation(event, model);
169+const summary = __testing.summarizeResponsesFailedNoDetailsObservation(observation);
170+171+expect(observation.providerRuntimeFailureKind).toBe("no_error_details");
172+expect(observation.responseId).toBe("resp_failed_123");
173+expect(observation.responseStatus).toBe("failed");
174+expect(observation.responseModel).toBe("gpt-5.4-pro");
175+expect(observation.requestIdHashes).toHaveLength(6);
176+expect(observation.requestIdHashes.join(",")).toContain("sha256:");
177+expect(summary).toContain("responseId=resp_failed_123");
178+expect(summary).toContain("requestIds=");
179+expect(JSON.stringify(observation)).not.toContain("litellm_req_plaintext_123");
180+expect(JSON.stringify(observation)).not.toContain("provider_req_plaintext_456");
181+expect(JSON.stringify(observation)).not.toContain("provider_req_nested_789");
182+expect(JSON.stringify(observation)).not.toContain("provider_error_req_nested_012");
183+expect(JSON.stringify(observation)).not.toContain("header_req_plaintext_345");
184+expect(JSON.stringify(observation)).not.toContain("header_req_plaintext_678");
185+expect(JSON.stringify(observation)).not.toContain("sk-observation-secret");
186+});
187+188+it("preserves the failed response id before throwing detail-less Responses failures", async () => {
189+const model = createAzureResponsesModel();
190+const output = createResponsesAssistantOutput(model);
191+192+await expect(
193+__testing.processResponsesStream(
194+streamChunks([
195+{
196+type: "response.failed",
197+response: {
198+id: "resp_failed_runtime",
199+status: "failed",
200+model: "gpt-5.4-pro",
201+},
202+},
203+]),
204+output,
205+{ push: vi.fn() },
206+model,
207+),
208+).rejects.toThrow("Unknown error (no error details in response)");
209+210+expect(output.responseId).toBe("resp_failed_runtime");
211+});
212+213+it("treats empty Responses error objects as detail-less failures", async () => {
214+const model = createAzureResponsesModel();
215+const output = createResponsesAssistantOutput(model);
216+217+await expect(
218+__testing.processResponsesStream(
219+streamChunks([
220+{
221+type: "response.failed",
222+response: {
223+id: "resp_failed_empty_error",
224+status: "failed",
225+model: "gpt-5.4-pro",
226+error: { code: null, message: null },
227+provider_request_id: "provider_req_empty_error",
228+},
229+},
230+]),
231+output,
232+{ push: vi.fn() },
233+model,
234+),
235+).rejects.toThrow("Unknown error (no error details in response)");
236+237+expect(output.responseId).toBe("resp_failed_empty_error");
238+});
239+143240it("clamps Responses cached prompt usage at zero", async () => {
144241const model = createAzureResponsesModel();
145242const output = createResponsesAssistantOutput(model);
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。