@nanogpt/private-mode 0.2.14 → 0.2.16

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.
package/README.md CHANGED
@@ -25,7 +25,7 @@ const client = new OpenAI({
25
25
  });
26
26
 
27
27
  const response = await client.chat.completions.create({
28
- model: "private/glm-5-2",
28
+ model: "private/glm-5-3",
29
29
  messages: [{ role: "user", content: "Hello" }],
30
30
  });
31
31
  ```
@@ -68,18 +68,17 @@ GET http://127.0.0.1:8787/v1/private-mode/attestation
68
68
 
69
69
  Supported private model IDs include:
70
70
 
71
+ - `private/deepseek-v4-1-flash` - DeepSeek V4.1 Flash
71
72
  - `private/deepseek-v4-flash` - DeepSeek V4 Flash 0731
72
73
  - `private/kimi-k3`
73
74
  - `private/gpt-oss-120b`
74
75
  - `private/llama3-3-70b`
75
- - `private/glm-5-2`
76
- - `private/glm-5-2:thinking`
77
76
  - `private/glm-5-3`
78
77
  - `private/glm-5-3-flash`
79
78
  - `private/gemma4-31b`
80
79
  - `private/gemma4-31b:thinking`
81
80
 
82
- Both GLM 5.2 variants are deployed with a 393,216-token total context limit, with prompt and output sharing that window. GLM 5.3 Private and GLM 5.3 Flash Private each have a 1,048,576-token total context limit and a 131,072-token output ceiling. Kimi K3 Private has a 256,000-token context limit. DeepSeek V4 Flash 0731 Private has a 1,048,576-token total context limit. The model-list extension `context_length` is the combined prompt-and-output window, while `max_output_tokens` is the output ceiling within that same window. These values are not additive.
81
+ GLM 5.3 Private and GLM 5.3 Flash Private each have a 1,048,576-token total context limit and a 131,072-token output ceiling. Kimi K3 Private has a 256,000-token context limit. DeepSeek V4 Flash 0731 Private has a 1,048,576-token total context limit. The model-list extension `context_length` is the combined prompt-and-output window, while `max_output_tokens` is the output ceiling within that same window. These values are not additive.
83
82
 
84
83
  ### Thinking without leaving Private Mode
85
84
 
@@ -94,7 +93,7 @@ Keep the same private model ID when enabling thinking. For example:
94
93
  }
95
94
  ```
96
95
 
97
- DeepSeek V4 Flash uses the 0731 release and supports optional thinking. GLM 5.2 and Gemma 4 also support optional thinking. Use `thinking: true` or `enable_thinking: true` to enable it; `thinking: false` disables it for these optional-thinking models. Kimi K3, GLM 5.3, and GLM 5.3 Flash always generate reasoning. GLM 5.3 models accept `low`, `high`, or `max` effort. `reasoning: { "exclude": true }` controls response visibility and does not disable thinking.
96
+ DeepSeek V4 Flash uses the 0731 release and supports optional thinking. Gemma 4 also supports optional thinking. Use `thinking: true` or `enable_thinking: true` to enable it; `thinking: false` disables it for these optional-thinking models. Kimi K3, GLM 5.3, and GLM 5.3 Flash always generate reasoning. GLM 5.3 models accept `low`, `high`, or `max` effort. `reasoning: { "exclude": true }` controls response visibility and does not disable thinking.
98
97
 
99
98
  Non-streaming reasoning requests may take more than five minutes. The CLI allows the encrypted request to wait for the hosted route's response, with a 30-minute transport limit. The hosted route stops non-streaming generation after at most 29 minutes to leave time before its platform deadline. Use `stream: true` for earlier output, and configure your API client's timeout to allow long generations. Upgrade the local proxy as well as the hosted service to receive both timeout fixes.
100
99
 
@@ -236,8 +236,16 @@ function isReasoningEnabled(reasoning) {
236
236
  return undefined;
237
237
  }
238
238
 
