DeepSeek Harness Plugin Hub

Publish and manage complete Harness Profiles. Discover Plugins for your next setup.

Explore

PluginsPresetsDocsNews

Community

Publish a pluginContactReport an issue

Resources

Plugin Hub on GitHubDeepSeek HarnessSystem statusPrivacy notice
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

Independent and unofficial. Not affiliated with, authorized by, or endorsed by DeepSeek.

Manual Context — DSH Plugin for DeepSeek Harness
DeepSeek Harness Plugin Hub
ProfilesPluginsCategoriesNewsDocsSign inManage Profiles
ProfilesPluginsCategoriesNewsDocsSign in
← Plugins
M

@dsh-external/manual-context

Manual Context

Manual context injection + conversation history editor (DeepSeek Harness plugin)

The plugin will be installed here. Keep web if you are unsure.

npx -y @deepseek-ai/dsh plugin --profile web add github:iii993/dsh-manual-context#77c9d83a5a7f23baa746b1b6e108c46f1ec18cd4
READMECompatibilityVersions

Compatibility and provenance

Manual Context is published as @dsh-external/manual-context and currently resolves to version 0.1.0. The Hub verifies its manifest and preserves the exact installation source for reproducible installs.

DSH compatibility
*
Runtime surfaces
web
Release source
github
Registry updated
9/18/2026

Versions

0.1.0stable
9/18/2026

Related plugins

Loading related plugins…

Latest
0.1.0
DSH
*
HMR
Process restart
Tree shaking
Safe tree shaking not declared
Unpacked size
Unavailable
Files
Unavailable
Surface
web
License
Not declared
Source
github
GitHub
★ 0
Weekly downloads
0
Last push
9/19/2026
View source ↗
README badge

Click the badge to copy Markdown for your README.

Do you maintain this Plugin?Claim benefit · Priority security scan

Verify the GitHub repository declared in package.json to manage this listing. After you claim it, Hub will prioritize a security scan of the current version and publish the result when it passes.

Claim this Plugin →
Report an issue

Related plugins

More verified plugins in memory-context.

Memsearch Dsh@zilliz/memsearch-dshMemSearch plugin for DeepSeek Harness: shared markdown memory across agents, with capture, pre-step context injection, memory-recall skill, and a skill-candidate review panel.Reme@agentscope-ai/remeReMe client and memory integrations for TypeScript agentsStratagate Dshstratagate-dshRecent conversations stay vivid. Older ones fade into summaries, not oblivion. StrataGate gives DeepSeek Harness six-layer, time-decaying memory, while lasting events and relationships settle into a knowledge graph. Bring your memories from other AIs withMeow Memorymeow-memoryCross-session project memory for DeepSeek Harness: seven-layer SQLite memory, first-turn snapshot injection, per-message keyword hits, memory_remember/search/project tools, automatic reflection with reflection-fold UI, and idle-triggered dream consolidati

README

手动上下文编辑器(manual-context)

DeepSeek Harness 插件。它做两件事:

  1. 手动上下文自动注入 —— 自动检测「手动上下文」文件夹里的内容, 每次对话前对照当前上下文,把尚未出现的条目插入到「用户本轮输入」之前、历史上下文之后。
  2. 对话历史编辑 —— 在 Web 里直接编辑历史对话(系统提示词 / 用户输入 / 模型输出 / 工具调用输入输出), 修改状态按会话保存,压缩上下文后依然保留。

1. 手动上下文文件夹

默认扫描两个位置(都会自动创建):

顺序位置用途
1<会话工作区>/manual-context随项目走的上下文
2$DSH_HOME/manual-context(本机为 $DSH_HOME\manual-context)全局上下文

也可以用环境变量 DSH_MANUAL_CONTEXT_DIRS 覆盖(分号分隔的绝对路径)。

文件夹里每个 *.md / *.txt 文件是一个条目,文件名即标题。

新建位置

面板左上角的下拉框决定新条目写进哪个根目录:

选项实际路径作用范围
项目(当前工作区)<会话工作区>/manual-context只对该项目生效
全局(DSH 根目录)$DSH_HOME/manual-context对所有项目生效

也可以不经 UI,直接把 .md / .txt 文件丢进这两个目录,下次对话前就会被扫描到。

新建时可以直接选注入类型(用户输入 / 模型输出 / 工具调用 / 工具返回), 它会写进文件头部的 frontmatter;API 上就是 create-file 的 role 字段。

注入类型(role)

每个条目可以在文件头部用 frontmatter 声明它注入成什么类型的消息,默认是「用户输入」:

---
role: assistant
---
我已经检查过配置文件,没有问题。
role注入方式模型看到的角色
user(默认)合成一条 user 消息插到本轮用户输入之前,不写会话日志user
assistant追加 assistant/messageassistant
tool-call追加 assistant/message,内嵌 tool-call 块assistant
tool-result追加 tool/resultuser(tool-result 块)

可用字段:

字段适用 role说明
role全部user / assistant / tool-call / tool-result
tooltool-call工具名,默认 manual_tool
argstool-call工具参数,JSON 字符串
callIdtool-call / tool-result省略时自动生成;tool-result 省略则按条目顺序与前面最近的未配对 tool-call 配对
isErrortool-resulttrue 时标记为失败的工具结果

