npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@karoc/dsh-smoothly-opencode-session

v0.2.1

Published

Smoothly OpenCode Session (Smoothly OCS) — 思磨力 OpenCode 会话头: external DeepSeek Harness host plugin that attaches the OpenCode-required x-opencode-session header to model calls routed to OpenCode / OpenCode Go provider routes (stable per-conversation id; f

Downloads

846

Readme

思磨力 OpenCode 会话头(Smoothly OCS)

Smoothly OpenCode Session (Smoothly OCS) — 一个外部 DeepSeek Harness (DSH) 宿主插件:为路由到 OpenCode / OpenCode Go 提供方的模型请求自动附加 OpenCode 要求的 x-opencode-session 请求头,取值是稳定的按会话 id。

自 2026-09-05 起,OpenCode 的中继会拒绝任何缺少该头的推理请求 (400 MissingSessionID);该值同时把一段会话固定到同一上游后端,并让 OpenCode 的提示词缓存在该会话各轮之间保持命中(上游跟踪见 deepseek-harness discussion #5495)。

它做什么

  • 修掉 400:凡是路由到允许 host 上的 OpenCode(Go) 提供方的请求,一律带上 x-opencode-session(由 host 门控判定,无需配置提供方列表)。
  • 保住缓存/亲和收益:取值按会话唯一、且在该会话各轮、压缩、重试与进程重启 之间保持稳定(默认直接复用 DSH 会话 id——官方 DeepSeek 适配器已作为 x-deepseek-harness-session-id 发送的同一个身份)。
  • 其余一概不动:初始 URL 不在允许主机内的请求永不被修改(host 门控,默认 https://opencode.ai);已自带该头的请求、以及没有会话 id 的调用同样原样放行。 提供方是按目标 host 覆盖的、不是按名字,所以要把注入限制在特定路由上,需要显式写 providers 列表。见 hosts 与 providers。

工作原理

插件监听 llm/stream 瀑布——一个文档化的 DSH 扩展缝("围绕每次流式模型调用的 Waterfall")。LOOP 构建的请求 options 是深度冻结的(改写即抛错),所以不能靠改写 options 加头;插件改为:

  1. 从瀑布 options 上读取 provider + sessionId;
  2. 把下游流的每次 pull 放进一个 AsyncLocalStorage store 里执行;
  3. 一次性 patch globalThis.fetch,当有 store 处于激活时,把 x-opencode-session: <值> 合入出站请求(除非请求已自带该头——已有值永远优先)。

两处注册都是 fiber 作用域的(ctx.on 监听 + ctx.effect 清理函数),因此 停止 / 更新 / 卸载插件时会恢复原始 fetch 并移除监听。

为什么在 fetch 层注入

外部插件没有任何官方缝能给适配器请求逐条加请求头(options 深度冻结;provider 的 headers 配置是静态的、归属部署方)。fetch shim 是外部插件唯一能附加按会话值的 机制。正确的长期修复在提供方适配器本身(pi-ai);本插件只是它上线前的过渡方案。见 说明 / 限制。

配置

行的 config(写在插件的 cordis.patch.yml,或按 profile 覆盖)全部可选—— 缺失的键由代码填默认值。

- insert:
    - id: dsh-smoothly-opencode-session
      name: '@karoc/dsh-smoothly-opencode-session'
      config:
        # providers: [opencode, opencode-go]  # 可选收窄;不写 = 由 host 门控决定
        mode: session-id
        debug: false

providers

可选收窄——通常你根本不需要配这一项。 权威判据是请求的目标 host(见 hosts):不设 providers 时,凡目标 host 通过门控的提供方都被覆盖,因此自定义 路由键(例如 opencode-go-self)无需登记,被改名也不会静默失效。只有想把注入限制在 特定路由键上时才设它(届时 pi-ai 目录 id opencode / opencode-go 只是两个普通条目)。 匹配用的是路由键——提供方的显示名(例如界面上的 "OC Go" 标签)在这里永远看不到。设了列表 时,插件会在第一次模型调用把列表与实际注册的路由比对,缺哪个就告警一次(配置了 debugFile 时同样写入该文件——服务化部署可能不捕获控制台)。/ocgo 命令会打印生效策略 (门控 / 收窄 / mode / 已注册路由),无需任何客户端界面。

hosts

host 门控:只有目标主机在允许列表内(默认 ['https://opencode.ai'],含子域)的请求 才会被修改。条目可写 host(默认按 https 处理)或 scheme://host[:port];开头的 *. 会被忽略;IDN 条目会规范化为 punycode;不可用条目会在启动日志里报告而不是被 静默忽略,trim 后为空的条目不视为已提供——最终没有任何可用条目时,回到上面的默认 规则。['*'] 完全关闭门控——只对完全信任的镜像使用。如果你通过反向代理或镜像 访问 OpenCode,必须把该主机写进来(写全 scheme;裸 host 条目意味着 https), 否则头会静默不加;插件会按「提供方/host」对被挡下的情况各告警一次。

mode

  • session-id(默认)——头值 = 该次模型调用的 DSH 会话 id。每会话唯一, 跨轮次 / 压缩 / 重试 / 重启稳定。
  • uuid——按 DSH 会话 id 派生的进程内稳定随机 UUID(不透明;进程重启后重置)。

debug / debugFile

  • debug: true——把每个进入注入流程的流式调用经 ctx.logger(dsh 进程控制台) 打日志,并在请求级记录里显示原始值。
  • debugFile: <绝对路径>——每次流式调用追加一行 JSON(kind: "stream",含 provider/model/session/value);每个被注入或被 host 门控挡下的请求也各追加 一行(kind: "inject" | "skip",只要配了该文件就会写;debugRequests 加的是控制台 那行,不是文件记录)。配置了但没有任何适配器注册的路由键会追加一条 kind: "diagnostic" 记录(见 providers)。流级记录只表示 "进入了注入流程",只有请求级记录能证明实际是否带上了头。流级记录携带原始 会话 id 与值(沿用 0.1.0 的格式以兼容),默认哈希的只有请求级记录。 该文件只追加、 不轮转(一次被注入的调用写两条:流级一条、请求级一条),且是 fire-and-forget—— 短命进程可能丢尾部记录。

debugRequests

debugRequests: true 在真实 fetch 时刻经 ctx.logger(dsh 进程控制台)为每条 请求级记录打一行日志;记录本身在配置了 debugFile 时追加进该文件(见上)。记录的 reason 取 session / discovery / host-not-allowed / already-present。被注入的 记录携带 {"ts","kind","reason","host","provider","valueHash","valueLen"};skip 记录只描述请求、不含指纹(ts/kind/reason/host/provider,URL 无法解析时没有 host),discovery 记录没有 provider(纯发现请求不属于任何路由)。值默认哈希: 只写值的 12 位十六进制 SHA-256 前缀;只有同时开 debug: true 才写原始值。 (上面单独说明的流级记录仍保留原始会话 id——见其注记。)

discoveryFallback

discoveryFallback: true(默认关)会为一个没有会话 id 的纯发现请求附加 进程内稳定 UUID:仅限 GET 且路径以 /models 结尾、且 host 通过门控的请求。 今天的 Models 页列表不需要它;只有当你的 OpenCode 端点开始拒绝该列表时才开启。

想在不改本包的情况下按 profile 覆盖配置:在 profile 自己的 cordis.patch.yml 里加一条 同 id 的 patch 条目(它整体替换 config,所以需要的键都要重写)。patch 条目用 id-targeted 形式,不是 insert——见 安装。

安装

兼容性: 本插件所需 seam(llm/stream、GenerateOptions.sessionId、commands 服务)最早出现的 dsh 版本是 0.1.0-rc.7——这就是声明的最低版本,依据是 seam 可用性,而不是对中间每个版本都跑过测试。该下限声明为对 @deepseek-ai/dsh-llm: ">=0.1.0-rc.7" 的可选 peer 依赖,DSH 会拿它对照自身运行时版本:不在区间内的运行时会拒绝加载——跳过该插件层,并打印 dsh plugin allow-version 的具体解法。这项检查本身自 dsh 0.1.7-rc.1 起才有,而所有带它的版本都已满足本下限,所以这条声明目前是写明契约而不是强制拦截;早于 0.1.7-rc.1 的 dsh 会照常加载本插件。peer 标记为 peerDependenciesMeta.optional,因为 dsh-llm 由宿主在运行时提供,npm 不会额外安装任何东西。区间里显式写出预发布号(>=0.1.0-rc.7 而非 >=0.1.0)是刻意的:面向正式版的区间不会匹配预发布运行时。

从 npm 安装(推荐)

dsh plugin --profile web add @karoc/dsh-smoothly-opencode-session

然后完全重启 dsh profile(bundle 层启动时才读取)。启动日志应出现:

[dsh-smoothly-opencode-session] active with mode session-id; provider narrowing: (none — the host gate decides)
[dsh-smoothly-opencode-session] host gate: https://opencode.ai

如果你从源码 checkout 运行 dsh,也可以作为 overlay 加载: pnpm dsh web --patch ./cordis.patch.yml。

从 git 安装

dsh plugin --profile web add git+https://github.com/karoc/dsh-smoothly-opencode-session.git

更新

dsh plugin --profile web update @karoc/dsh-smoothly-opencode-session

之后重启 dsh web。

卸载

dsh plugin --profile web remove @karoc/dsh-smoothly-opencode-session

之后重启 dsh web。卸载是安全的:卸载时恢复原始 fetch,不影响其他提供方。

目录结构

src/index.ts            宿主插件:llm/stream 监听 + fetch shim
cordis.patch.yml        bundle 层(插入带默认配置的插件行)
scripts/                发布门禁 + 发布后校验
tests/                  node --test 单元测试 + fake cordis 集成测试
lib/                    构建产物(npm 包入口)

构建与测试

npm install       # 安装开发依赖(tsdown、@deepseek-ai/cordis 类型、@types/node)
npm run bundle    # 产出 lib/index.js
npm test          # node --test tests/*.test.ts(直接运行 TypeScript)+ 负向保证门禁

pnpm 同样可用(pnpm bundle、pnpm test);本仓库文档写 npm 路径,因为 pnpm 不总在 PATH 上。

说明 / 限制

  • 范围:只有在 llm/stream 调用内发出的请求会收到该头——判定依据是这个上下文, 不是 URL 路径。Models 页使用的一次性模型列表(GET <baseURL>/models)发生在该上下文之外, 因此默认不会收到该头(除非开启 discoveryFallback)。
  • 重定向不再过门控:门控判定的是初始请求 URL。Node 的 fetch 会跟随重定向,且 (在 Node 24 实测)跨 origin 保留自定义头——因此从允许主机开始、再跳到别处的请求, 会把该头带到重定向目标。
  • 实现依赖:注入依赖 Node 的全局 fetch。如果未来某个 DSH 版本换掉网络栈, 该头会静默不再发送(400 复现)——届时卸载即可。这是提供方适配器(pi-ai)自身 发送该头之前的过渡方案。
  • 不是官方修复:DSH 维护者的立场是提供方特殊性应归 pi-ai 包处理(见 discussion #5495 与 earendil-works/pi #9326)。本插件是它上线前的过渡方案——移除前请先走下面的 退役流程。
  • 发现探测默认不受影响(没有会话 id 的请求原样放行)。

退役(可核验流程)

不要凭感觉退役本插件,按顺序核验:

  1. 读 DSH 实际加载的版本——pnpm 严格布局下真实路径是 <dsh 根>/packages/llm/llm-pi-ai/node_modules/@earendil-works/pi-ai/package.json (扁平布局 <dsh 根>/node_modules/@earendil-works/pi-ai/package.json 是备选;该包 不导出 package.json,所以 require.resolve 找不到它)。定位不到就保持插件, 等下次 DSH 升级后再查。
  2. 若该版本 dist/ 里含 x-opencode-session (grep -rl x-opencode-session <该包>/dist),判断它的注入是按提供方 id (opencode / opencode-go)还是按 base URL(opencode.ai)触发。
  3. 结局:按 base URL → 本插件已冗余,卸载;只按提供方 id → 自定义路由 opencode-go-self 仍不被覆盖,要么继续用本插件,要么先把该路由迁到内置 opencode-go。
  4. 没有新版本 / 仍未命中 → 继续用本插件;等 DSH 升了 @earendil-works/pi-ai 依赖后 重跑本流程(npm view "@earendil-works/pi-ai@<声明的范围>" version 可查该范围允许的 最新版本)。

许可证

MIT

参与贡献

见 CONTRIBUTING.md。