pi-cache-optimizer 2.8.19 → 2.8.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.
- package/README.md +5 -5
- package/README.zh-CN.md +6 -6
- package/index.ts +1 -0
- package/package.json +3 -3
- package/src/provider-errors.ts +36 -4
package/README.md
CHANGED
|
@@ -62,7 +62,7 @@ Run `/reload` in Pi after install/update/remove so extension hooks refresh.
|
|
|
62
62
|
|
|
63
63
|
On Pi 0.79.7 and newer, `pi update` updates Pi itself only. To update installed Pi packages such as this extension, run `pi update --extensions` (packages only) or `pi update --all` (Pi + packages).
|
|
64
64
|
|
|
65
|
-
This extension requires Pi 0.82+ and is validated against Pi 1.0.
|
|
65
|
+
This extension requires Pi 0.82+ and is validated against Pi 1.0.3. It uses the official Pi package types directly for type-checking, along with extension hooks, `getAgentDir()`, and prompt options shared by those versions; it does not depend on Pi 0.83+ APIs such as `ctx.scopedModels` or the bundled TypeBox 1.3 aliases. Native virtual model support and codemode nested-call coalescing activate only on Pi 0.99+ hosts that produce them; older hosts keep the previous behavior. The local development baseline uses Node.js 22.19.0 or newer, matching Pi 1.0.3's engine requirement.
|
|
66
66
|
|
|
67
67
|
## Commands
|
|
68
68
|
|
|
@@ -156,9 +156,9 @@ The explicit setting is stored in `pi-cache-optimizer-config.json` under Pi's ag
|
|
|
156
156
|
|
|
157
157
|
## Per-model `prompt_cache_key` opt-out
|
|
158
158
|
|
|
159
|
-
Some OpenAI-compatible Completions endpoints reject `prompt_cache_key` with HTTP 400 even though the same field is valid for other providers. Pi 1.0.
|
|
159
|
+
Some OpenAI-compatible Completions endpoints reject `prompt_cache_key` with HTTP 400 even though the same field is valid for other providers. Pi 1.0.3 owns the key for Responses/Codex transports; this extension's key opt-out and fallback apply only to `openai-completions`. Pi 1.0.3 has no native `supportsPromptCacheKey` compat field; do **not** add that unknown field to `models.json`. `supportsLongCacheRetention` is not an equivalent switch and should not be used for this purpose.
|
|
160
160
|
|
|
161
|
-
When the extension observes an explicit field-level `prompt_cache_key` unsupported error for the exact provider/model, ordinary `/cache-optimizer fix` offers a confirmed model-scoped repair. Value-validation failures and conditional restrictions such as “not allowed when temperature is set” do not qualify. If concurrent responses from different models cannot be correlated because Pi provides no request ID, header-only evidence is ignored unless the finalized assistant message supplies exact provider/model identity. If you already know that the endpoint rejects the field, use the explicit command:
|
|
161
|
+
When the extension observes an explicit field-level `prompt_cache_key` unsupported error for the exact provider/model (including recognized Chinese-localized forms such as `未知请求字段:prompt_cache_key`), ordinary `/cache-optimizer fix` offers a confirmed model-scoped repair. Value-validation failures and conditional restrictions such as “not allowed when temperature is set” do not qualify. If concurrent responses from different models cannot be correlated because Pi provides no request ID, header-only evidence is ignored unless the finalized assistant message supplies exact provider/model identity. If you already know that the endpoint rejects the field, use the explicit command:
|
|
162
162
|
|
|
163
163
|
```text
|
|
164
164
|
/cache-optimizer fix prompt-cache-key
|
|
@@ -196,7 +196,7 @@ Notes:
|
|
|
196
196
|
|
|
197
197
|
- `sendSessionAffinityHeaders: true` is the safe default when your proxy supports sticky routing.
|
|
198
198
|
- `supportsLongCacheRetention: true` is optional. Add it only when the endpoint explicitly supports OpenAI long prompt cache retention.
|
|
199
|
-
- Do not add `supportsPromptCacheKey` to `models.json`: Pi 1.0.
|
|
199
|
+
- Do not add `supportsPromptCacheKey` to `models.json`: Pi 1.0.3 does not define that compat field. Use `/cache-optimizer fix prompt-cache-key` to store an exact provider/model omit rule in the extension-owned config; it removes both key spellings, including a key supplied by Pi.
|
|
200
200
|
- If you see `400 Unsupported parameter: prompt_cache_retention`, remove/avoid `supportsLongCacheRetention` for that channel. Keep `sendSessionAffinityHeaders` if supported. The extension detects the explicit error from response headers or the finalized assistant error message and strips the parameter from subsequent requests in the current process.
|
|
201
201
|
- Use `/cache-optimizer compat` or `/cache-optimizer doctor` to see model-specific advice.
|
|
202
202
|
- DeepSeek model names select the `DS cache` adapter only; they do not prove a reasoning wire protocol. Generic cache/routing advice remains active for absent or non-DeepSeek formats. DeepSeek replay advice is shown only when effective `compat.thinkingFormat: "deepseek"` is explicitly configured; it never treats `thinkingFormat` as a missing fix key.
|
|
@@ -354,7 +354,7 @@ Pi's model-family name and its reasoning wire protocol are separate. A DeepSeek-
|
|
|
354
354
|
The novice-safe workflow is staged:
|
|
355
355
|
|
|
356
356
|
1. Run `/cache-optimizer fix` for protocol-neutral cache/routing repairs such as session affinity. It shows the exact placement and requires confirmation.
|
|
357
|
-
2. Make a normal request. If an OpenAI-compatible DeepSeek-like model explicitly rejects the `thinking` parameter in favor of `reasoning_effort
|
|
357
|
+
2. Make a normal request. If an OpenAI-compatible DeepSeek-like model explicitly rejects the `thinking` parameter in favor of `reasoning_effort` (including recognized Chinese-localized rejection and recommendation text), the extension keeps only a model-scoped, process-local category. It does not persist or display the complete provider error, send a hidden probe, or edit configuration from a response hook.
|
|
358
358
|
3. Run `/cache-optimizer fix` again to review an evidence-based model-level protocol repair. It is written through the highest-precedence `modelOverrides[modelId].compat` layer and validated against runtime compat, so an extension-provided model cannot silently shadow it. A provider-level change is never broadened from a model name alone. Explicit `openai`, `qwen`, `openrouter`, and `together` formats remain respected.
|
|
359
359
|
4. If the latest confirmed fix caused the problem, run `/cache-optimizer rollback`. Rollback always requires UI confirmation.
|
|
360
360
|
|
package/README.zh-CN.md
CHANGED
|
@@ -62,7 +62,7 @@ pi remove npm:pi-deepseek-cache-optimizer && pi install npm:pi-cache-optimizer
|
|
|
62
62
|
|
|
63
63
|
Pi 0.79.7 及之后,`pi update` 默认只更新 Pi 本体。若要更新已安装的 Pi package(包括本扩展),请运行 `pi update --extensions`(只更新 packages)或 `pi update --all`(Pi 与 packages 一起更新)。
|
|
64
64
|
|
|
65
|
-
本扩展要求 Pi 0.82+,并已使用 Pi 1.0.
|
|
65
|
+
本扩展要求 Pi 0.82+,并已使用 Pi 1.0.3 验证。TypeScript 校验直接使用官方 Pi package 类型,同时只使用这些版本共有的 extension hooks、`getAgentDir()` 和 prompt options;不依赖 Pi 0.83+ 专有 API(例如 `ctx.scopedModels` 或 bundled TypeBox 1.3 aliases)。原生虚拟模型支持与 codemode 嵌套工具调用合并只在会产生它们的 Pi 0.99+ 上生效,较早版本保持原有行为。本地开发基线需要 Node.js 22.19.0 或更高版本,与 Pi 1.0.3 的 engine 要求一致。
|
|
66
66
|
|
|
67
67
|
## 命令
|
|
68
68
|
|
|
@@ -156,9 +156,9 @@ Footer 默认使用 `session`,避免另一个并行 Pi 终端使用相同 prov
|
|
|
156
156
|
|
|
157
157
|
## 按模型关闭 `prompt_cache_key`
|
|
158
158
|
|
|
159
|
-
某些 OpenAI-compatible Completions endpoint 会因 `prompt_cache_key` 返回 HTTP 400,但同一个字段对其他 provider 可能有效。Pi 1.0+ 已负责 Responses/Codex transport 的 key;本扩展的 fallback 和 opt-out 只作用于 `openai-completions`。Pi 1.0.
|
|
159
|
+
某些 OpenAI-compatible Completions endpoint 会因 `prompt_cache_key` 返回 HTTP 400,但同一个字段对其他 provider 可能有效。Pi 1.0+ 已负责 Responses/Codex transport 的 key;本扩展的 fallback 和 opt-out 只作用于 `openai-completions`。Pi 1.0.3 没有原生的 `supportsPromptCacheKey` compat 字段,**不要**把这个未知字段加入 `models.json`。`supportsLongCacheRetention` 也不是等价开关,不应借用来实现此目的。
|
|
160
160
|
|
|
161
|
-
当扩展观察到精确 provider/model 对 `prompt_cache_key`
|
|
161
|
+
当扩展观察到精确 provider/model 对 `prompt_cache_key` 的明确字段级拒绝后(包括 `未知请求字段:prompt_cache_key` 这类已识别的中文错误),普通 `/cache-optimizer fix` 会提供经过确认的模型级修复。参数值校验失败,以及“设置 temperature 时不允许”这类条件限制都不构成证据。若不同模型的响应并发交错,而 Pi 又没有提供 request ID,扩展会忽略无法安全关联的 response-header 证据;只有最终 assistant message 提供精确 provider/model 身份时才恢复归因。如果你已经确定 endpoint 不支持该字段,可以主动执行:
|
|
162
162
|
|
|
163
163
|
```text
|
|
164
164
|
/cache-optimizer fix prompt-cache-key
|
|
@@ -170,7 +170,7 @@ Footer 默认使用 `session`,避免另一个并行 Pi 终端使用相同 prov
|
|
|
170
170
|
|
|
171
171
|
LiteLLM / OneAPI / NewAPI / 类 OpenRouter 渠道等第三方 `openai-completions` 代理,常会把同一个 session 分散到多个上游后端,导致 provider 侧 prompt cache 被拆散。
|
|
172
172
|
|
|
173
|
-
Pi 0.84.1 还修复了内置 Fireworks 渠道对拒绝 `prompt_cache_retention` 的模型兼容性;本扩展不按 provider 名称增加特殊分支,而是结合 `models.json` 与 runtime model,按精确 provider/model 解析有效 compat。Pi 0.81+ 也内置了使用 OpenAI-shaped transport 的 `llama.cpp` provider。本扩展只对第三方 `openai-completions` 保留 session-id key fallback;Pi 1.0+ 已负责 Responses/Codex transport 的 key。只有符合 Pi 内置 provider 明确 compat 指纹的模型会跳过通用 proxy 路由 / session-affinity 建议;仅复用 `llama.cpp` id 的自定义或覆盖 provider 仍按普通 OpenAI-compatible 渠道处理。`prompt_cache_retention` 继续遵循统一安全规则:仅官方 OpenAI 或 `models.json` 中有效配置为 `supportsLongCacheRetention: true` 时保留,否则发送前移除。Pi 1.0.
|
|
173
|
+
Pi 0.84.1 还修复了内置 Fireworks 渠道对拒绝 `prompt_cache_retention` 的模型兼容性;本扩展不按 provider 名称增加特殊分支,而是结合 `models.json` 与 runtime model,按精确 provider/model 解析有效 compat。Pi 0.81+ 也内置了使用 OpenAI-shaped transport 的 `llama.cpp` provider。本扩展只对第三方 `openai-completions` 保留 session-id key fallback;Pi 1.0+ 已负责 Responses/Codex transport 的 key。只有符合 Pi 内置 provider 明确 compat 指纹的模型会跳过通用 proxy 路由 / session-affinity 建议;仅复用 `llama.cpp` id 的自定义或覆盖 provider 仍按普通 OpenAI-compatible 渠道处理。`prompt_cache_retention` 继续遵循统一安全规则:仅官方 OpenAI 或 `models.json` 中有效配置为 `supportsLongCacheRetention: true` 时保留,否则发送前移除。Pi 1.0.3 没有原生的 `supportsPromptCacheKey` compat 字段,因此仅对 `openai-completions` 按模型关闭 key 的策略保存在本扩展的 `pi-cache-optimizer-config.json` 中,而不是 `models.json`。扩展配置独立于 Pi 的 compat 优先级,只影响其中列出的精确 provider/model。
|
|
174
174
|
|
|
175
175
|
对真正的代理,建议先启用 session affinity:
|
|
176
176
|
|
|
@@ -196,7 +196,7 @@ Pi 0.84.1 还修复了内置 Fireworks 渠道对拒绝 `prompt_cache_retention`
|
|
|
196
196
|
|
|
197
197
|
- `sendSessionAffinityHeaders: true` 是安全默认项,前提是你的代理支持 sticky routing。
|
|
198
198
|
- `supportsLongCacheRetention: true` 是可选项。只有 endpoint 明确支持 OpenAI long prompt cache retention 时才添加。
|
|
199
|
-
- 不要把 `supportsPromptCacheKey` 加入 `models.json`:Pi 1.0.
|
|
199
|
+
- 不要把 `supportsPromptCacheKey` 加入 `models.json`:Pi 1.0.3 没有定义这个 compat 字段。请使用 `/cache-optimizer fix prompt-cache-key` 在扩展自有配置中保存精确 provider/model 的 omit 规则;它会移除两种 key 写法,包括 Pi 提供的 key。
|
|
200
200
|
- 如果出现 `400 Unsupported parameter: prompt_cache_retention`,请为该渠道移除 / 避免 `supportsLongCacheRetention`;如支持,可保留 `sendSessionAffinityHeaders`。扩展会从响应头或最终 assistant error message 中识别这条明确错误,并在当前进程的后续请求中移除该参数。
|
|
201
201
|
- 使用 `/cache-optimizer compat` 或 `/cache-optimizer doctor` 查看当前模型的具体建议。
|
|
202
202
|
- DeepSeek 模型名只用于选择 `DS cache` adapter,不能证明 reasoning wire protocol。缺少或使用非 DeepSeek format 时仍保留通用缓存 / 路由建议;只有 effective `compat.thinkingFormat: "deepseek"` 被明确配置时,才显示 DeepSeek replay 建议,且不会把 `thinkingFormat` 列为缺失修复项。
|
|
@@ -353,7 +353,7 @@ Pi Cache Optimizer 按 Pi 的优先级解析有效 compat(`provider.compat`
|
|
|
353
353
|
面向新手的安全流程是分阶段的:
|
|
354
354
|
|
|
355
355
|
1. 先运行 `/cache-optimizer fix`,只处理协议无关的缓存 / 路由修复,例如 session affinity;命令会展示具体位置并要求确认。
|
|
356
|
-
2. 发起一次普通请求。如果 OpenAI-compatible 的 DeepSeek-like 模型明确拒绝 `thinking` 并要求使用 `reasoning_effort
|
|
356
|
+
2. 发起一次普通请求。如果 OpenAI-compatible 的 DeepSeek-like 模型明确拒绝 `thinking` 并要求使用 `reasoning_effort`(包括已识别的中文拒绝和建议文本),扩展只在当前进程保留 model-scoped 分类,不会持久化或显示完整错误,不会发送隐藏探测请求,也不会在 response hook 中自动修改配置。
|
|
357
357
|
3. 再次运行 `/cache-optimizer fix`,查看基于证据的 model-level 协议修复;该修复写入最高优先级的 `modelOverrides[modelId].compat`,并结合 runtime compat 自检,避免 extension-provided model 静默遮挡。不会仅凭共享 provider 或模型名字扩大修改范围,显式 `openai`、`qwen`、`openrouter`、`together` format 会被尊重。
|
|
358
358
|
4. 如果最近一次已确认修复导致问题,运行 `/cache-optimizer rollback`;回滚始终需要 UI 确认。
|
|
359
359
|
|
package/index.ts
CHANGED
|
@@ -197,6 +197,7 @@ export const __internals_for_tests = {
|
|
|
197
197
|
isOpenAISdkHeader403Applicable,
|
|
198
198
|
hasPromptCacheRetentionUnsupportedSignal,
|
|
199
199
|
hasPromptCacheRetentionUnsupportedErrorMessage,
|
|
200
|
+
hasPromptCacheKeyUnsupportedText,
|
|
200
201
|
hasPromptCacheKeyUnsupportedSignal,
|
|
201
202
|
hasPromptCacheKeyUnsupportedErrorMessage,
|
|
202
203
|
isPromptCacheKeyUnsupportedApplicable,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-cache-optimizer",
|
|
3
|
-
"version": "2.8.
|
|
3
|
+
"version": "2.8.20",
|
|
4
4
|
"description": "Improve Pi prompt/KV cache hit rates with stable prompts, OpenAI-compatible cache keys, proxy compat warnings, and footer cache stats.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package",
|
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
"check:modules": "node scripts/check-module-graph.mjs"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
|
-
"@earendil-works/pi-coding-agent": "^1.0.
|
|
41
|
-
"@earendil-works/pi-server": "1.0.
|
|
40
|
+
"@earendil-works/pi-coding-agent": "^1.0.3",
|
|
41
|
+
"@earendil-works/pi-server": "1.0.3",
|
|
42
42
|
"@types/node": "^22.0.0",
|
|
43
43
|
"jiti": "^2.7.0",
|
|
44
44
|
"typescript": "^5.8.3"
|
package/src/provider-errors.ts
CHANGED
|
@@ -84,6 +84,15 @@ export function hasPromptCacheRetentionUnsupportedErrorMessage(message: unknown)
|
|
|
84
84
|
hasPromptCacheRetentionUnsupportedText(record.errorMessage);
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
+
// A Chinese rejection must start a diagnostic clause, not occur inside a
|
|
88
|
+
// negation or condition. Keep comma-separated conditions in the same sentence.
|
|
89
|
+
function hasChineseRejectionContext(value: string, index: number): boolean {
|
|
90
|
+
const prefix = value.slice(0, index).split(/[;!\n。;!]/).at(-1) ?? "";
|
|
91
|
+
const suffix = value.slice(index).split(/[;!\n。;!]/)[0];
|
|
92
|
+
return !/(?:如果|若|当|仅在|只有|模式下|情况下|设置.{0,40}时)/.test(prefix + suffix) &&
|
|
93
|
+
!/(?:并非|并不|并未|不是)/.test(prefix);
|
|
94
|
+
}
|
|
95
|
+
|
|
87
96
|
export function hasPromptCacheKeyUnsupportedText(value: unknown): boolean {
|
|
88
97
|
const normalized = lower(value)
|
|
89
98
|
.replace(/["'`]/g, "")
|
|
@@ -98,11 +107,13 @@ export function hasPromptCacheKeyUnsupportedText(value: unknown): boolean {
|
|
|
98
107
|
// Keep this deliberately grammar-bound. A rejected value or a conditional
|
|
99
108
|
// restriction (for example, "not allowed when temperature is set") is not
|
|
100
109
|
// proof that the endpoint lacks support for the field itself.
|
|
101
|
-
const terminal = String.raw`(?=$|[}\]
|
|
110
|
+
const terminal = String.raw`(?=$|[}\]>,.;,。;])`;
|
|
102
111
|
return (
|
|
103
112
|
new RegExp(String.raw`(?:unsupported|unknown|unrecognized|unexpected)\s+${field}\s*[:=]?\s*${key}${terminal}`).test(normalized) ||
|
|
104
113
|
new RegExp(String.raw`(?:extra\s+inputs?|${field}\s+not\s+(?:allowed|permitted|supported))\s*[:=]\s*${key}${terminal}`).test(normalized) ||
|
|
105
|
-
new RegExp(String.raw`${key}(?:\s+${field})?\s*[:=]?\s*(?:is\s+)?${unsupported}${terminal}`).test(normalized)
|
|
114
|
+
new RegExp(String.raw`${key}(?:\s+${field})?\s*[:=]?\s*(?:is\s+)?${unsupported}${terminal}`).test(normalized) ||
|
|
115
|
+
Array.from(normalized.matchAll(new RegExp(String.raw`(?:^|[^a-z0-9_\u4e00-\u9fff])(?:未知|未识别|不支持|不允许)(?:请求)?(?:字段|参数)\s*[::]\s*${key}${terminal}`, "g")))
|
|
116
|
+
.some((match) => hasChineseRejectionContext(normalized, match.index))
|
|
106
117
|
);
|
|
107
118
|
}
|
|
108
119
|
|
|
@@ -126,6 +137,15 @@ export function hasReasoningProtocolRejectionText(value: unknown): boolean {
|
|
|
126
137
|
/(?:^|[^a-z0-9_])(?:unsupported|unknown|unrecognized|invalid|disallowed|rejected|not\s+(?:a\s+)?valid|not\s+accepted|not\s+allowed|not\s+permitted)(?:[_ ](?:parameter|field|argument))?\s*[:=]?\s*["'`]?thinking["'`]?(?![a-z0-9_])/,
|
|
127
138
|
/(?:^|[^a-z0-9_])(?:extra\s+inputs?|additional\s+(?:inputs?|parameters?))\s+(?:are\s+)?(?:not permitted|not allowed|unsupported)\s*[:=]?\s*["'`]?thinking["'`]?(?![a-z0-9_])/,
|
|
128
139
|
];
|
|
140
|
+
const chineseStart = String.raw`(?:^|[^a-z0-9_\u4e00-\u9fff])`;
|
|
141
|
+
const chineseEnd = String.raw`(?=\s*(?:$|["'\x60}\]>,.;!?,。;!?]))`;
|
|
142
|
+
const chineseRejection = String.raw`(?:未知|未识别|无法识别|不支持|不被支持|不允许|不被允许|不接受|不被接受|无效|不合法|拒绝|被拒绝)`;
|
|
143
|
+
const chineseThinking = String.raw`["'\x60]?thinking["'\x60]?`;
|
|
144
|
+
const chinesePatterns = [
|
|
145
|
+
new RegExp(String.raw`${chineseStart}${chineseRejection}(?:请求)?(?:参数|字段)\s*[::]?\s*${chineseThinking}${chineseEnd}`, "g"),
|
|
146
|
+
new RegExp(String.raw`${chineseStart}${chineseRejection}\s*${chineseThinking}(?:\s*(?:请求)?(?:参数|字段))?${chineseEnd}`, "g"),
|
|
147
|
+
new RegExp(String.raw`${chineseStart}${chineseThinking}\s*(?:(?:请求)?(?:参数|字段)\s*)?${chineseRejection}${chineseEnd}`, "g"),
|
|
148
|
+
];
|
|
129
149
|
let rejectionEnd = -1;
|
|
130
150
|
for (const pattern of thinkingParameterRejectionPatterns) {
|
|
131
151
|
const match = pattern.exec(normalized);
|
|
@@ -133,6 +153,13 @@ export function hasReasoningProtocolRejectionText(value: unknown): boolean {
|
|
|
133
153
|
rejectionEnd = match.index + match[0].length;
|
|
134
154
|
}
|
|
135
155
|
}
|
|
156
|
+
for (const pattern of chinesePatterns) {
|
|
157
|
+
for (const match of normalized.matchAll(pattern)) {
|
|
158
|
+
if (hasChineseRejectionContext(normalized, match.index)) {
|
|
159
|
+
rejectionEnd = Math.max(rejectionEnd, match.index + match[0].length);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
136
163
|
if (rejectionEnd < 0) return false;
|
|
137
164
|
|
|
138
165
|
// The provider must direct the caller to reasoning_effort after the
|
|
@@ -142,7 +169,7 @@ export function hasReasoningProtocolRejectionText(value: unknown): boolean {
|
|
|
142
169
|
const recommendation = normalized.slice(rejectionEnd, rejectionEnd + 260);
|
|
143
170
|
if (!/\breasoning[_\.]effort\b/.test(recommendation)) return false;
|
|
144
171
|
|
|
145
|
-
const recommendationClauses = recommendation.split(/[.;!?\n]/);
|
|
172
|
+
const recommendationClauses = recommendation.split(/[.;!?\n,。;!?]/);
|
|
146
173
|
return recommendationClauses.some((clause) => {
|
|
147
174
|
if (!/\breasoning[_\.]effort\b/.test(clause)) return false;
|
|
148
175
|
// A target mentioned inside a negated/disabled clause is not positive
|
|
@@ -150,7 +177,9 @@ export function hasReasoningProtocolRejectionText(value: unknown): boolean {
|
|
|
150
177
|
if (
|
|
151
178
|
/\b(?:do\s+not|don't|never|avoid)\s+(?:use|set|send|pass|provide)?\s*["'`]?reasoning[_\.]effort\b/.test(clause) ||
|
|
152
179
|
/\breasoning[_\.]effort\b[^.;]{0,80}\b(?:must|should|may|do)\s+(?:not|never)\b/.test(clause) ||
|
|
153
|
-
/\breasoning[_\.]effort\b[^.;]{0,80}\b(?:unsupported|disabled|unavailable|not\s+(?:supported|accepted|allowed|available|enabled|required|recommended|expected))\b/.test(clause)
|
|
180
|
+
/\breasoning[_\.]effort\b[^.;]{0,80}\b(?:unsupported|disabled|unavailable|not\s+(?:supported|accepted|allowed|available|enabled|required|recommended|expected))\b/.test(clause) ||
|
|
181
|
+
/(?:请)?(?:不要|勿|不应|不该|不得|不可|不能|不建议|不推荐|禁止|无需|不必|不需要)\s*(?:再)?(?:使用|设置|发送|传入|提供|改用|采用|把)?\s*(?:参数\s*)?["'`]?reasoning[_\.]effort\b/.test(clause) ||
|
|
182
|
+
/\breasoning[_\.]effort\b[^.;,。;!?]{0,80}(?:不支持|不允许|不可用|不接受|不能|不建议|不推荐|不需要|无需|不必|不得|不应|不该|禁止)/.test(clause)
|
|
154
183
|
) return false;
|
|
155
184
|
|
|
156
185
|
return [
|
|
@@ -159,6 +188,9 @@ export function hasReasoningProtocolRejectionText(value: unknown): boolean {
|
|
|
159
188
|
/(?:parameter|field|option)\s+(?:is|should be)\s+["'`]?reasoning[_\.]effort["'`]?(?![a-z0-9_])/,
|
|
160
189
|
/instead[^.;]{0,120}(?:use|try|set|send|pass|provide)\s+(?:the\s+)?["'`]?reasoning[_\.]effort["'`]?(?![a-z0-9_])/,
|
|
161
190
|
/(?:replace|change|switch)\s+(?:the\s+)?["'`]?thinking["'`]?\s+(?:with|to)\s+["'`]?reasoning[_\.]effort["'`]?(?![a-z0-9_])/,
|
|
191
|
+
/(?:请)?(?:使用|改用|采用|设置|发送|传入|提供|切换到|改为|用)\s*(?:参数\s*)?["'`]?reasoning[_\.]effort["'`]?(?![a-z0-9_])/,
|
|
192
|
+
/(?:将|把)\s*["'`]?thinking["'`]?(?:\s*(?:请求)?参数)?\s*(?:替换为|改为|换成|切换为|替代为)\s*["'`]?reasoning[_\.]effort["'`]?(?![a-z0-9_])/,
|
|
193
|
+
/reasoning[_\.]effort\b[^.;,。;!?]{0,80}(?:必须|必需|应当|应该|推荐|受支持|可用)/,
|
|
162
194
|
].some((pattern) => pattern.test(clause));
|
|
163
195
|
});
|
|
164
196
|
}
|