DeepSeek Harness plugin

dsh-neoforge

NeoForge-style standard API layer for DeepSeek Harness plugins: runtime mixins with snapshot/restore + a Cordis-native event bus

Jump to install

Source facts

Repository
r05En1cU/dsh-neoforge
Latest update
Aug 16, 2026
Category
Tools & Capabilities
GitHub stars
3
Format
plugin
Catalog evidence
Upstream dsh.bundle evidence
Evidence path
package.json#dsh.bundle
Checked against
0.1.0-rc.8
Upstream check date
2026-08-20

This evidence comes from the upstream catalog. This site has not installed, run, or security-reviewed the plugin.

Install

Start with a prompt that asks an agent to review the GitHub repository and source. Switch to the command if you want to install it yourself.

Copy this prompt into DSH, Codex, or another agent and ask it to review the GitHub repository and source first.

Do not install or run any commands yet. Read this plugin's GitHub repository, README, and relevant source code. Then answer the questions below clearly and directly so I can decide whether it fits my needs:

1. What is this plugin, and what problem does it solve?
2. Who is it for, and what are its typical use cases?
3. How is it used after installation? Include one minimal example.
4. What known limitations or privacy, security, compatibility, or maintenance risks does it have?
5. Give a clear recommendation: recommend, conditionally recommend, or do not recommend, with reasons.

Distinguish statements documented by the repository, inferences from source code, and unknowns. If evidence is insufficient, say so explicitly. Do not guess or simply repeat the README.

GitHub: https://github.com/r05En1cU/dsh-neoforge
Plugin: dsh-neoforge
Author: r05En1cU

Check the source files

Read the README and other files from this plugin directory before installing.

File explorer3 files
README.mdSource · read only

dsh-neoforge

面向 DeepSeek Harness(DSH)插件开发的类 NeoForge 标准 API 层

  • 语义化 source,先 seam 后 mixin:catalog 作者声明 event / service / view / mixin,后端自动选择;官方已有事件或服务方法时零补丁。
  • Mixin 是可选子层dsh-neoforge/mixin 通过 createMixinLayer() 挂载;运行期解析目标、保留旧快照、执行修改后的包装,卸载时恢复旧快照。
  • 运行期目标全局独占:同一目标被多个第三方包 patch 时直接 loud error,不做隐式链式叠加。
  • 事件总线复用官方 HMRctx.on('vendor/action', handler) / ctx.neoforge.on(...) 就是官方 Cordis 事件注册,fiber 卸载自动回收 listener。
语义 source
  ├─ event     → 官方事件别名(零补丁)
  ├─ service   → internal/service + 原型快照/恢复
  ├─ view      → internal/get 消费方视图
  ├─ mixin     → 运行期 resolve → descriptor 快照 → wrapper → 恢复
                    │
                    ▼
            {id}/before (ctx.bail) + {id} (ctx.emit)
                    │
                    ▼
        社区插件 ctx.on('vendor/action', …)

dsh plugin add 相容

dsh-neoforge 现在同时是库和 bundle carrier:

dsh plugin --profile web add github:r05En1cU/dsh-neoforge
  • 安装后注入一个默认禁用的 dsh-neoforge 行;
  • 默认不 mount,不会作为 plugin 启动;
  • 其他插件可以直接 import from 'dsh-neoforge'
  • 如果宿主想挂载基础服务,可在 profile overlay 启用:
- id: dsh-neoforge
  disabled: false

启用后根入口作为标准 function plugin 执行,等价于调用一次 getNeoForge(ctx),挂载 ctx.neoforge

快速开始

1. catalog 作者:语义 source + 稳定事件

import { defineCatalog, defineEventPoint } from 'dsh-neoforge'
import type { NeoForgeEvent } from 'dsh-neoforge'

declare module '@deepseek-ai/cordis' {
  interface Events {
    'agent-preset/switch'(event: NeoForgeEvent<{ to: string }>): void
    'agent-preset/switch/before'(event: NeoForgeEvent<{ to: string }>): void
  }
}

