@nanogpt/private-mode 0.2.18 → 0.2.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1021,6 +1021,37 @@ function applyTinfoilCompatibilityMutations(body, model) {
1021
1021
  }
1022
1022
  }
1023
1023
 
1024
+ function stripEmptyPrivateModeToolDeclarations(body) {
1025
+ // Some OpenAI-compatible clients send inactive tool support as empty arrays.
1026
+ // Tinfoil rejects those arrays, so omit them and their dependent controls.
1027
+ const hasTopLevelTools = Array.isArray(body.tools) && body.tools.length > 0;
1028
+ const hasMessageTools = Array.isArray(body.messages) && body.messages.some(
1029
+ (message) => isPlainObject(message) &&
1030
+ message.role === 'system' &&
1031
+ Array.isArray(message.tools) &&
1032
+ message.tools.length > 0,
1033
+ );
1034
+
1035
+ if (Array.isArray(body.tools) && body.tools.length === 0) {
1036
+ delete body.tools;
1037
+ if (!hasMessageTools) {
1038
+ delete body.tool_choice;
1039
+ delete body.parallel_tool_calls;
1040
+ }
1041
+ }
1042
+
1043
+ // Some clients leave tool_choice="auto" behind even when they omit tools.
1044
+ // Tinfoil rejects that otherwise harmless inactive control.
1045
+ if (!hasTopLevelTools && !hasMessageTools && body.tool_choice === 'auto') {
1046
+ delete body.tool_choice;
1047
+ }
1048
+
1049
+ if (Array.isArray(body.functions) && body.functions.length === 0) {
1050
+ delete body.functions;
1051
+ delete body.function_call;
1052
+ }
1053
+ }
1054
+
1024
1055
  function normalizeMaxTokenAliases(body) {
1025
1056
  for (const key of MAX_TOKEN_ALIAS_FIELDS) {
1026
1057
  if (body.max_tokens === undefined && body[key] !== undefined) {
@@ -1115,6 +1146,7 @@ export function applyPrivateModelRequestMutations(body, model) {
1115
1146
  if (model.thinkingMode !== 'glm-5.3') delete body.reasoning_effort;
1116
1147
  }
1117
1148
 
1149
+ stripEmptyPrivateModeToolDeclarations(body);
1118
1150
  stripUnsupportedPrivateTinfoilFields(body);
1119
1151
  return body;
1120
1152
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nanogpt/private-mode",
3
- "version": "0.2.18",
3
+ "version": "0.2.20",
4
4
  "description": "OpenAI-compatible localhost proxy for NanoGPT Private Mode.",
5
5
  "type": "module",
6
6
  "publishConfig": {