surface 只认 system/message / user/message / assistant/message / tool/result 四种消息事件, 所以非 user 类型必须真正写进会话日志;追加发生在 pre-step 之后、本轮用户输入写入之前, 于是模型看到的顺序是「历史上下文 → 模拟的工具/模型消息 → 本轮用户输入」。

在 UI 里选中条目后,用文件名旁边的下拉框即可切换类型,保存时会写回 frontmatter。

两种编辑方式

选中条目后,编辑框上方可以在 文本 与 JSON 之间切换:

方式编辑内容
文本整个文件(含 frontmatter),改完由宿主按 role 同步
JSON结构化字段,保存时由宿主组装 frontmatter

JSON 模式的形状:

{
  "role": "tool-call",
  "tool": "read_file",
  "args": "{\"path\":\"config.json\"}",
  "callId": "",
  "isError": false,
  "body": "我来读取配置文件"
}
  • role 为 user、isError 为 false、空字符串都会被省略,写出的文件与文本模式完全一致;
  • frontmatter 键大小写不敏感:callId / callid / CALL_ID 解析后都归一成 callId;
  • JSON 解析失败或顶层不是对象时会在面板报错,不写文件。

一个文件里混排多种角色(段标记)

文件正文可以用 `` 切成多段,每段各自决定角色:

```markdown 这段没有标记,继承 frontmatter 的 role

请始终用中文回答

好的,我会用中文。

我来读取配置文件

{"port": 3080} ```

规则:

  • 连续的多行标记组成一个「段头」,其后到下一个段头之间的正文属于该段;
  • 段头里可以写 `role` / `tool` / `args` / `callId` / `isError`,段标记优先,其次继承文件级 frontmatter;
  • 没有任何标记时整篇就是一段,老写法完全兼容;
  • 编辑框上方的五个按钮(用户输入 / 模型输出 / 思维链 / 工具调用 / 工具返回)会在光标处插入对应的 ``。

注入时按段展开:同一个文件里 user 段会合并成一条 user 消息, 其余段各自落地成对应角色的真实消息。实例:

```text user │ 看看配置 assistant │ 好的,我会用中文。 ← assistant │ 我来读取配置文件 + [tool-call read_file] ← user │ [tool-result manual-call-…] ← user │ … 请始终用中文回答 ← 两个 user 段合成 user │ 看看配置 ← 本轮真实输入 ```

注入时机与去重

  • 只在每个 turn 的第一个 step(agent/pre-step)检查,也就是「每次对话前」。
  • 判断依据是会话当前的模型可见历史:先看有没有 id 等于 manual-context:<条目 hash> 的消息(非 user 类型靠这个), 再看文本里有没有 <dsh-manual-context file="…" hash="…"> 标记(user 类型,兼容旧版)。
  • 内容变了(hash 变)或条目被压缩掉了,就会重新注入;已经在上下文里就不重复插入。
  • user 类型合成一条 plugin 来源的 user 消息插在用户输入之前;其余类型追加成真实消息事件。

2. 历史编辑

点击会话头部的 「✎ 上下文编辑」 按钮打开面板,第二个标签页列出当前模型可见的全部消息。

编辑一条消息时,插件追加一个带 surfaceOp: { op: 'replace', startSeq, endSeq } 的事件, 遮蔽原节点 —— 这与 Harness 内置压缩使用完全相同的机制,因此:

  • 模型之后的请求立即看到编辑后的内容;
  • 编辑本身是会话日志的一部分,可被压缩、可被 replay;
  • 不需要也不允许写入自定义的事件类型(外部插件事件无法通过持久化读取校验,会造成会话无法重建)。

替换时保留原消息的 role 与 source,只换内容:

目标节点承载事件编辑后的角色
用户输入user/message仍是 user
模型输出user/message(消息的 role 仍为 assistant)仍是 assistant
工具输出user/message(消息里仍是 tool-result 块)仍是 user + tool-result 块,toolCallId 保持不变
系统提示词—不可改写,见下

运行时并不强制「事件类型 == 消息角色」:surface 只要求事件类型可替换, 所以用 user/message 事件承载一条 role: 'assistant' 的消息是合法的, 模型历史里它依然以模型输出出现。

为什么系统提示词改不了:agent-loop 的 SystemPromptProjection 会在每次请求组装时 把 surface 头节点重新写回渲染结果,任何替换下一轮都会被覆盖。 面板里因此不再提供该按钮。想长期生效,请把手动上下文条目的 role 设为 user,它每轮都会注入。

两种编辑方式

编辑框上方可以在 文本 与 JSON 之间切换:

方式内容适合
文本消息的纯文本;工具调用等非文本块自动保留改措辞
JSON直接编辑 content blocks 数组增删工具调用、改工具名与参数、构造精确结构

JSON 模式的 content 必须是数组,保存时按原样写入;角色与 source 仍然保持。 JSON 解析失败会在面板里直接报错,不会写入会话。

保持原位

