From 41f12e874d443cf2ee021414f73e42df9d928458 Mon Sep 17 00:00:00 2001 From: wucm667 Date: Fri, 24 Jul 2026 16:25:53 +0800 Subject: [PATCH 1/2] fix(grok): drop orphaned Responses tool choice --- .../internal/service/openai_gateway_grok.go | 8 ++- .../service/openai_gateway_grok_test.go | 54 +++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/backend/internal/service/openai_gateway_grok.go b/backend/internal/service/openai_gateway_grok.go index d887ff73f..efd4a328e 100644 --- a/backend/internal/service/openai_gateway_grok.go +++ b/backend/internal/service/openai_gateway_grok.go @@ -663,7 +663,13 @@ var grokResponsesSupportedToolTypes = map[string]struct{}{ func sanitizeGrokResponsesTools(body []byte) ([]byte, error) { tools := gjson.GetBytes(body, "tools") - if !tools.Exists() || !tools.IsArray() { + if !tools.Exists() { + if gjson.GetBytes(body, "tool_choice").Exists() { + return sjson.DeleteBytes(body, "tool_choice") + } + return body, nil + } + if !tools.IsArray() { return body, nil } diff --git a/backend/internal/service/openai_gateway_grok_test.go b/backend/internal/service/openai_gateway_grok_test.go index 3a8e34733..ce6424d28 100644 --- a/backend/internal/service/openai_gateway_grok_test.go +++ b/backend/internal/service/openai_gateway_grok_test.go @@ -209,6 +209,60 @@ func TestPatchGrokResponsesBodyDropsToolChoiceWhenNoSupportedToolsRemain(t *test require.False(t, gjson.GetBytes(patched, "tool_choice").Exists()) } +func TestSanitizeGrokResponsesToolsKeepsToolChoiceOnlyWithSupportedTools(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + body string + wantTools bool + wantToolChoice bool + }{ + { + name: "missing tools with string tool choice", + body: `{"input":"hello","tool_choice":"auto"}`, + }, + { + name: "missing tools with object tool choice", + body: `{"input":"hello","tool_choice":{"type":"function","name":"lookup"}}`, + }, + { + name: "empty tools", + body: `{"input":"hello","tools":[],"tool_choice":"auto"}`, + wantTools: true, + }, + { + name: "all tools unsupported", + body: `{"input":"hello","tools":[{"type":"namespace","name":"client_tools"}],"tool_choice":"auto"}`, + }, + { + name: "supported tool", + body: `{"input":"hello","tools":[{"type":"function","name":"lookup"}],"tool_choice":"auto"}`, + wantTools: true, + wantToolChoice: true, + }, + { + name: "malformed non-array tools remain untouched", + body: `{"input":"hello","tools":{"type":"function","name":"lookup"},"tool_choice":"auto"}`, + wantTools: true, + wantToolChoice: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + patched, err := sanitizeGrokResponsesTools([]byte(tt.body)) + require.NoError(t, err) + require.True(t, json.Valid(patched)) + require.Equal(t, tt.wantTools, gjson.GetBytes(patched, "tools").Exists()) + require.Equal(t, tt.wantToolChoice, gjson.GetBytes(patched, "tool_choice").Exists()) + if tt.wantToolChoice { + require.Equal(t, "auto", gjson.GetBytes(patched, "tool_choice").String()) + } + }) + } +} + func TestPatchGrokResponsesBodyPromotesCodexAdditionalTools(t *testing.T) { t.Parallel() From 41456b69dd9e905b3e97a136d4219d62a9be60d5 Mon Sep 17 00:00:00 2001 From: wucm667 Date: Fri, 24 Jul 2026 08:33:58 +0800 Subject: [PATCH 2/2] fix(frontend): upgrade postcss for security audit --- frontend/package.json | 2 +- frontend/pnpm-lock.yaml | 46 ++++++++++++++++++++--------------------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/frontend/package.json b/frontend/package.json index b3c3450a3..c92599031 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -51,7 +51,7 @@ "eslint": "^8.57.0", "eslint-plugin-vue": "^9.25.0", "jsdom": "^24.1.3", - "postcss": "^8.4.32", + "postcss": "^8.5.12", "tailwindcss": "^3.4.0", "typescript": "~5.6.0", "vite": "^5.0.10", diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml index 4bc3d2fee..b98ec68f3 100644 --- a/frontend/pnpm-lock.yaml +++ b/frontend/pnpm-lock.yaml @@ -105,7 +105,7 @@ importers: version: 2.4.6 autoprefixer: specifier: ^10.4.16 - version: 10.4.23(postcss@8.5.6) + version: 10.4.23(postcss@8.5.12) eslint: specifier: ^8.57.0 version: 8.57.1 @@ -116,8 +116,8 @@ importers: specifier: ^24.1.3 version: 24.1.3 postcss: - specifier: ^8.4.32 - version: 8.5.6 + specifier: ^8.5.12 + version: 8.5.12 tailwindcss: specifier: ^3.4.0 version: 3.4.19 @@ -3550,8 +3550,8 @@ packages: postcss-value-parser@4.2.0: resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - postcss@8.5.6: - resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} + postcss@8.5.12: + resolution: {integrity: sha512-W62t/Se6rA0Az3DfCL0AqJwXuKwBeYg6nOaIgzP+xZ7N5BFCI7DYi1qs6ygUYT6rvfi6t9k65UMLJC+PHZpDAA==} engines: {node: ^10 || ^12 || >=14} prelude-ls@1.2.1: @@ -6284,7 +6284,7 @@ snapshots: '@vue/shared': 3.5.26 estree-walker: 2.0.2 magic-string: 0.30.21 - postcss: 8.5.6 + postcss: 8.5.12 source-map-js: 1.2.1 '@vue/compiler-ssr@3.5.26': @@ -6515,13 +6515,13 @@ snapshots: attr-accept@2.2.5: {} - autoprefixer@10.4.23(postcss@8.5.6): + autoprefixer@10.4.23(postcss@8.5.12): dependencies: browserslist: 4.28.1 caniuse-lite: 1.0.30001761 fraction.js: 5.3.4 picocolors: 1.1.1 - postcss: 8.5.6 + postcss: 8.5.12 postcss-value-parser: 4.2.0 axios@1.18.1: @@ -8607,28 +8607,28 @@ snapshots: dependencies: '@babel/runtime': 7.28.4 - postcss-import@15.1.0(postcss@8.5.6): + postcss-import@15.1.0(postcss@8.5.12): dependencies: - postcss: 8.5.6 + postcss: 8.5.12 postcss-value-parser: 4.2.0 read-cache: 1.0.0 resolve: 1.22.11 - postcss-js@4.1.0(postcss@8.5.6): + postcss-js@4.1.0(postcss@8.5.12): dependencies: camelcase-css: 2.0.1 - postcss: 8.5.6 + postcss: 8.5.12 - postcss-load-config@6.0.1(jiti@1.21.7)(postcss@8.5.6): + postcss-load-config@6.0.1(jiti@1.21.7)(postcss@8.5.12): dependencies: lilconfig: 3.1.3 optionalDependencies: jiti: 1.21.7 - postcss: 8.5.6 + postcss: 8.5.12 - postcss-nested@6.2.0(postcss@8.5.6): + postcss-nested@6.2.0(postcss@8.5.12): dependencies: - postcss: 8.5.6 + postcss: 8.5.12 postcss-selector-parser: 6.1.2 postcss-selector-parser@6.1.2: @@ -8638,7 +8638,7 @@ snapshots: postcss-value-parser@4.2.0: {} - postcss@8.5.6: + postcss@8.5.12: dependencies: nanoid: 3.3.11 picocolors: 1.1.1 @@ -9253,11 +9253,11 @@ snapshots: normalize-path: 3.0.0 object-hash: 3.0.0 picocolors: 1.1.1 - postcss: 8.5.6 - postcss-import: 15.1.0(postcss@8.5.6) - postcss-js: 4.1.0(postcss@8.5.6) - postcss-load-config: 6.0.1(jiti@1.21.7)(postcss@8.5.6) - postcss-nested: 6.2.0(postcss@8.5.6) + postcss: 8.5.12 + postcss-import: 15.1.0(postcss@8.5.12) + postcss-js: 4.1.0(postcss@8.5.12) + postcss-load-config: 6.0.1(jiti@1.21.7)(postcss@8.5.12) + postcss-nested: 6.2.0(postcss@8.5.12) postcss-selector-parser: 6.1.2 resolve: 1.22.11 sucrase: 3.35.1 @@ -9489,7 +9489,7 @@ snapshots: vite@5.4.21(@types/node@20.19.27): dependencies: esbuild: 0.21.5 - postcss: 8.5.6 + postcss: 8.5.12 rollup: 4.54.0 optionalDependencies: '@types/node': 20.19.27