You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Fix AI chat Responses API tool-chaining and context limit handling
- Fix streaming tool continuations: track currentLegResponseId from
StreamingResponseCreatedUpdate and clone options with that ID before
calling ExecuteFunctionCallAsync, so the continuation correctly
references the response that produced the function call (not the
outer conversation root).
- Fix non-streaming loop token waste: after each tool-call response,
advance PreviousResponseId to the new responseId and reset
responseItems to [] so subsequent iterations only send new tool
outputs — not the growing full history. This prevents quadratic
token re-processing.
- Remove redundant functionCallItem from continuation inputs: when
using previous_response_id chaining, the function call is already
stored server-side in the referenced response; only the
FunctionCallOutputResponseItem is new content.
- Add ConversationContextLimitExceededException domain exception and
IsContextLengthError helper to detect context window overflow from
ClientResultException (HTTP 400 with context_length_exceeded text).
- Handle context limit in ChatController: both /api/chat/message and
/api/chat/stream return 400 with errorCode 'context_limit_exceeded'.
- Add CloneOptionsWithPreviousResponseId helper to avoid mutating
shared options across concurrent streaming legs.
- Add ParseToolArguments helper to deduplicate JSON argument parsing
in both streaming and non-streaming paths.
- Fix OPENAI001 pragma: extend the disable region to cover the full
loop body including the ClientResult<OpenAIResponse> declaration.
#pragma warning disable OPENAI001// Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
189
194
if(updateisStreamingResponseCreatedUpdatecreated)
190
195
{
191
196
// Emit the response ID early so the controller can record ownership
192
197
// before the stream completes — handles client disconnects mid-stream.
// Feed a benign error back to the model so it can recover gracefully,
243
-
// mirroring what GetChatCompletionCore does on the non-streaming path.
251
+
// Feed a benign error back to the model so it can recover gracefully.
252
+
// The functionCallItem is in the stored response at PreviousResponseId — only send the output.
244
253
#pragma warning disable OPENAI001// Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
245
254
varerrorItems=newList<ResponseItem>
246
255
{
247
-
functionCallItem,
248
256
newFunctionCallOutputResponseItem(
249
257
functionCallItem.CallId,
250
258
$"Tool '{functionCallItem.FunctionName}' is not available.")
// Create input items with both the function call and the result
299
-
// This matches the Python pattern: append both tool_call and result
281
+
// The functionCallItem is already stored in the server's context (referenced by
282
+
// responseOptions.PreviousResponseId). Only the tool output is new content.
300
283
#pragma warning disable OPENAI001// Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
#pragma warning restore OPENAI001// Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
#pragma warning disable OPENAI001// Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
#pragma warning restore OPENAI001// Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
/// Used when chaining tool-call continuations from a specific response leg.
486
+
/// </summary>
487
+
#pragma warning disable OPENAI001// Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
#pragma warning restore OPENAI001// Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
503
+
504
+
/// <summary>
505
+
/// Parses function call arguments from a <see cref="BinaryData"/> JSON payload into a
awaitResponse.WriteAsJsonAsync(new{error="This conversation has grown too long. Please start a new one.",errorCode="context_limit_exceeded"},CancellationToken.None);
awaitResponse.WriteAsync("data: {\"type\":\"error\",\"message\":\"This conversation has grown too long. Please start a new one.\",\"errorCode\":\"context_limit_exceeded\"}\n\n",CancellationToken.None);
0 commit comments