@verneuil/dsh-ocg-session-head 0.1.3 → 0.1.4

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.
Files changed (3) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/index.js +21 -17
  3. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.4
4
+
5
+ ### 修复
6
+ - 修复请求头监听器的异常边界:下游贡献者抛错时会被本插件二次调用 `next()`,把真实错误改写成 `next() called multiple times`。现在 `next()` 只在 `try` 外调用一次,下游错误原样上浮,自身错误仍 fail-open。
7
+
8
+ ---
9
+ ### Fixes
10
+ - Fixed the listener's error boundary: when a downstream contributor threw, the plugin could call `next()` a second time and replace the real error with `next() called multiple times`. `next()` is now called exactly once outside `try`, downstream errors surface untouched, and the plugin's own failures still fail open.
11
+
3
12
  ## 0.1.3
4
13
 
5
14
  ### 修复
package/index.js CHANGED
@@ -243,24 +243,28 @@ export function apply(ctx, config) {
243
243
  const uuidBySession = new Map()
244
244
 
245
245
  ctx.on('llm-pi-ai/request-headers', (request, headers, next) => {
246
- // 宿主契约要求监听者必须调用 next();任何异常都不允许把整次推理打断,
247
- // 因此在本地逻辑上失败即「放弃注入、原样放行」。
246
+ // 契约要求每个监听者**恰好调用一次** next()。
247
+ // try 只包住「自己的判断与写头」:这里出错就地放弃注入(fail-open),
248
+ // 但不能把下游监听者的异常一起吞掉——那会把别人的真实错误改写成 cordis 的
249
+ // "next() called multiple times",排查时完全失真。
250
+ if (typeof next !== 'function') return headers
248
251
  try {
249
- if (typeof next !== 'function') return headers
250
- if (request === null || typeof request !== 'object') return next()
251
- if (headers === null || typeof headers !== 'object' || typeof headers.set !== 'function') return next()
252
- if (!isOpenCodeRoute(options, request)) return next()
253
- // 已有同名头一律让路:与官方实现、其它插件、静态 headers 配置共存。
254
- if (typeof headers.has === 'function' && headers.has(options.header)) return next()
255
- const value = headerValueFor(options, uuidBySession, request.sessionId)
256
- if (value === undefined) return next()
257
- headers.set(options.header, value)
258
- if (options.debug) {
259
- ctx.logger.info(
260
- `[dsh-ocg-session-head] ${options.header}=${value} `
261
- + `provider=${String(request.provider)} model=${String(request.model)} `
262
- + `purpose=${String(request.purpose ?? 'chat')}`,
263
- )
252
+ if (request !== null && typeof request === 'object'
253
+ && headers !== null && typeof headers === 'object' && typeof headers.set === 'function'
254
+ && isOpenCodeRoute(options, request)
255
+ // 已有同名头一律让路:与官方实现、其它插件、静态 headers 配置共存。
256
+ && !(typeof headers.has === 'function' && headers.has(options.header))) {
257
+ const value = headerValueFor(options, uuidBySession, request.sessionId)
258
+ if (value !== undefined) {
259
+ headers.set(options.header, value)
260
+ if (options.debug) {
261
+ ctx.logger.info(
262
+ `[dsh-ocg-session-head] ${options.header}=${value} `
263
+ + `provider=${String(request.provider)} model=${String(request.model)} `
264
+ + `purpose=${String(request.purpose ?? 'chat')}`,
265
+ )
266
+ }
267
+ }
264
268
  }
265
269
  } catch (error) {
266
270
  ctx.logger.warn(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@verneuil/dsh-ocg-session-head",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "OpenCode Go 会话头:监听宿主 llm-pi-ai/request-headers 瀑布,按会话为 ocg 路由注入 x-opencode-session(不猴补丁 fetch、不修改宿主)。",
5
5
  "main": "index.js",
6
6
  "type": "module",