export default defineCatalog({
  plugin: '@deepseek-ai/dsh-agent',
  versionRange: '>=0.0.0-0',          // DSH 全系 rc:不能用 '^x'(不匹配预发布)
  points: [
    defineEventPoint({
      id: 'agent-preset/switch',
      requires: 'mutate',
      source: {
        kind: 'mixin',
        target: {
          module: '@deepseek-ai/dsh-agent',
          versionRange: '>=0.0.0-0',
          filePath: 'lib/index.js',
          functionQuery: { className: 'AgentPresets', methodName: 'recompose', kind: 'Method' },
        },
        operation: 'around',
      },
      map: {
        toEvent: (args) => ({ to: args[0] }),
        applyEvent: (payload, args) => { args[0] = payload.to },
      },
    }),
  ],
})

2. 装配 catalog

import { createNeoForge } from 'dsh-neoforge'
import { createMixinLayer } from 'dsh-neoforge/mixin'
import agentCatalog from './catalogs/agent.ts'

// catalog 含 source.kind === 'mixin' 时,必须先挂可选 mixin 层
ctx.plugin(createMixinLayer())
ctx.plugin(createNeoForge(agentCatalog))

3. 社区插件:零 mixin 概念

export const name = 'my-preset-logger'

export function apply(ctx) {
  ctx.on('agent-preset/switch/before', (event) => {
    event.payload.to = 'code'
  })
  ctx.on('agent-preset/switch', (event) => {
    console.log('switched to', event.result)
  })
}

运行期 Mixin:快照 → 修改后运行 → 恢复

每个 runtime-mixin 注册都执行:

1. Object.getOwnPropertyDescriptor(holder, key) 保存精确旧快照; 2. Object.defineProperty(holder, key, { ...snapshot, value: wrapper }); 3. 调用经 wrapper 执行 Advice 语义; 4. fiber 卸载时恢复旧快照 descriptor。

冲突策略:目标 (holder, key) 运行期全局独占。第二个第三方包尝试 patch 同一目标时注册直接抛错:

neoforge: runtime mixin "b" conflicts with "a" on Object.helper —
a runtime patch target is exclusive

同一 mixin id 的同 owner 重注册视为 HMR/重放,卸载后目标恢复可再次注册。

运行期 Mixin 能做什么

目标支持机制
CJS exports.helper / 对象属性函数保存 descriptor,替换为 wrapper
class 实例方法 ChatService.prototype._sendclassName + methodName 定位 prototype,现有实例立即生效
ESM class export 的实例方法namespace 绑定只读,但 class.prototype 可变
尚未加载模块里的 class 方法监听官方 internal/service,服务注册时补丁
ESM named export 模块级函数unavailablenamespace 绑定运行期不可写
#private、闭包、astQueryunavailable运行期原理性不可达

不可达目标不会静默假装成功:ctx.neoforge.status() 明确报告 bound / pending / missing / unavailable / stale

Advice:唯一拦截原语

before / after / around / replace 全部编译为同一个 around 形态:

type OperationPhases = {
  before?(call): void
  after?(call): unknown
  around?(call, proceed): unknown
}

事件后端和裸 ctx.mixinLayer.register 后端共享这一个操作分发器,因此 async settle、host policy、payload 映射只实现一次。

事件语义

织入 operation{id}/beforectx.bail{id}ctx.emit
before可改 event.args
afterevent.result 可改并回流
around可改参;event.veto = true 跳过原方法settle 后携带 event.result
replace完全接管;event.invoke() 才执行原方法

source: { kind: 'event' } 是纯观察别名,只有 {id},没有写回能力。

破坏性更新影响最小化

  • 稳定事件面:事件名是 catalog 的公共契约,官方方法改名/改签名只改 catalog。
  • 版本治理target.versionRange + 自动读取目标包 package.json(或注入 readVersion)。
  • 契约测试contractSuite(catalog, harness) —— 一次安装、一次调用、断言事件恰好一次。
  • 默认观察、显式写入requires: 'mutate' | 'replace' 是 review-listed 能力;宿主可 ctx.intercept('neoforge', { allowMutate: false }) 降级为只读。

