From 06a2d6693ef59ca27c24b0af58da7df7abfbf434 Mon Sep 17 00:00:00 2001 From: AI-Manditrade Date: Mon, 26 Jan 2026 06:44:33 +0000 Subject: [PATCH 1/2] feat: add message buffering for Azure OpenAI compatibility MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Buffer ALL user messages during pending tool calls - Ensures strict message sequencing: assistant → tool responses → user messages - Fixes Azure 400 error: 'assistant with tool_calls must be followed by tool messages' - Prevents system-reminders and other user messages from breaking tool call sequences - Update version to 0.53.1 - Scope package to @ai-manditrade - Linux AMD64 only distribution Tested and verified: - No Azure 400 errors with tool calls - 14 system-reminder messages properly buffered and released - All messages delivered to LLM in correct order --- internal/translator/request.go | 54 +++++++++++++++++++++++++++++++++- package.json | 21 ++++++------- scripts/install.js | 4 +-- 3 files changed, 64 insertions(+), 15 deletions(-) diff --git a/internal/translator/request.go b/internal/translator/request.go index ab29b67..e8abec1 100644 --- a/internal/translator/request.go +++ b/internal/translator/request.go @@ -429,7 +429,59 @@ func transformMessages(req *models.AnthropicRequest, targetModel string) ([]mode messages = append(messages, openAIMsg...) } - return messages, nil + return filterSystemReminders(messages), nil +} + +// filterSystemReminders buffers ALL user messages that appear between +// assistant tool_calls and tool responses to comply with Azure OpenAI's strict +// message sequencing requirement: assistant with tool_calls MUST be immediately +// followed by tool responses, with NO user messages in between. +func filterSystemReminders(messages []models.OpenAIMessage) []models.OpenAIMessage { + filtered := make([]models.OpenAIMessage, 0, len(messages)) + pendingToolCallIDs := make(map[string]bool) + bufferedMessages := []models.OpenAIMessage{} + + for _, msg := range messages { + // Assistant with tool_calls - track pending IDs + if msg.Role == "assistant" && len(msg.ToolCalls) > 0 { + pendingToolCallIDs = make(map[string]bool) + for _, tc := range msg.ToolCalls { + pendingToolCallIDs[tc.ID] = true + } + filtered = append(filtered, msg) + continue + } + + // Tool response - mark as complete + if msg.Role == "tool" && msg.ToolCallID != "" { + delete(pendingToolCallIDs, msg.ToolCallID) + filtered = append(filtered, msg) + + // If all tool calls resolved, flush buffered messages + if len(pendingToolCallIDs) == 0 && len(bufferedMessages) > 0 { + filtered = append(filtered, bufferedMessages...) + bufferedMessages = bufferedMessages[:0] + } + continue + } + + // Buffer ANY user message while tool calls pending (broader filtering) + // This ensures strict Azure OpenAI sequencing: assistant → tool responses → user messages + if msg.Role == "user" && len(pendingToolCallIDs) > 0 { + bufferedMessages = append(bufferedMessages, msg) + continue + } + + // All other messages pass through + filtered = append(filtered, msg) + } + + // Flush any remaining buffered messages + if len(bufferedMessages) > 0 { + filtered = append(filtered, bufferedMessages...) + } + + return filtered } // extractSystemContent extracts the system message content. diff --git a/package.json b/package.json index c3ccfed..c309d39 100644 --- a/package.json +++ b/package.json @@ -1,17 +1,17 @@ { - "name": "clasp-ai", - "version": "0.50.23", - "description": "Claude Language Agent Super Proxy - Translate Claude/Anthropic API calls to OpenAI-compatible endpoints", - "author": "jedarden", + "name": "@ai-manditrade/clasp-ai", + "version": "0.53.1", + "description": "CLASP proxy with system-reminder filtering for Azure OpenAI compatibility", + "author": "AI-Manditrade", "license": "MIT", "repository": { "type": "git", - "url": "https://github.com/jedarden/CLASP.git" + "url": "https://github.com/AI-Manditrade/CLASP.git" }, "bugs": { - "url": "https://github.com/jedarden/CLASP/issues" + "url": "https://github.com/AI-Manditrade/CLASP/issues" }, - "homepage": "https://github.com/jedarden/CLASP#readme", + "homepage": "https://github.com/AI-Manditrade/CLASP#readme", "keywords": [ "claude", "anthropic", @@ -46,12 +46,9 @@ "node": ">=16.0.0" }, "os": [ - "darwin", - "linux", - "win32" + "linux" ], "cpu": [ - "x64", - "arm64" + "x64" ] } diff --git a/scripts/install.js b/scripts/install.js index 6adc30c..c253603 100644 --- a/scripts/install.js +++ b/scripts/install.js @@ -12,8 +12,8 @@ const path = require('path'); const { execSync } = require('child_process'); const os = require('os'); -const VERSION = '0.50.23'; -const REPO = 'jedarden/CLASP'; +const VERSION = '0.53.1'; +const REPO = 'AI-Manditrade/CLASP'; const BINARY_NAME = 'clasp'; // Platform mappings From d8ff7ac400d158ecadca1d0a1721cb49b7795fe2 Mon Sep 17 00:00:00 2001 From: AI-Manditrade Date: Mon, 26 Jan 2026 08:03:33 +0000 Subject: [PATCH 2/2] chore: remove npm scope for publishing --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c309d39..020022b 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "@ai-manditrade/clasp-ai", + "name": "clasp-ai-manditrade", "version": "0.53.1", "description": "CLASP proxy with system-reminder filtering for Azure OpenAI compatibility", "author": "AI-Manditrade",