ck-pi-zen-session 0.1.4 → 0.1.6
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 +1 -1
- package/package.json +1 -1
- package/src/index.ts +21 -22
package/README.md
CHANGED
|
@@ -24,7 +24,7 @@ OpenCode Zen 免费模型同步、请求头伪装与 Session 会话自动维护
|
|
|
24
24
|
- 若用户处于纯文本或无工具模式,自动补齐官方完整的 6 大核心工具(`bash`, `edit`, `glob`, `grep`, `read`, `write`)与 `tool_choice: "auto"`,彻底根除 403 拦截;
|
|
25
25
|
- 若请求已有工具,严格按照官方客户端规约(`localeCompare`)按函数名升序重排;
|
|
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
|
- 🧠 **精准上下文与思维链适配**:严格对齐免费模型的 `contextWindow`、`maxTokens` 与 `thinkingLevelMap`(涵盖小米 MiMo、英伟达 Nemotron、Meta Muse Spark、Ling、Jev 等)。
|
|
29
29
|
- 🔌 **全自动多端持久化同步**:自动双写 Pi 本地配置(`~/.pi/agent/models.json` 和 `~/.pi/agent/auth.json`),若检测到 CC-Switch 亦无缝同步其 SQLite 数据库。
|
|
30
30
|
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -68,6 +68,20 @@ export function registerZenProviderToPi(
|
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
+
export function isZenModelTarget(model?: { provider?: string; id?: string }): boolean {
|
|
72
|
+
if (!model) return false;
|
|
73
|
+
// 严格隔离:仅处理 opencode-zen-free 或明确属于 opencode 官方的免费模型
|
|
74
|
+
// 绝不干涉 relayhub、deepseek、anthropic、openai 等其他任何供应商或 CC 插件
|
|
75
|
+
if (model.provider === ZEN_PROVIDER_ID) return true;
|
|
76
|
+
if (
|
|
77
|
+
model.provider === "opencode" &&
|
|
78
|
+
(model.id?.includes("-free") || model.id === "big-pickle")
|
|
79
|
+
) {
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
|
|
71
85
|
export default function piZenSession(pi: ExtensionAPI): void {
|
|
72
86
|
// 1. 若本地已配置 Key,启动时即刻注册独立供应商 opencode-zen-free
|
|
73
87
|
// 独立命名空间,彻底避开并兼容用户自带的官方登录 opencode / opencode-zen 套餐
|
|
@@ -78,13 +92,7 @@ export default function piZenSession(pi: ExtensionAPI): void {
|
|
|
78
92
|
|
|
79
93
|
// 2. 核心请求头拦截钩子:在每一次请求发往 Provider 前注入完整官方客户端对齐请求头
|
|
80
94
|
pi.on("before_provider_headers", (event, ctx) => {
|
|
81
|
-
|
|
82
|
-
const isZenModel =
|
|
83
|
-
model?.provider === ZEN_PROVIDER_ID ||
|
|
84
|
-
model?.id?.includes("-free") ||
|
|
85
|
-
model?.id === "big-pickle";
|
|
86
|
-
|
|
87
|
-
if (isZenModel) {
|
|
95
|
+
if (isZenModelTarget(ctx.model)) {
|
|
88
96
|
// 检查 x-opencode-session 是否过期 (>30分钟) 或缺失
|
|
89
97
|
let currentSession = event.headers["x-opencode-session"];
|
|
90
98
|
if (
|
|
@@ -111,13 +119,7 @@ export default function piZenSession(pi: ExtensionAPI): void {
|
|
|
111
119
|
|
|
112
120
|
// 3. 核心请求体守卫钩子:深度对齐 OpenCode 官方请求体结构与工具集
|
|
113
121
|
pi.on("before_provider_request", (event, ctx) => {
|
|
114
|
-
|
|
115
|
-
const isZenModel =
|
|
116
|
-
model?.provider === ZEN_PROVIDER_ID ||
|
|
117
|
-
model?.id?.includes("-free") ||
|
|
118
|
-
model?.id === "big-pickle";
|
|
119
|
-
|
|
120
|
-
if (isZenModel && event.payload && typeof event.payload === "object") {
|
|
122
|
+
if (isZenModelTarget(ctx.model) && event.payload && typeof event.payload === "object") {
|
|
121
123
|
const payload = event.payload as Record<string, unknown>;
|
|
122
124
|
const tools = payload.tools;
|
|
123
125
|
let modified = false;
|
|
@@ -151,13 +153,7 @@ export default function piZenSession(pi: ExtensionAPI): void {
|
|
|
151
153
|
|
|
152
154
|
// 4. 网关响应守卫:遇 401/403 会话受限或过期时,立即自愈换新 Session ID
|
|
153
155
|
pi.on("after_provider_response", (event, ctx) => {
|
|
154
|
-
|
|
155
|
-
const isZenModel =
|
|
156
|
-
model?.provider === ZEN_PROVIDER_ID ||
|
|
157
|
-
model?.id?.includes("-free") ||
|
|
158
|
-
model?.id === "big-pickle";
|
|
159
|
-
|
|
160
|
-
if (isZenModel && (event.status === 401 || event.status === 403)) {
|
|
156
|
+
if (isZenModelTarget(ctx.model) && (event.status === 401 || event.status === 403)) {
|
|
161
157
|
// 自动异步刷新 Session
|
|
162
158
|
syncZenConfiguration({ forceSession: true }).catch(() => {});
|
|
163
159
|
if (ctx.hasUI) {
|
|
@@ -170,8 +166,11 @@ export default function piZenSession(pi: ExtensionAPI): void {
|
|
|
170
166
|
});
|
|
171
167
|
|
|
172
168
|
// 5. 常驻生命周期守卫:在每次 Agent 循环执行前,自动检测 Session 有效性并无感续期
|
|
173
|
-
pi.on("before_agent_start", async () => {
|
|
169
|
+
pi.on("before_agent_start", async (_event, ctx) => {
|
|
174
170
|
try {
|
|
171
|
+
// 严格隔离:仅在当前激活/选择的是 Zen 模型时才触发轮换检测,绝不干扰其他模型或 CC 插件
|
|
172
|
+
if (!isZenModelTarget(ctx.model)) return;
|
|
173
|
+
|
|
175
174
|
const currentSession = getStoredZenSessionId();
|
|
176
175
|
// 若当前会话不存在或已使用超过 30 分钟,后台自动续期
|
|
177
176
|
if (!currentSession || isZenSessionExpired(currentSession, DEFAULT_SESSION_MAX_AGE_MS)) {
|