模块级函数 mixin:自定义事件层

functionName / expressionName 类型的 mixin source 会自动路由到 module-mixin 后端,它专门消费以下标准 Cordis 事件:

事件语义
neoforge/module/load模块 handle 首次可用 → 解析并 patch
neoforge/module/reload重新求值产生新 exports holder → 退役旧快照、patch 新 holder
neoforge/module/unload模块句柄失效 → 恢复当前快照,回到 pending

宿主 / loader / bundle 刷新器只需发布:

import { trackModule, reloadModule, untrackModule } from 'dsh-neoforge'

trackModule(ctx, {
  id: '@pkg/lib/index.js',      // 与 mixin target 的 module/filePath 对应
  module: '@pkg',
  filePath: 'lib/index.js',
  exports: cjsExports,          // 可变 exports holder
  version: '1.2.0',
})

// HMR/重导入后
reloadModule(ctx, { ...same, exports: freshExports })

// 卸载
untrackModule(ctx, '@pkg/lib/index.js')

事件派发是同步的,因此 reload 完成后旧 holder 已恢复、新 holder 已 patch。该层只对运行期可写的 CJS exports / class prototype 有效;ESM named export 绑定应改用官方事件或 service seam。

HMR 语义

  • 下游监听器:官方 ctx.on,loader 卸载旧 fiber 时自动回收。
  • catalog/neoforge 插件自身:注册是 ctx.effect;卸载恢复快照,重载重新注册。
  • service 类目标:完整代际 HMR。internal/service 同步通知,新类 prototype 在同一窗口内完成 retire(old) → attach(new)
  • 模块级 CJS 目标:无官方“模块被重新求值”事件,运行期无法自动感知;getNeoForgeStatus(ctx) / status() 会重新解析已绑定目标,发现新 exports holder 后自动退役旧快照、补丁新 holder。
  • ESM named export / #private / 闭包:运行期不可达;dsh-neoforge 不再内置加载期桥,请改用官方事件、service seam,或让目标模块暴露可变句柄。

服务与治理

NeoForgeService 是标准 Cordis 服务(ctx.neoforge):

ctx.intercept('neoforge', { deny: ['vendor/unsafe-point'] })
ctx.intercept('neoforge', { allowMutate: false })

ctx.neoforge.register(catalog)         // fiber-scoped 注册
ctx.mixinLayer.register(mixin, h)      // 裸 mixin 运行期注册
ctx.neoforge.status()                  // 每个注入点的 source/后端/绑定/漂移诊断
ctx.neoforge.on(name, listener)        // = ctx.on,官方 HMR 事件路径

旧 catalog 的 tier/runtime/mixin 字段会 normalize 为语义 source,现有声明无需迁移。

统一 UI 服务:page → layer → slot → component

dsh-neoforge/ui 是一个纯 Cordis、无 Node builtin 的渲染无关 UI 层。插件只需 inject: ['ui']

const store = ctx.ui.state({
  id: 'feed',
  init: () => ({ items: [] }),
  actions: {
    push(draft, item) { draft.items.push(item) },
  },
})

ctx.ui.page({ id: 'workspace', title: 'Workspace' })
ctx.ui.layer({ id: 'webui', kind: 'react-dom' })

ctx.ui.slot({ id: 'workspace.sidebar', page: 'workspace' })
ctx.ui.component({
  id: 'feed-panel',
  slot: 'workspace.sidebar',
  title: 'Feed',
  state: store,
  render: (h) => h('view', { direction: 'column' }, [
    h('text', { value: `items: ${store.getSnapshot().items.length}` }),
    h('button', { label: 'Refresh' }),
  ]),
})
  • component:返回统一 vnode,不直接依赖 React/Ink/RN;
  • stategetSnapshot / subscribe / select / actions,adapter 各自绑定框架;
  • adapter:webui adapter 把 vnode 转成 React 组件并注册到 ctx.slots;tui adapter 把 vnode 投影成文本 panel;
  • 组件注册、store、layer/slot 都是 fiber effect,HMR 自动回收。

