ck-pi-zen-session 0.1.7 → 0.1.8

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
@@ -26,6 +26,7 @@ OpenCode Zen 免费模型同步、请求头伪装与 Session 会话自动维护
26
26
  - 自动对齐流式用量元数据 `stream_options: { include_usage: true }`。
27
27
  - 🌐 **独立供应商隔离与零干扰保障 (`isZenModelTarget`)**:严格将生命周期守卫、请求头与请求体拦截限制在 `opencode-zen-free` 命名空间内,对 `relayhub`、`deepseek`、`anthropic`、`openai`、`onerouter`、`apmix` 等其他任何模型及 Claude Code(`pi-cc-extensions`)插件 100% 保持完全静默放行,零副作用、零冲突。
28
28
  - 🧠 **高精智能模型能力与参数解析引擎 (v0.1.7)**:无论输入新 Key 还是 OpenCode Zen 官方端点动态上线任何新免费/零额度模型,自动深度识别其上下文窗口(Context Window,如 1M, 256K, 200K, 128K)、最大输出(Max Tokens,如 128K, 64K, 32K, 16K)、推理思考能力与思考等级映射(thinkingLevelMap,涵盖 6 档深度推理 [minimal..xhigh]、3 档标准推理 [low, high, max] 或快反模式)以及视觉多模态支持,并在 `/zen <key>` 和 `/zen list` 中呈现精美结构化卡片。
29
+ - 🛡️ **OpenAI 标准思考档位全链路映射与双重防线 (v0.1.8)**:彻底修复 OpenCode Zen 上游端点不支持 `max` / `xhigh` 思考档位导致抛出 `[400] Invalid request parameters` 的致命问题。全面将思考档位映射对齐 OpenAI 标准 `reasoning_effort`(`low` / `medium` / `high`),并在 `before_provider_request` 请求体守卫中设立兜底防线,自动将非标准或溢出档位降级规约为合法参数,确保小米 MiMo、英伟达 Nemotron、Meta Muse Spark 等全系模型在任意 Pi 默认思考模式下 100% 稳定响应。
29
30
  - 🔌 **全自动多端持久化同步**:自动双写 Pi 本地配置(`~/.pi/agent/models.json` 和 `~/.pi/agent/auth.json`),若检测到 CC-Switch 亦无缝同步其 SQLite 数据库。
30
31
 
31
32
  ---
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ck-pi-zen-session",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "OpenCode Zen session auto-refresh and free-tier model catalog synchronization for the Pi coding agent.",
5
5
  "keywords": [
6
6
  "pi-package",
package/src/index.ts CHANGED
@@ -82,8 +82,18 @@ export function registerZenProviderToPi(
82
82
  }
83
83
  }
84
84
 
85
- export function isZenModelTarget(model?: { provider?: string; id?: string }): boolean {
86
- if (!model) return false;
85
+ export function isZenModelTarget(model?: { provider?: string; id?: string }, payloadModel?: string): boolean {
86
+ if (!model) {
87
+ if (payloadModel) {
88
+ const lower = payloadModel.toLowerCase();
89
+ return (
90
+ lower.endsWith("-free") ||
91
+ lower === "big-pickle" ||
92
+ lower.includes("zen")
93
+ );
94
+ }
95
+ return false;
96
+ }
87
97
  // 严格隔离:仅处理 opencode-zen-free 或明确属于 opencode 官方的免费模型
88
98
  // 绝不干涉 relayhub、deepseek、anthropic、openai 等其他任何供应商或 CC 插件
89
99
  if (model.provider === ZEN_PROVIDER_ID) return true;
@@ -130,6 +140,7 @@ export default function piZenSession(pi: ExtensionAPI): void {
130
140
  }
131
141
 
132
142
  // 注入全部官方客户端 7 维对齐请求头
143
+ delete event.headers["user-agent"];
133
144
  event.headers["User-Agent"] = ZEN_USER_AGENT;
134
145
  event.headers["x-opencode-client"] = "cli";
135
146
  event.headers["x-opencode-session"] = currentSession;
@@ -142,8 +153,9 @@ export default function piZenSession(pi: ExtensionAPI): void {
142
153
 
143
154
  // 3. 核心请求体守卫钩子:深度对齐 OpenCode 官方请求体结构与工具集
144
155
  pi.on("before_provider_request", (event, ctx) => {
145
- if (isZenModelTarget(ctx.model) && event.payload && typeof event.payload === "object") {
146
- const payload = event.payload as Record<string, unknown>;
156
+ const payload = event.payload as Record<string, unknown> | undefined;
157
+ const payloadModel = typeof payload?.model === "string" ? payload.model : undefined;
158
+ if (isZenModelTarget(ctx.model, payloadModel) && payload && typeof payload === "object") {
147
159
  const tools = payload.tools;
148
160
  let modified = false;
149
161
  const transformed = { ...payload };
@@ -168,6 +180,22 @@ export default function piZenSession(pi: ExtensionAPI): void {
168
180
  modified = true;
169
181
  }
170
182
 
183
+ // C. 规范化 reasoning_effort:OpenCode Zen 上游端点仅支持 "low", "medium", "high"
184
+ // 若为 "max" 或 "xhigh",降级映射为 "high";若为 "minimal" 映射为 "low",彻底根除 400 Invalid request parameters
185
+ if (typeof transformed.reasoning_effort === "string") {
186
+ const effort = transformed.reasoning_effort.toLowerCase();
187
+ if (effort === "max" || effort === "xhigh") {
188
+ transformed.reasoning_effort = "high";
189
+ modified = true;
190
+ } else if (effort === "minimal") {
191
+ transformed.reasoning_effort = "low";
192
+ modified = true;
193
+ } else if (!["low", "medium", "high"].includes(effort)) {
194
+ transformed.reasoning_effort = "high";
195
+ modified = true;
196
+ }
197
+ }
198
+
171
199
  if (modified) {
172
200
  return transformed;
173
201
  }
@@ -12,22 +12,22 @@ export const ZEN_BASE_URL = "https://opencode.ai/zen/v1";
12
12
  export const ZEN_USER_AGENT = "opencode/1.18.32 ai-sdk/provider-utils/4.0.23 runtime/bun/1.3.14";
13
13
 
14
14
  export const STANDARD_THINKING_LEVELS: Record<string, string | null> = {
15
+ minimal: "low",
15
16
  low: "low",
17
+ medium: "medium",
16
18
  high: "high",
17
- max: "max",
18
- medium: null,
19
- minimal: null,
19
+ xhigh: "high",
20
+ max: "high",
20
21
  off: null,
21
- xhigh: null,
22
22
  };
23
23
 
24
24
  export const MUSE_SPARK_THINKING_LEVELS: Record<string, string | null> = {
25
- minimal: "minimal",
25
+ minimal: "low",
26
26
  low: "low",
27
27
  medium: "medium",
28
28
  high: "high",
29
- xhigh: "xhigh",
30
- max: "xhigh",
29
+ xhigh: "high",
30
+ max: "high",
31
31
  off: null,
32
32
  };
33
33
 
@@ -37,7 +37,7 @@ export const GRANULAR_THINKING_LEVELS: Record<string, string | null> = {
37
37
  medium: "medium",
38
38
  high: "high",
39
39
  xhigh: "high",
40
- max: "max",
40
+ max: "high",
41
41
  off: null,
42
42
  };
43
43