dsh-semble 2.0.0
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/LICENSE +21 -0
- package/README.md +212 -0
- package/README.zh-CN.md +198 -0
- package/cordis.patch.yml +48 -0
- package/icon.svg +8 -0
- package/lib/index.js +75 -0
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +52 -0
- package/skills/semble/SKILL.md +65 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Liu Kai
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
# dsh-semble
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/dsh-semble)
|
|
4
|
+
|
|
5
|
+
> Semantic code search for DeepSeek Harness.
|
|
6
|
+
>
|
|
7
|
+
> Ask **where** something lives instead of recalling **what** it is called, and the agent finds the
|
|
8
|
+
> file, reads it, then edits.
|
|
9
|
+
|
|
10
|
+
English | [简体中文](README.zh-CN.md)
|
|
11
|
+
|
|
12
|
+
`dsh-semble` brings [Semble](https://github.com/MinishLab/semble)'s code index into every DSH
|
|
13
|
+
session as two native MCP tools. `grep` needs a string you already know; this needs a description of
|
|
14
|
+
behaviour — "where is the retry policy applied when a request fails", "which module decides the
|
|
15
|
+
scoring weights". That is usually the moment an agent starts guessing file names.
|
|
16
|
+
|
|
17
|
+
Nothing to learn beyond that: after installation the tools sit next to `read` and `grep`, and the
|
|
18
|
+
agent decides when the index is worth a call.
|
|
19
|
+
|
|
20
|
+
## What you get
|
|
21
|
+
|
|
22
|
+
| Tool | Hand it | Back comes |
|
|
23
|
+
| --- | --- | --- |
|
|
24
|
+
| `mcp__semble__search` | a sentence describing the code or where it lives | ranked `file:line` hits with snippets |
|
|
25
|
+
| `mcp__semble__find_related` | one location you already know | its neighbours: other implementations, callers, tests |
|
|
26
|
+
|
|
27
|
+
A typical exchange:
|
|
28
|
+
|
|
29
|
+
> **You:** Where does DSH decide that a plugin is "loaded"?
|
|
30
|
+
>
|
|
31
|
+
> **Agent:** calls `search`, gets a hit in the plugin inventory, opens it with `read`, finds
|
|
32
|
+
> `isEntryLoaded` comparing loader entry names against the package name, and answers from the source
|
|
33
|
+
> rather than from a guess.
|
|
34
|
+
|
|
35
|
+
## Using the tools
|
|
36
|
+
|
|
37
|
+
- `repo` — **required**. Absolute path of the repository, or an `https://` git URL. A list searches
|
|
38
|
+
several repositories at once.
|
|
39
|
+
- `top_k` — default 5. Raise to 10–20 when the first pass misses.
|
|
40
|
+
- `max_snippet_lines` — default 10; `0` returns locations only.
|
|
41
|
+
- `content` — `code` (default), `docs`, `config`, or `all`.
|
|
42
|
+
|
|
43
|
+
The first query against a repository builds its index (slow, one-time); later queries reuse it.
|
|
44
|
+
Hits are ranked by similarity, so a score near `0.0x` usually means "nothing relevant here" rather
|
|
45
|
+
than "the best answer".
|
|
46
|
+
|
|
47
|
+
## Install
|
|
48
|
+
|
|
49
|
+
### Desktop app
|
|
50
|
+
|
|
51
|
+
**Settings → Plugins → Install**, and paste:
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
dsh-semble
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Pin a version with `dsh-semble@2.0.0`. The settings page is the only supported route for the
|
|
58
|
+
`desktop` profile — the CLI refuses it because the Electron app owns that profile's `node_modules`
|
|
59
|
+
and lockfile.
|
|
60
|
+
|
|
61
|
+
### CLI
|
|
62
|
+
|
|
63
|
+
```sh
|
|
64
|
+
dsh plugin --profile web add dsh-semble
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
The subcommand runs `pnpm add` inside the profile and reconciles `dsh.profile.bundles`, so the bundle
|
|
68
|
+
mounts on the next start. There is no build step, so pnpm needs no `allowBuilds` exemption.
|
|
69
|
+
|
|
70
|
+
### From source
|
|
71
|
+
|
|
72
|
+
To track `main`, a fork, or an unreleased commit, install from the repository instead:
|
|
73
|
+
|
|
74
|
+
```sh
|
|
75
|
+
dsh plugin --profile web add github:CodeIntegrity/dsh-semble
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
`github:owner/repo`, `git+https://…`, `https://github.com/owner/repo` and `.tgz` URLs are accepted;
|
|
79
|
+
these need `git` on PATH.
|
|
80
|
+
|
|
81
|
+
### Local checkout
|
|
82
|
+
|
|
83
|
+
```sh
|
|
84
|
+
dsh plugin --profile web add link:/absolute/path/to/dsh-semble # macOS / Linux
|
|
85
|
+
dsh plugin --profile web add link:D:\path\to\dsh-semble # Windows
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
The profile then points at your working copy, so edits to `cordis.patch.yml` apply on the next start
|
|
89
|
+
without reinstalling.
|
|
90
|
+
|
|
91
|
+
### Prerequisites
|
|
92
|
+
|
|
93
|
+
[uv](https://docs.astral.sh/uv/) must be on PATH — `uvx` launches Semble from PyPI:
|
|
94
|
+
|
|
95
|
+
```powershell
|
|
96
|
+
winget install astral-sh.uv # Windows
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
```sh
|
|
100
|
+
brew install uv # macOS
|
|
101
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh # macOS / Linux
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
First start downloads the package and the embedding model (~1–2 min, one-time, offline afterwards).
|
|
105
|
+
Restart DSH once after installing; until then the settings row may read 待重启.
|
|
106
|
+
|
|
107
|
+
## Settings
|
|
108
|
+
|
|
109
|
+
Edit the `semble-mcp` row in **Settings → Plugins**:
|
|
110
|
+
|
|
111
|
+
| Field | Default | Why change it |
|
|
112
|
+
| --- | --- | --- |
|
|
113
|
+
| `args` | `--from 'semble[mcp]' semble` | append `--content all` to index docs and config too |
|
|
114
|
+
| `args` (version) | floating | `semble[mcp]==X.Y.Z` pins a release |
|
|
115
|
+
| `env` | empty | `HF_ENDPOINT` on restricted networks, `SEMBLE_CACHE_LOCATION` to move the index |
|
|
116
|
+
| `cwd` | inherited | keep unset; per-call `repo` values should be absolute paths |
|
|
117
|
+
| `command` | `uvx` | point it at `uvx.exe` if only a `.cmd` shim is installed |
|
|
118
|
+
|
|
119
|
+
Changing settings restarts the MCP connection; disk index caches survive.
|
|
120
|
+
|
|
121
|
+
## Platform notes
|
|
122
|
+
|
|
123
|
+
The bundle ships no OS-specific path and no region-specific endpoint, so one installation serves all
|
|
124
|
+
three platforms. What differs is only what you type:
|
|
125
|
+
|
|
126
|
+
| Concern | Windows | macOS / Linux |
|
|
127
|
+
| --- | --- | --- |
|
|
128
|
+
| Executable | `uvx.exe`, resolved through PATH | `uvx` |
|
|
129
|
+
| Repository paths | `D:\work\repo` | `/home/me/repo` |
|
|
130
|
+
| Profile home | `C:\Users\<you>\.dsh` | `~/.dsh` |
|
|
131
|
+
| Retrieved paths | keep `\` separators | POSIX `/` |
|
|
132
|
+
|
|
133
|
+
## Bundled skill
|
|
134
|
+
|
|
135
|
+
Installation also registers one routing skill, `semble-code-search`. The tools do not advertise
|
|
136
|
+
*when* they are worth calling, and a model that reaches for `grep` first never learns that the index
|
|
137
|
+
existed.
|
|
138
|
+
|
|
139
|
+
DSH loads skills lazily:
|
|
140
|
+
|
|
141
|
+
| When | Enters the session | Cost |
|
|
142
|
+
| --- | --- | --- |
|
|
143
|
+
| Before the first request | one catalog entry (name + capped description) | a few hundred bytes per session |
|
|
144
|
+
| Model calls `skill` | the full `skills/semble/SKILL.md` body | ~2 KB, only when used |
|
|
145
|
+
| You type `/semble-code-search` | same body, injected into that step | manual |
|
|
146
|
+
|
|
147
|
+
The body never enters the system prompt. To keep the tools and drop the skill, delete the
|
|
148
|
+
`ctx.skills.register(...)` call in `lib/index.js`.
|
|
149
|
+
|
|
150
|
+
## How it works
|
|
151
|
+
|
|
152
|
+
The bundle inserts two loader rows:
|
|
153
|
+
|
|
154
|
+
1. `semble-mcp-anchor` — a no-op plugin loaded under this package's own name. DSH decides "loaded"
|
|
155
|
+
by matching loader entry names against the installed package name, and the MCP client row loads
|
|
156
|
+
under `@deepseek-ai/dsh-mcp-client`; without the anchor the settings row reads 未加载 / 待重启
|
|
157
|
+
while the tools work fine.
|
|
158
|
+
2. `semble-mcp` — the official `@deepseek-ai/dsh-mcp-client` row, configured to start
|
|
159
|
+
`uvx --from "semble[mcp]" semble` over stdio.
|
|
160
|
+
|
|
161
|
+
Semble itself is **not vendored**. The plugin declares how to launch it from PyPI with a floating
|
|
162
|
+
spec, so upstream bugfixes and new tools arrive on the next server start; only a breaking change to
|
|
163
|
+
the CLI surface would need an edit here.
|
|
164
|
+
|
|
165
|
+
## Update
|
|
166
|
+
|
|
167
|
+
Re-run the install with a newer version, or press 更新 in settings:
|
|
168
|
+
|
|
169
|
+
```sh
|
|
170
|
+
dsh plugin --profile web add dsh-semble@2.0.0
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Source installs re-run with the new ref, e.g.
|
|
174
|
+
`dsh plugin --profile web add github:CodeIntegrity/dsh-semble#v2.0.0`.
|
|
175
|
+
|
|
176
|
+
## Uninstall
|
|
177
|
+
|
|
178
|
+
**Settings → Plugins → 卸载**, or:
|
|
179
|
+
|
|
180
|
+
```sh
|
|
181
|
+
dsh plugin --profile web remove dsh-semble
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Installed the 1.x source build? Remove it by its old name first:
|
|
185
|
+
`dsh plugin --profile web remove @local/semble-mcp`. The package was renamed in 2.0.0, and the anchor
|
|
186
|
+
row only matches an install whose package name is `dsh-semble`.
|
|
187
|
+
|
|
188
|
+
The cached index and the HuggingFace model stay on disk and are reused after a reinstall.
|
|
189
|
+
|
|
190
|
+
## Troubleshooting
|
|
191
|
+
|
|
192
|
+
| Symptom | Cause | Fix |
|
|
193
|
+
| --- | --- | --- |
|
|
194
|
+
| Row reads 待重启 after install | the host loaded its layer list before the install | restart DSH once |
|
|
195
|
+
| Tools work, row reads 未加载 | `cordis.patch.yml` lost the anchor row | reinstall this version or newer |
|
|
196
|
+
| `mcp__semble__*` never appears | `uvx` missing, or the first download failed | run `uvx --from "semble[mcp]" semble --version` and read the error |
|
|
197
|
+
| First search takes minutes | one-time model download | wait, or set `HF_ENDPOINT` |
|
|
198
|
+
| `ERR_PNPM_GIT_RESOLVE_FAILED` | no network route to github.com | use a tarball URL or a mirror |
|
|
199
|
+
|
|
200
|
+
## Development
|
|
201
|
+
|
|
202
|
+
```sh
|
|
203
|
+
git clone https://github.com/CodeIntegrity/dsh-semble
|
|
204
|
+
dsh plugin --profile web add link:$(pwd) # then edit and restart DSH
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
No build step: `lib/index.js` is plain ESM and `cordis.patch.yml` is read directly. The only runtime
|
|
208
|
+
dependency is `uv`.
|
|
209
|
+
|
|
210
|
+
## License
|
|
211
|
+
|
|
212
|
+
MIT
|
package/README.zh-CN.md
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
# dsh-semble
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/dsh-semble)
|
|
4
|
+
|
|
5
|
+
> 给 DeepSeek Harness 的语义代码检索。
|
|
6
|
+
>
|
|
7
|
+
> 你只需要问「这东西在哪」,不必先想起它叫什么——agent 自己找到文件、读它、再改。
|
|
8
|
+
|
|
9
|
+
[English](README.md) | 简体中文
|
|
10
|
+
|
|
11
|
+
`dsh-semble` 把 [Semble](https://github.com/MinishLab/semble) 的代码索引接进每个 DSH 会话,
|
|
12
|
+
以两个原生 MCP 工具的形式出现。`grep` 要求你手里已经有一个字符串;它要的是一句行为描述——
|
|
13
|
+
「请求失败时重试策略在哪生效」「哪个模块决定了打分权重」。而这种时刻,agent 通常正好开始猜文件名。
|
|
14
|
+
|
|
15
|
+
除此之外没有要学的东西:装好之后两个工具就摆在 `read`、`grep` 旁边,由 agent 决定什么时候值得查一次索引。
|
|
16
|
+
|
|
17
|
+
## 你会得到什么
|
|
18
|
+
|
|
19
|
+
| 工具 | 交给它 | 拿回来 |
|
|
20
|
+
| --- | --- | --- |
|
|
21
|
+
| `mcp__semble__search` | 一句话描述代码做什么、或者它在哪儿 | 按相关度排序的 `file:line` 命中 + 片段 |
|
|
22
|
+
| `mcp__semble__find_related` | 一个你已经知道的位置 | 它的邻居:其他实现、调用方、测试 |
|
|
23
|
+
|
|
24
|
+
一次典型对话:
|
|
25
|
+
|
|
26
|
+
> **你:** DSH 判断「插件已加载」是在哪儿决定的?
|
|
27
|
+
>
|
|
28
|
+
> **agent:** 调 `search`,拿到插件清单模块的一条命中,用 `read` 打开,找到 `isEntryLoaded`
|
|
29
|
+
> 把 loader 条目名和包名做比对,然后**基于源码**回答,而不是基于猜测。
|
|
30
|
+
|
|
31
|
+
## 工具怎么用
|
|
32
|
+
|
|
33
|
+
- `repo` —— **必填**。仓库绝对路径,或 `https://` git 地址;传数组可同时检索多个仓库。
|
|
34
|
+
- `top_k` —— 默认 5,首轮没命中时提到 10–20。
|
|
35
|
+
- `max_snippet_lines` —— 默认 10,`0` 只返回位置。
|
|
36
|
+
- `content` —— `code`(默认)、`docs`、`config`、`all`。
|
|
37
|
+
|
|
38
|
+
某个仓库的首次查询要建索引(慢,一次性),之后复用。命中按相似度排序,所以分数接近 `0.0x`
|
|
39
|
+
通常意味着「这儿没有相关内容」,而不是「这是最佳答案」。
|
|
40
|
+
|
|
41
|
+
## 安装
|
|
42
|
+
|
|
43
|
+
### 桌面端
|
|
44
|
+
|
|
45
|
+
**设置 → 插件 → 安装**,粘贴:
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
dsh-semble
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
钉住版本写 `dsh-semble@2.0.0`。`desktop` profile 只支持从设置页安装——CLI 会拒绝,
|
|
52
|
+
因为这个 profile 的 `node_modules` 与 lockfile 由 Electron 应用独占。
|
|
53
|
+
|
|
54
|
+
### 命令行
|
|
55
|
+
|
|
56
|
+
```sh
|
|
57
|
+
dsh plugin --profile web add dsh-semble
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
该子命令在 profile 目录里跑 `pnpm add`,随后 reconcile `dsh.profile.bundles`,所以下次启动即挂载。
|
|
61
|
+
没有构建步骤,pnpm 不需要 `allowBuilds` 例外。
|
|
62
|
+
|
|
63
|
+
### 从源码安装
|
|
64
|
+
|
|
65
|
+
要跟 `main`、装某个 fork 或装还没发版的提交,走仓库安装:
|
|
66
|
+
|
|
67
|
+
```sh
|
|
68
|
+
dsh plugin --profile web add github:CodeIntegrity/dsh-semble
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
支持 `github:owner/repo`、`git+https://…`、`https://github.com/owner/repo` 和 `.tgz` 链接;
|
|
72
|
+
这些需要 PATH 上有 `git`。
|
|
73
|
+
|
|
74
|
+
### 本地目录
|
|
75
|
+
|
|
76
|
+
```sh
|
|
77
|
+
dsh plugin --profile web add link:/绝对路径/dsh-semble # macOS / Linux
|
|
78
|
+
dsh plugin --profile web add link:D:\path\to\dsh-semble # Windows
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
之后 profile 指向你的工作副本,改完 `cordis.patch.yml` 下次启动即生效,无需重装。
|
|
82
|
+
|
|
83
|
+
### 前置条件
|
|
84
|
+
|
|
85
|
+
PATH 上要有 [uv](https://docs.astral.sh/uv/)——`uvx` 负责从 PyPI 拉起 Semble:
|
|
86
|
+
|
|
87
|
+
```powershell
|
|
88
|
+
winget install astral-sh.uv # Windows
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
```sh
|
|
92
|
+
brew install uv # macOS
|
|
93
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh # macOS / Linux
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
首次启动会下载包与嵌入模型(约 1–2 分钟,一次性,之后离线可用)。装完重启一次 DSH;在那之前设置页那行
|
|
97
|
+
可能显示「待重启」。
|
|
98
|
+
|
|
99
|
+
## 设置
|
|
100
|
+
|
|
101
|
+
在 **设置 → 插件** 里编辑 `semble-mcp` 行:
|
|
102
|
+
|
|
103
|
+
| 字段 | 默认值 | 什么时候改 |
|
|
104
|
+
| --- | --- | --- |
|
|
105
|
+
| `args` | `--from 'semble[mcp]' semble` | 追加 `--content all` 让文档和配置也进索引 |
|
|
106
|
+
| `args`(版本) | 浮动 | 改成 `semble[mcp]==X.Y.Z` 钉版本 |
|
|
107
|
+
| `env` | 空 | 受限网络加 `HF_ENDPOINT`;搬索引加 `SEMBLE_CACHE_LOCATION` |
|
|
108
|
+
| `cwd` | 继承 | 保持不设;每次调用的 `repo` 用绝对路径 |
|
|
109
|
+
| `command` | `uvx` | 如果只装了 `.cmd` 包装,改指向 `uvx.exe` |
|
|
110
|
+
|
|
111
|
+
改设置会重启 MCP 连接;磁盘上的索引缓存不受影响。
|
|
112
|
+
|
|
113
|
+
## 平台差异
|
|
114
|
+
|
|
115
|
+
bundle 不含任何 OS 专属路径、也不含区域专属 endpoint,一份安装三平台通用。真正不同的只有你敲进去的东西:
|
|
116
|
+
|
|
117
|
+
| 关注点 | Windows | macOS / Linux |
|
|
118
|
+
| --- | --- | --- |
|
|
119
|
+
| 可执行文件 | `uvx.exe`,经 PATH 解析 | `uvx` |
|
|
120
|
+
| 仓库路径 | `D:\work\repo` | `/home/me/repo` |
|
|
121
|
+
| profile 目录 | `C:\Users\<你>\.dsh` | `~/.dsh` |
|
|
122
|
+
| 命中路径分隔符 | 保留 `\` | POSIX `/` |
|
|
123
|
+
|
|
124
|
+
## 内置 skill
|
|
125
|
+
|
|
126
|
+
安装同时注册一个路由 skill:`semble-code-search`。工具本身不会说明「什么时候值得用」,而先摸
|
|
127
|
+
`grep` 的模型永远不会发现索引的存在。
|
|
128
|
+
|
|
129
|
+
DSH 的 skill 惰性加载:
|
|
130
|
+
|
|
131
|
+
| 时机 | 进入会话的内容 | 成本 |
|
|
132
|
+
| --- | --- | --- |
|
|
133
|
+
| 首次请求前 | 一条目录条目(名称 + 截断描述) | 每会话几百字节 |
|
|
134
|
+
| 模型调 `skill` | 完整 `skills/semble/SKILL.md` 正文 | 约 2 KB,只在实际用到时 |
|
|
135
|
+
| 你输入 `/semble-code-search` | 同一份正文,注入当步 | 手动 |
|
|
136
|
+
|
|
137
|
+
正文不进系统提示词。只想保留工具、不要 skill,删掉 `lib/index.js` 里的 `ctx.skills.register(...)`
|
|
138
|
+
调用即可。
|
|
139
|
+
|
|
140
|
+
## 工作原理
|
|
141
|
+
|
|
142
|
+
bundle 插入两行 loader:
|
|
143
|
+
|
|
144
|
+
1. `semble-mcp-anchor` —— 以本包名加载的空插件。DSH 判断「已加载」是拿 loader 条目名和已安装包名做匹配,
|
|
145
|
+
而 MCP 客户端那行是以 `@deepseek-ai/dsh-mcp-client` 加载的;没有这个锚点,明明工具能用,设置页却显示
|
|
146
|
+
未加载 / 待重启。
|
|
147
|
+
2. `semble-mcp` —— 官方 `@deepseek-ai/dsh-mcp-client` 行,配置为通过 stdio 启动
|
|
148
|
+
`uvx --from "semble[mcp]" semble`。
|
|
149
|
+
|
|
150
|
+
Semble 本体**不做 vendored 内嵌**。插件只声明如何从 PyPI 拉起它,且用浮动版本号,所以上游的 bugfix
|
|
151
|
+
与新工具在下次 server 启动时生效;只有 CLI 表面发生破坏性变更时才需要改这里。
|
|
152
|
+
|
|
153
|
+
## 更新
|
|
154
|
+
|
|
155
|
+
用更新的版本重跑安装,或在设置页点「更新」:
|
|
156
|
+
|
|
157
|
+
```sh
|
|
158
|
+
dsh plugin --profile web add dsh-semble@2.0.0
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
源码安装则换 ref 重跑,例如
|
|
162
|
+
`dsh plugin --profile web add github:CodeIntegrity/dsh-semble#v2.0.0`。
|
|
163
|
+
|
|
164
|
+
## 卸载
|
|
165
|
+
|
|
166
|
+
**设置 → 插件 → 卸载**,或:
|
|
167
|
+
|
|
168
|
+
```sh
|
|
169
|
+
dsh plugin --profile web remove dsh-semble
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
装过 1.x 源码版的话,先按旧名卸载:`dsh plugin --profile web remove @local/semble-mcp`。
|
|
173
|
+
2.0.0 起改了包名,而锚点行只认包名为 `dsh-semble` 的安装。
|
|
174
|
+
|
|
175
|
+
已缓存的索引与 HuggingFace 模型留在磁盘上,重装可复用。
|
|
176
|
+
|
|
177
|
+
## 常见问题
|
|
178
|
+
|
|
179
|
+
| 现象 | 原因 | 处理 |
|
|
180
|
+
| --- | --- | --- |
|
|
181
|
+
| 装完显示「待重启」 | 宿主在安装前已经加载了层列表 | 重启 DSH 一次 |
|
|
182
|
+
| 工具能用但显示「未加载」 | `cordis.patch.yml` 缺了锚点行 | 重装本版本或更新版本 |
|
|
183
|
+
| `mcp__semble__*` 一直不出现 | 缺 `uvx`,或首次下载失败 | 手动跑 `uvx --from "semble[mcp]" semble --version` 看报错 |
|
|
184
|
+
| 首次检索卡几分钟 | 模型一次性下载 | 等待,或设 `HF_ENDPOINT` |
|
|
185
|
+
| 安装时报 `ERR_PNPM_GIT_RESOLVE_FAILED` | 到 github.com 没有网络通路 | 改用 tarball 链接或镜像 |
|
|
186
|
+
|
|
187
|
+
## 开发
|
|
188
|
+
|
|
189
|
+
```sh
|
|
190
|
+
git clone https://github.com/CodeIntegrity/dsh-semble
|
|
191
|
+
dsh plugin --profile web add link:$(pwd) # 之后改代码、重启 DSH
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
没有构建步骤:`lib/index.js` 是纯 ESM,`cordis.patch.yml` 直接读取。唯一运行时依赖是 `uv`。
|
|
195
|
+
|
|
196
|
+
## 许可
|
|
197
|
+
|
|
198
|
+
MIT
|
package/cordis.patch.yml
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Semble MCP bridge for DeepSeek Harness.
|
|
2
|
+
#
|
|
3
|
+
# Inserts the official @deepseek-ai/dsh-mcp-client row configured to start the
|
|
4
|
+
# Semble MCP server (PyPI project `semble`, MIT, https://github.com/MinishLab/semble)
|
|
5
|
+
# over stdio. No semble source code is vendored here: `uvx` resolves and installs
|
|
6
|
+
# the package from PyPI, so upstream releases (bugfixes, new MCP tools) are picked
|
|
7
|
+
# up automatically on the next server start.
|
|
8
|
+
#
|
|
9
|
+
# Platform policy: this file deliberately contains no OS-specific path and no
|
|
10
|
+
# region-specific endpoint. `command: uvx` is a real executable on every platform
|
|
11
|
+
# uv supports (uvx.exe on Windows, uvx on macOS/Linux), resolved through PATH, so
|
|
12
|
+
# the same row works unchanged everywhere. Everything an operator may need to
|
|
13
|
+
# adapt — repository paths, proxies, mirrors — belongs in the plugin settings,
|
|
14
|
+
# not in the shipped default.
|
|
15
|
+
#
|
|
16
|
+
# Version policy: floating spec `semble[mcp]` follows the latest release.
|
|
17
|
+
# To pin a specific version for stability, edit this row in the DSH plugin
|
|
18
|
+
# settings and change the spec to `semble[mcp]==X.Y.Z`.
|
|
19
|
+
- insert:
|
|
20
|
+
# Host-side anchor row: an empty plugin loaded under this package's own name.
|
|
21
|
+
# DSH's plugin inventory (and the Plugin Hub) decide "loaded" by matching loader
|
|
22
|
+
# entry names against the installed package name, and the MCP client row below
|
|
23
|
+
# loads under @deepseek-ai/dsh-mcp-client — without this anchor the bundle would
|
|
24
|
+
# report 未加载 / 待重启 while its tools are actually registered and working.
|
|
25
|
+
- id: semble-mcp-anchor
|
|
26
|
+
name: 'dsh-semble'
|
|
27
|
+
|
|
28
|
+
- id: semble-mcp
|
|
29
|
+
name: '@deepseek-ai/dsh-mcp-client'
|
|
30
|
+
config:
|
|
31
|
+
serverName: semble
|
|
32
|
+
transport: stdio
|
|
33
|
+
command: uvx
|
|
34
|
+
args:
|
|
35
|
+
- --from
|
|
36
|
+
- 'semble[mcp]'
|
|
37
|
+
- semble
|
|
38
|
+
failOnStartupError: true
|
|
39
|
+
# No `env` defaults on purpose: the embedding model
|
|
40
|
+
# (minishlab/potion-code-16M-v2) is fetched from huggingface.co unless the
|
|
41
|
+
# operator asks otherwise. On networks where huggingface.co is unreachable,
|
|
42
|
+
# add the following in the plugin settings rather than here:
|
|
43
|
+
#
|
|
44
|
+
# HF_ENDPOINT: https://hf-mirror.com
|
|
45
|
+
#
|
|
46
|
+
# `cwd` is intentionally unset too: the server inherits the host working
|
|
47
|
+
# directory, and per-call `repo` values should be absolute paths in the
|
|
48
|
+
# host's own convention (C:\... on Windows, /... on macOS/Linux).
|
package/icon.svg
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
|
|
2
|
+
<rect x="5" y="9" width="36" height="46" rx="7" fill="#e8f2fa" stroke="#247bbf" stroke-width="3"/>
|
|
3
|
+
<path d="M15 24l-6 6 6 6" fill="none" stroke="#247bbf" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
|
4
|
+
<path d="M31 24l6 6-6 6" fill="none" stroke="#247bbf" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
|
5
|
+
<path d="M26 18l-4 24" fill="none" stroke="#247bbf" stroke-width="3" stroke-linecap="round"/>
|
|
6
|
+
<circle cx="46" cy="44" r="11" fill="none" stroke="#247bbf" stroke-width="5"/>
|
|
7
|
+
<path d="M54 52l6 6" stroke="#247bbf" stroke-width="6" stroke-linecap="round"/>
|
|
8
|
+
</svg>
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Semble MCP bundle — host-side anchor plugin.
|
|
3
|
+
*
|
|
4
|
+
* Two responsibilities:
|
|
5
|
+
*
|
|
6
|
+
* 1. Give the bundle a stable loader entry. The real work is done by the
|
|
7
|
+
* `@deepseek-ai/dsh-mcp-client` row declared next to this one in
|
|
8
|
+
* cordis.patch.yml, which loads the MCP client under its own module name, so
|
|
9
|
+
* a running host would otherwise have no loader entry named after this
|
|
10
|
+
* package. DSH's plugin inventory and the Plugin Hub decide "loaded" by
|
|
11
|
+
* matching loader entry names against the installed npm package name
|
|
12
|
+
* (`isEntryLoaded`), so without an entry of our own the plugin is reported as
|
|
13
|
+
* 未加载 / 待重启 even while its MCP tools are registered and working.
|
|
14
|
+
*
|
|
15
|
+
* 2. Register the bundled routing skill so the model knows *when* the MCP tools
|
|
16
|
+
* are worth calling. The skill body ships inside this package (skills/
|
|
17
|
+
* semble/SKILL.md) and is registered as a runtime skill, which keeps plugin
|
|
18
|
+
* installation a single step: no copying files into ~/.dsh/skills.
|
|
19
|
+
*
|
|
20
|
+
* The skill is loaded lazily by DSH: the session catalog carries only the name
|
|
21
|
+
* and description, and the body text reaches the model only when it calls the
|
|
22
|
+
* `skill` tool. Reading the file here costs one small synchronous read at host
|
|
23
|
+
* start and nothing per request.
|
|
24
|
+
*/
|
|
25
|
+
import { readFileSync } from 'node:fs'
|
|
26
|
+
|
|
27
|
+
export const name = 'semble-mcp'
|
|
28
|
+
|
|
29
|
+
export const inject = ['skills']
|
|
30
|
+
|
|
31
|
+
const SKILL_URL = new URL('../skills/semble/SKILL.md', import.meta.url)
|
|
32
|
+
|
|
33
|
+
/** Strip the YAML frontmatter so filesystem-style SKILL.md files render clean. */
|
|
34
|
+
function stripFrontmatter(markdown) {
|
|
35
|
+
const match = /^\uFEFF?---\r?\n[\s\S]*?\r?\n---\r?\n/.exec(markdown)
|
|
36
|
+
return match === null ? markdown : markdown.slice(match[0].length).replace(/^\s*\n/, '')
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Read the bundled skill body, or `undefined` when the package is incomplete. */
|
|
40
|
+
function readSkillBody() {
|
|
41
|
+
try {
|
|
42
|
+
return stripFrontmatter(readFileSync(SKILL_URL, 'utf8')).trim()
|
|
43
|
+
} catch (error) {
|
|
44
|
+
// A missing skill file must not take the MCP connection's anchor row down
|
|
45
|
+
// with it: the tools keep working, only the routing hint is absent.
|
|
46
|
+
console.warn('[semble-mcp] bundled skill could not be read:', error?.message ?? error)
|
|
47
|
+
return undefined
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Apply: provide the loader anchor and register the bundled routing skill. */
|
|
52
|
+
export default function sembleMcpBundle(ctx) {
|
|
53
|
+
const content = readSkillBody()
|
|
54
|
+
if (content === undefined) return
|
|
55
|
+
// Registered into this plugin's layer, so teardown follows the fiber and the
|
|
56
|
+
// returned disposer needs no bookkeeping here.
|
|
57
|
+
ctx.skills.register({
|
|
58
|
+
name: 'semble-code-search',
|
|
59
|
+
description:
|
|
60
|
+
'Find code by what it does, not by exact text. Use when locating an implementation, a caller, or a related pattern before editing, or when a plain text search returns too much noise.',
|
|
61
|
+
whenToUse:
|
|
62
|
+
'before a broad code search in a repository, and when a grep result is too noisy to be useful; gives the query shape, the semantic search workflow, and the cost limits of the Semble MCP tools.',
|
|
63
|
+
content,
|
|
64
|
+
source: 'bundle:dsh-semble',
|
|
65
|
+
resourceBase: { kind: 'opaque', description: 'Exposed as the mcp__semble__search and mcp__semble__find_related MCP tools.' },
|
|
66
|
+
invocation: { modelInvocable: true, userInvocable: true },
|
|
67
|
+
})
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Named form of the same entry point. The loader accepts either the default
|
|
72
|
+
* export or a module-level `apply(ctx)`, and spelling both out makes the
|
|
73
|
+
* plugin's shape explicit to readers and to plugin-listing checks.
|
|
74
|
+
*/
|
|
75
|
+
export const apply = sembleMcpBundle
|
package/locale/en.json
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
{
|
|
2
|
+
"meta": {
|
|
3
|
+
"title": "Semble Code Search (MCP)",
|
|
4
|
+
"description": "Exposes the Semble agent code-search engine as native MCP tools (search / find_related). Starts the official Semble MCP server from PyPI via uvx; follows the latest upstream release automatically."
|
|
5
|
+
}
|
|
6
|
+
}
|
package/locale/zh.json
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "dsh-semble",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "lib/index.js",
|
|
6
|
+
"description": "Semble 语义代码搜索(semantic code search)MCP bundle:安装即用,无需客户端配置。Semble semantic code search for DeepSeek Harness via MCP (search / find_related).",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"author": "Liu Kai",
|
|
9
|
+
"icon": "icon.svg",
|
|
10
|
+
"engines": {
|
|
11
|
+
"node": ">=22",
|
|
12
|
+
"dsh": ">=0.2.1-rc.2"
|
|
13
|
+
},
|
|
14
|
+
"homepage": "https://github.com/CodeIntegrity/dsh-semble#readme",
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "git+https://github.com/CodeIntegrity/dsh-semble.git"
|
|
18
|
+
},
|
|
19
|
+
"bugs": {
|
|
20
|
+
"url": "https://github.com/CodeIntegrity/dsh-semble/issues"
|
|
21
|
+
},
|
|
22
|
+
"keywords": [
|
|
23
|
+
"dsh",
|
|
24
|
+
"dsh-plugin",
|
|
25
|
+
"dsh-bundle",
|
|
26
|
+
"deepseek-harness",
|
|
27
|
+
"semble",
|
|
28
|
+
"mcp",
|
|
29
|
+
"code-search",
|
|
30
|
+
"semantic-search"
|
|
31
|
+
],
|
|
32
|
+
"exports": {
|
|
33
|
+
".": "./lib/index.js",
|
|
34
|
+
"./locale/*.json": "./locale/*.json",
|
|
35
|
+
"./icon": "./icon.svg"
|
|
36
|
+
},
|
|
37
|
+
"files": [
|
|
38
|
+
"lib",
|
|
39
|
+
"skills",
|
|
40
|
+
"cordis.patch.yml",
|
|
41
|
+
"locale/*.json",
|
|
42
|
+
"icon.svg",
|
|
43
|
+
"LICENSE",
|
|
44
|
+
"README.md",
|
|
45
|
+
"README.zh-CN.md"
|
|
46
|
+
],
|
|
47
|
+
"dsh": {
|
|
48
|
+
"bundle": {
|
|
49
|
+
"patch": "./cordis.patch.yml"
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: semble-code-search
|
|
3
|
+
description: Find code by what it does, not by exact text. Use when you need to locate an implementation, a caller, or a related pattern in the current repository before editing, or when a plain text search returns too much noise.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Semble code search
|
|
7
|
+
|
|
8
|
+
Semantic search over code, exposed by the Semble MCP server as two tools:
|
|
9
|
+
|
|
10
|
+
- `mcp__semble__search` — describe what the code does or where it lives, get ranked `file:line` hits with snippets.
|
|
11
|
+
- `mcp__semble__find_related` — given one known location, find its siblings: other implementations of the same interface, the callers of a function, the tests for a class.
|
|
12
|
+
|
|
13
|
+
## When to use it
|
|
14
|
+
|
|
15
|
+
Use it when you know *what* you are looking for but not *where* it is:
|
|
16
|
+
|
|
17
|
+
- "where is the retry policy applied when a request fails"
|
|
18
|
+
- "which module decides the scoring weights"
|
|
19
|
+
- "what else implements this provider interface"
|
|
20
|
+
|
|
21
|
+
Prefer the `grep` and `read` tools when you already have a path, an exact identifier, or a
|
|
22
|
+
short literal to match — the semantic index is a coarse first pass, not a replacement for
|
|
23
|
+
reading the code.
|
|
24
|
+
|
|
25
|
+
## How to query well
|
|
26
|
+
|
|
27
|
+
The query is matched against embedded function bodies, so phrase it as behaviour:
|
|
28
|
+
|
|
29
|
+
- Good: `persist a chunk to the vector store`, `resolve the model name from config`, `stream tokens to the client`.
|
|
30
|
+
- Bad: a stack trace, an error string, a single identifier, or `fix bug`.
|
|
31
|
+
|
|
32
|
+
Controls, all on both tools unless noted:
|
|
33
|
+
|
|
34
|
+
- `repo` — **required**. The absolute path of the repository, or an `https://` URL of a git remote.
|
|
35
|
+
In a session this is normally the session working directory, written the way the host writes paths
|
|
36
|
+
(`D:\work\repo` on Windows, `/home/me/repo` on macOS/Linux). Pass a list to search several
|
|
37
|
+
repositories at once. Omitting it fails validation, so always send it.
|
|
38
|
+
- `top_k` — default 5; raise it to 10–20 when the first pass misses.
|
|
39
|
+
- `max_snippet_lines` — default 10; use `0` for locations only, or omit a cap to see a whole chunk.
|
|
40
|
+
- `content` — `code` (default), `docs`, `config`, or `all`; switch to `all` when the answer may live in documentation or configuration.
|
|
41
|
+
|
|
42
|
+
## Workflow
|
|
43
|
+
|
|
44
|
+
1. `search` with a behaviour phrase, always passing `repo`.
|
|
45
|
+
2. Open the top hit with the `read` tool, using its `start_line` as `offset`, to confirm it is the
|
|
46
|
+
right code and not a similarity artifact. Pass the returned path through exactly as given — it
|
|
47
|
+
keeps `\` separators on Windows and is already POSIX on macOS/Linux. Rewriting separators by hand
|
|
48
|
+
is where these paths break.
|
|
49
|
+
3. `find_related` on that location when you need callers, siblings, or tests.
|
|
50
|
+
4. Only then edit.
|
|
51
|
+
|
|
52
|
+
## Costs and limits
|
|
53
|
+
|
|
54
|
+
- The first query against a repository builds its index; later queries reuse it. Expect the first
|
|
55
|
+
call in a new repository to be slow.
|
|
56
|
+
- Results are ranked by cosine similarity, so the top hit can be a near-miss. A score close to
|
|
57
|
+
`0.0x` usually means the index holds nothing relevant — stop instead of forcing the hit.
|
|
58
|
+
- The index may be stale relative to uncommitted edits; when proximity matters, read the file
|
|
59
|
+
rather than trusting the snippet.
|
|
60
|
+
|
|
61
|
+
## If the tools are missing
|
|
62
|
+
|
|
63
|
+
`mcp__semble__search` and `mcp__semble__find_related` only exist when this bundle's MCP connection
|
|
64
|
+
mounted in the current session. If they are absent from your toolset, say so and fall back to
|
|
65
|
+
`grep`/`glob`; do not narrate a call you cannot make.
|