内置 adapter:

import { createUiKit, webuiSlotsAdapter, tuiAdapter } from 'dsh-neoforge/ui'

ctx.plugin(createUiKit({
  adapters: [
    webuiSlotsAdapter({ createElement: React.createElement }),
    tuiAdapter(),
  ],
}))
  • tuiPanelAdapter():注册到 CodeWhale 风格的 registerPanel surface;
  • tuiOverlayAdapter():注册到官方 dsh/cc-tui 的 openOverlay surface;
  • tuiAdapter() / codewhaleTuiAdapter:自动选择上述两种 TUI surface。

dsh-neoforge/ui 同时内置了迁移自 CodeWhale 的 TUI 表面:

import { createTui } from 'dsh-neoforge/ui'

ctx.plugin(createTui({ placement: 'top', panel: 'tasks' }))

ctx.tui.registerPanel({
  id: 'neoforge.status',
  title: 'neoforge',
  lines: () => ctx.neoforge.status().map((row) => `${row.id}: ${row.mounted.join(',')}`),
})

ctx.tui.setWorkSurface({
  panel: 'tasks',
  placement: 'top',
  rows: [
    { id: 'patch', label: 'runtime mixin', status: 'done', tone: 'success' },
    { id: 'tui', label: 'migrate CodeWhale TUI', status: 'running', tone: 'live' },
  ],
})

ctx.tui.render({ width: 80, height: 24 }) // 确定性文本快照

createTui 是幂等插件;ctx.tui 支持 registerPanel / openOverlay / setChrome / render,panel/overlay 都随调用 fiber 自动回收。createCodewhaleTui 是迁移别名。

Node 侧零依赖 ANSI host:

import { createTuiHost } from 'dsh-neoforge/tui-host'

ctx.plugin(createUiKit({ adapters: [tuiAdapter()] }))
ctx.plugin(createTui())
ctx.plugin(createTuiHost())
// q / ctrl+c 发出 'tui/host/exit-requested',launcher 负责 shutdown

GUI/React Native 可以用同一套 SurfaceAdapter 约定接自己的 service。

WebUI / TUI:事件跨树

  • TUI(cc-tui):Node 同树场景直接 ctx.on,无需额外层;组件注入仅在目标运行期可达时使用 mixin
  • WebUI:浏览器是另一棵 Cordis 树,使用两个新入口:
// host 侧:把最新事件发布到官方 webserver exact route
import { createNeoForgeRelay } from 'dsh-neoforge'

ctx.plugin(createNeoForgeRelay({
  path: '/neoforge/snapshot',
  points: ['agent-preset/switch'],
}))
// browser 侧:dsh-neoforge/client 轮询 relay 并 re-emit 同名 neoforge 事件
import { createNeoForgeClient } from 'dsh-neoforge/client'

ctx.plugin(createNeoForgeClient({
  route: '/neoforge/snapshot',
  points: ['agent-preset/switch'],
  interval: 1500,
}))

createNeoForgeClient 是浏览器安全入口,不 import 任何 Node builtin;事件到达浏览器树后,UI 注册仍走官方 ctx.slots / ctx.command,neoforge 只负责事件语义跨树。

开发

pnpm install         # 同时执行 prepare 构建 dist/
pnpm run typecheck   # tsc strict
pnpm test            # 64 项:Advice + source + runtime/module mixin + WebUI relay/client + ctx.ui + CodeWhale TUI + HMR + policy
pnpm run build       # dist/ ESM + d.ts

要求 Node ≥ 22.19;ESM class 运行期补丁依赖当前 Node 的同步 require(esm)(Node 24 默认启用)。架构决策见 [docs/architecture.md](docs/architecture.md),完整调用文档见 [docs/usage.md](docs/usage.md),迁移技能见 [skills/dsh-neoforge-migrate/SKILL.md](skills/dsh-neoforge-migrate/SKILL.md)。