替换会生成一个新节点(surface 用"遮蔽"而不是"删除"),但:

  • 新节点在 surface 里的位置与原节点相同,模型看到的历史顺序不变;
  • 面板保存后会自动把选中项切到新节点上(接口返回 replacedSeq),列表位置和选中状态都不跳。

删除消息

列表项右侧的 ✕ 可以把一条消息从模型可见上下文里移除;点工具栏的 多选 会出现复选框, 勾选后 删除选中 可批量删除。

实现上是用一条 空内容的 system/message 遮蔽目标节点 —— 空内容不会投影出任何消息 (deriveEventMessage 对空 content 返回 null),从而达到删除效果,且不破坏节点顺序。 surface 第 0 个系统提示词不允许删除。

手动上下文条目同样支持单条 ✕ 删除与多选批量删除。

思维链(reasoning)

模型输出的 `reasoning` 块与正文是分开的,面板会单独展示:

  • 详情里显示「思维链(reasoning 块)」区块;
  • 进入文本编辑态会多出一个思维链输入框,可以单独改写;
  • 只改正文时思维链原样保留(早期版本会把它丢掉,已修);
  • JSON 模式下 `{"type":"reasoning","text":"…"}` 就是普通块,可任意增删。

手动上下文侧,段标记支持 ``,注入成一条带 `reasoning` 块的 assistant 消息。

主对话流不会变(重要)

编辑通过 surface 遮蔽实现:新节点在 surface 里的位置与原节点相同, 但主对话流的消息列表是按原始事件日志渲染的,不应用 surface 遮蔽 (`dsh-client-ui-conversation` 只在重建系统提示词时读 surface)。

视图看到的内容
主对话流原始内容
本面板的历史列表编辑后的内容,也是模型实际看到的
模型请求编辑后的内容

判断改动是否生效,以本面板和模型的实际回答为准,不要看主对话流。

修改状态保存位置

$DSH_HOME/manual-context-edits/<会话ID>.json

按会话保存,记录了每个被编辑节点的 seq、替换节点 seq、原类型与编辑后的文本。 面板上的「已编辑 / 清除标记」即读写这份档案,因此压缩上下文后修改状态不会丢失。

安装 / 启用

插件通过 profile 的 patch 层挂载:

# $DSH_HOME/profiles/web/cordis.patch.yml
- insert:
    - id: manual-context
      name: '@dsh-external/manual-context'

包名需要在 profile 的 node_modules 下可解析。本机用 junction 指向本目录:

New-Item -ItemType Junction \
  -Path "$env:DSH_HOME\profiles\web\node_modules\@dsh-external\manual-context" \
  -Target "<插件目录>"

新增 bundle 需要重启 dsh web 才会进入客户端模块图。

HTTP 接口

浏览器端通过同源路由 /manual-context 与宿主通信:

方法参数作用
GET?op=status&sessionId=目录、条目列表、注入状态、编辑档案
GET?op=file&sessionId=&id=读取单个条目
GET?op=history&sessionId=当前模型可见的历史消息
POST{op:'save-file'} / {op:'create-file', root:0|1} / {op:'delete-file'}条目写操作(root 选根目录)
POST{op:'save-edit', seq, text} / {op:'forget-edit', seq} / {op:'clear-edits'}历史编辑写操作
POST{op:'append-message', kind, text, toolName?, toolInput?, callId?, isError?}追加新消息(kind: user / assistant / tool-call / tool-result)

排查

现象原因处理
面板报 Unexpected end of JSON input宿主没注册路由,响应体为空 —— 通常是插件尚未加载,或 HTTP 服务名写错见下:dsh 注册路由的服务叫 webServer;确认 patch 条目存在后重启 dsh web
面板报 宿主插件未挂载 /manual-context 路由(HTTP 404)同上同上
改了插件源码后页面文案更新了、接口仍 404刷新页面只重读磁盘上的浏览器 bundle,宿主进程里的插件模块不会重载必须重启 dsh web 进程(Ctrl+C 后重新运行),不是刷新页面
条目全部显示「未注入」该会话没有工作区(cwd),只扫描到了 $DSH_HOME/manual-context在项目目录里开会话
编辑历史时提示「已被压缩」目标节点已不在当前 surface 上属预期:被压缩掉的消息无法再被替换

注意:dsh 0.1.6 注册 HTTP 路由的服务名是 ctx.webServer(@deepseek-ai/dsh-host-webserver)。 代码里若写 ctx.inject(['httpServer', …]),回调永远不会执行且没有任何报错,表现为路由 404。

开发

无需构建步骤:宿主与浏览器端都是可直接运行的 ES 模块/CommonJS bundle。

node --check src/index.js          # 逐文件语法检查
node --test tests/store.test.mjs tests/host.test.mjs

文件

文件职责
src/index.js插件入口,挂载注入钩子与 HTTP 路由
src/store.js手动上下文文件夹的发现、创建与读写
src/inject.jsagent/pre-step 注入
src/history.jssurface 替换编辑与按会话的修改状态存储
src/http.js/manual-context 路由
src/client.js浏览器端面板(window.__ModuleLoader__ bundle)
src/freeze.js消息冻结与文本/工具调用提取