239
- function normalizeDeepSeekV4ReasoningEffort(value) {
239
+ function normalizeDeepSeekV4ReasoningEffort(value, model, nativeTemplateValue = false) {
240
240
  const normalized = typeof value === 'string' ? value.trim().toLowerCase() : '';
241
+ if (model?.thinkingMode === 'deepseek-v4.1') {
242
+ if (nativeTemplateValue && ['low', 'high', 'xhigh'].includes(normalized)) {
243
+ return normalized;
244
+ }
245
+ if (normalized === 'low' || normalized === 'minimal') return 'low';
246
+ if (normalized === 'medium') return 'high';
247
+ return 'xhigh';
248
+ }
241
249
  if (normalized === 'max' || normalized === 'xhigh') return 'max';
242
250
  if (normalized === 'medium') return 'medium';
243
251
  if (normalized === 'low' || normalized === 'minimal') return 'low';
@@ -606,14 +614,17 @@ function applyPrivateModeKimiK3RequestParams(body, model) {
606
614
  );
607
615
  }
608
616
 
609
- function clampPrivateModeDeepSeekV4Output(body) {
617
+ function clampPrivateModeDeepSeekV4Output(body, model) {
618
+ const maxCompletionTokens = Number.isFinite(model?.maxOutputTokens)
619
+ ? Math.max(1, Math.floor(model.maxOutputTokens))
620
+ : DEEPSEEK_V4_MAX_COMPLETION_TOKENS;
610
621
  const requestedMaxTokens = typeof body.max_tokens === 'number' && Number.isFinite(body.max_tokens)
611
622
  ? body.max_tokens
612
623
  : undefined;
613
624
  if (requestedMaxTokens === undefined) return;
614
625
 
615
626
  const normalizedMaxTokens = requestedMaxTokens < 0
616
- ? DEEPSEEK_V4_MAX_COMPLETION_TOKENS
627
+ ? maxCompletionTokens
617
628
  : requestedMaxTokens;
618
629
  const promptTokenEstimate = estimatePrivateModeKimiK3PromptTokens(body);
619
630
  const remainingContext = Math.max(
@@ -624,7 +635,7 @@ function clampPrivateModeDeepSeekV4Output(body) {
624
635
  );
625
636
  body.max_tokens = Math.min(
626
637
  Math.max(1, Math.floor(normalizedMaxTokens)),
627
- DEEPSEEK_V4_MAX_COMPLETION_TOKENS,
638
+ maxCompletionTokens,
628
639
  remainingContext,
629
640
  );
630
641
  }
@@ -1051,8 +1062,11 @@ export function applyPrivateModelRequestMutations(body, model) {
1051
1062
  applyTinfoilCompatibilityMutations(body, model);
1052
1063
  if (isPrivateModeKimiK3Model(model)) {
1053
1064
  applyPrivateModeKimiK3RequestParams(body, model);
1054
- } else if (model.thinkingMode === 'deepseek-v4') {
1055
- clampPrivateModeDeepSeekV4Output(body);
1065
+ } else if (
1066
+ model.thinkingMode === 'deepseek-v4' ||
1067
+ model.thinkingMode === 'deepseek-v4.1'
1068
+ ) {
1069
+ clampPrivateModeDeepSeekV4Output(body, model);
1056
1070
  } else if (model.thinkingMode === 'glm-5.3') {
1057
1071
  clampPrivateModeGlm53Output(body);
1058
1072
  }
@@ -1067,14 +1081,16 @@ export function applyPrivateModelRequestMutations(body, model) {
1067
1081
  } else if (
1068
1082
  model.thinkingMode === 'glm-5.2' ||
1069
1083
  model.thinkingMode === 'glm-5.3' ||
1070
- model.thinkingMode === 'deepseek-v4'
1084
+ model.thinkingMode === 'deepseek-v4' ||
1085
+ model.thinkingMode === 'deepseek-v4.1'
1071
1086
  ) {
1072
1087
  const thinkingEnabled = model.thinkingMode === 'glm-5.3'
1073
1088
  ? true
1074
1089
  : shouldEnableThinking(body, model);
1075
- const requestedReasoningEffort = body.reasoning_effort
1076
- ?? (isPlainObject(body.reasoning) ? body.reasoning.effort : undefined)
1077
- ?? body.chat_template_kwargs?.reasoning_effort;
1090
+ const publicReasoningEffort = body.reasoning_effort
1091
+ ?? (isPlainObject(body.reasoning) ? body.reasoning.effort : undefined);
1092
+ const nativeTemplateReasoningEffort = body.chat_template_kwargs?.reasoning_effort;
1093
+ const requestedReasoningEffort = publicReasoningEffort ?? nativeTemplateReasoningEffort;
1078
1094
  body.chat_template_kwargs = {
1079
1095
  ...mergeChatTemplateKwargs(body),
1080
1096
  thinking: thinkingEnabled,
@@ -1086,7 +1102,11 @@ export function applyPrivateModelRequestMutations(body, model) {
1086
1102
  body.reasoning_effort = normalizeGlm53ReasoningEffort(requestedReasoningEffort);
1087
1103
  delete body.chat_template_kwargs.reasoning_effort;
1088
1104
  } else if (thinkingEnabled) {
1089
- body.chat_template_kwargs.reasoning_effort = normalizeDeepSeekV4ReasoningEffort(requestedReasoningEffort);
1105
+ body.chat_template_kwargs.reasoning_effort = normalizeDeepSeekV4ReasoningEffort(
1106
+ requestedReasoningEffort,
1107
+ model,
1108
+ publicReasoningEffort === undefined && nativeTemplateReasoningEffort !== undefined,
1109
+ );
1090
1110
  } else {
1091
1111
  delete body.chat_template_kwargs.reasoning_effort;
1092
1112
  }
@@ -3,6 +3,7 @@ import { createHash } from 'node:crypto';
3
3
  export const PRIVATE_MODE_FRONTEND_SUPPORTED_FEATURES = Object.freeze([
4
4
  'text_chat',
5
5
  'vision_image_inputs',
6
+ 'encrypted_pdf_conversion',
6
7
  'streaming',
7
8
  'conversation_history',
8
9
  'model_settings',
@@ -10,7 +11,7 @@ export const PRIVATE_MODE_FRONTEND_SUPPORTED_FEATURES = Object.freeze([
10
11
  ]);
11
12
 
12
13
  export const PRIVATE_MODE_FRONTEND_DISABLED_FEATURES = Object.freeze([
13
- 'non_image_attachments',
14
+ 'non_image_non_pdf_attachments',
14
15
  'web_search',
15
16
  'url_scraped_content',
16
17
  'project_chats',
@@ -1,4 +1,18 @@
1
1
  [
2
+ {
3
+ "id": "private/deepseek-v4-1-flash",
4
+ "name": "DeepSeek V4.1 Flash Private",
5
+ "upstreamModel": "deepseek-v4-1-flash",
6
+ "billingModel": "TEE/deepseek-v4.1-flash",
7
+ "providerPricingModel": "TEE/deepseek-v4.1-flash",
8
+ "teeTargetModel": "deepseek-v4-1-flash",
9
+ "thinkingMode": "deepseek-v4.1",
10
+ "maxInputTokens": 1048576,
11
+ "maxOutputTokens": 384000,
12
+ "created": 1789084800,
13
+ "ownedBy": "nanogpt-private-mode",
14
+ "aliases": ["private/deepseek-v4.1-flash", "TEE/deepseek-v4.1-flash"]
15
+ },
2
16
  {
3
17
  "id": "private/deepseek-v4-flash",
4
18
  "name": "DeepSeek V4 Flash 0731 Private",
@@ -48,34 +62,6 @@
48
62
  "ownedBy": "nanogpt-private-mode",
49
63
  "aliases": ["private/llama-3.3-70b", "TEE/llama3-3-70b"]
50
64
  },
51
- {
52
- "id": "private/glm-5-2",
53
- "name": "GLM 5.2 Private",
54
- "upstreamModel": "glm-5-2",
55
- "billingModel": "TEE/glm-5-2",
56
- "providerPricingModel": "TEE/glm-5.2",
57
- "teeTargetModel": "glm-5-2",
58
- "thinkingMode": "glm-5.2",
59
- "maxInputTokens": 393216,
60
- "maxOutputTokens": 131072,
61
- "created": 1781827200,
62
- "ownedBy": "nanogpt-private-mode",
63
- "aliases": ["private/glm-5.2", "TEE/glm-5-2", "TEE/glm-5.2"]
64
- },
65
- {
66
- "id": "private/glm-5-2:thinking",
67
- "name": "GLM 5.2 Thinking Private",
68
- "upstreamModel": "glm-5-2",
69
- "billingModel": "TEE/glm-5-2:thinking",
70
- "providerPricingModel": "TEE/glm-5.2:thinking",
71
- "teeTargetModel": "glm-5-2",
72
- "thinkingMode": "glm-5.2",
73
- "maxInputTokens": 393216,
74
- "maxOutputTokens": 131072,
75
- "created": 1781827200,
76
- "ownedBy": "nanogpt-private-mode",
77
- "aliases": ["private/glm-5.2:thinking", "TEE/glm-5-2:thinking", "TEE/glm-5.2:thinking"]
78
- },
79
65
  {
80
66
  "id": "private/glm-5-3",
81
67
  "name": "GLM 5.3 Private",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nanogpt/private-mode",
3
- "version": "0.2.14",
3
+ "version": "0.2.16",
4
4
  "description": "OpenAI-compatible localhost proxy for NanoGPT Private Mode.",
5
5
  "type": "module",
6
6
  "publishConfig": {