misakanet 2.40.0 → 2.41.1
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/.codex-plugin/plugin.json +1 -1
- package/README.ja.md +8 -0
- package/README.md +89 -8
- package/README.zh-CN.md +9 -2
- package/index.js +70 -0
- package/lib/client.js +1068 -59
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +8 -3
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "misakanet",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.41.1",
|
|
4
4
|
"description": "Failure-memory network for AI coding agents: search evidence-rated failure lessons, submit new failures, and turn crashes into reusable knowledge.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Ikalus1988",
|
package/README.ja.md
CHANGED
|
@@ -111,6 +111,14 @@ jobs:
|
|
|
111
111
|
> **MisakaNetは1つのこと専用に構築されています:** エージェントが既知の障害を繰り返すのを防ぐこと。
|
|
112
112
|
> これは汎用メモリレイヤーでもランタイムでもベクトルデータベースでもありません。
|
|
113
113
|
|
|
114
|
+
### 答えてくれること、答えてくれないこと
|
|
115
|
+
|
|
116
|
+

|
|
117
|
+
|
|
118
|
+
答えてくれるのは**収録済みの障害**であり、一般知識ではありません。見つからない場合は `no_match` と、
|
|
119
|
+
そのまま呼び出せる `intake` の案内が返ります —— 未ヒットはギャップが記録される経路そのものなので、
|
|
120
|
+
これもまた答えです。
|
|
121
|
+
|
|
114
122
|
### v2.16.0の新機能
|
|
115
123
|
|
|
116
124
|
| 機能 | 説明 |
|
package/README.md
CHANGED
|
@@ -86,6 +86,47 @@ No account, no token, no Python needed for the plugin path: the npm bundle mount
|
|
|
86
86
|
Declared hosts and what was measured: [compatibility](docs/compatibility.md). Every channel, the
|
|
87
87
|
prerequisites, and the two-package trap that costs people an install: [How to use it](#how-to-use-it).
|
|
88
88
|
|
|
89
|
+
## What the DeepSeek Harness plugin adds
|
|
90
|
+
|
|
91
|
+
Version 2.40.0 ships the browser half, and 2.41.0 adds the rest of it: the surfaces below did not all land in
|
|
92
|
+
the same release, so this section lists them by the version that carries them. It is not a dialog: it puts
|
|
93
|
+
MisakaNet where the session already is.
|
|
94
|
+
|
|
95
|
+
**In 2.40.0 — published.** These six seats are what `npm view misakanet version` gives you today.
|
|
96
|
+
|
|
97
|
+
| Where | What you get |
|
|
98
|
+
| --- | --- |
|
|
99
|
+
| **Left column** | A permanent `MisakaNet` entry directly under `Plugins`. It is a shortcut, not the panel: clicking it opens a full page in the main column. Root scope — it does not come and go with a session. |
|
|
100
|
+
| **Conversation tab** | A `MisakaNet` tab beside Chat and Trajectory: what this session asked, what came back, and what you filed, rebuilt from the conversation's own rows. |
|
|
101
|
+
| **Right column** | The same panel as a pane, so it can sit next to the file tree, a terminal, or a document. |
|
|
102
|
+
| **Tool call rows** | Every `misakanet_search` and `misakanet_submit_intake` call gets its own row on the tool card: the query as it was sent, whether a lesson came back, and which lesson is on top, with the raw result one disclosure away. The row reports and never posts — the vote belongs on the answer's action row below. |
|
|
103
|
+
| **Assistant action row** | 👍 / 👎 on the answer that used a lesson. Those two are the only things the page ever sends — counters live in the browser, not on a server. |
|
|
104
|
+
| **Voice** | An off-by-default switch that explains both mechanisms: the cue the server names on the next search, and the local hook a page cannot read. |
|
|
105
|
+
|
|
106
|
+
<p align="center">
|
|
107
|
+
<img src="docs/assets/dsh-client-left-column.png" width="820" alt="DeepSeek Harness: a permanent MisakaNet entry in the left column under Plugins, and the full page it opens"/>
|
|
108
|
+
</p>
|
|
109
|
+
|
|
110
|
+
<p align="center">
|
|
111
|
+
<img src="docs/assets/dsh-client-right-panel.png" width="820" alt="The MisakaNet pane in the right column of a DeepSeek Harness session"/>
|
|
112
|
+
</p>
|
|
113
|
+
|
|
114
|
+
**With 2.41.0 — [release PR #2591](https://github.com/Ikalus1988/MisakaNet/pull/2591).** These six surfaces
|
|
115
|
+
are in `main` and ship in 2.41.0; a 2.40.0 install does not have them yet.
|
|
116
|
+
|
|
117
|
+
| Where | What you get |
|
|
118
|
+
| --- | --- |
|
|
119
|
+
| **`/misakanet` in the composer** | Type `/misakanet pip install timeout` and press Enter: the lessons come back in a card inside the composer, with no agent in the loop. The query is the only thing it sends. |
|
|
120
|
+
| **Frame-wide toast** | After a `/misakanet` search comes back with lessons, a card appears over every column with the top hit; dismiss it or click through to the lesson. |
|
|
121
|
+
| **Sidebar foot** | One action beside Settings: copy this session's MisakaNet activity as a summary for an issue or a PR body. |
|
|
122
|
+
| **中文 / English** | Every MisakaNet surface follows the host language: the panel, the `/misakanet` card, the settings row, and the plugin page's own title and description. |
|
|
123
|
+
| **Settings → General** | A MisakaNet preference row: play voice cues in this browser, and how much the surfaces show (compact / full). Both stay in the browser. |
|
|
124
|
+
| **Plugin page** | The MCP row's effective configuration — endpoint, transport, timeout — shown read-only, next to where it is edited (the profile's `cordis.patch.yml`). |
|
|
125
|
+
|
|
126
|
+
Which seats the half occupies and why they are `root` or `session` scope, with the host's own contract text
|
|
127
|
+
quoted: [compatibility](docs/compatibility.md). Running a host of your own and want a check that cannot
|
|
128
|
+
touch your profile: `python3 scripts/install_smoke.py dsh-client --serve`.
|
|
129
|
+
|
|
89
130
|
## What is MisakaNet?
|
|
90
131
|
|
|
91
132
|
**Git-backed failure memory for AI coding agents.** An error shows up → the agent searches the lessons →
|
|
@@ -113,6 +154,13 @@ how much a lesson has been proven.
|
|
|
113
154
|
| ❌ A cloud service requiring signup | ✅ `git clone` → search locally |
|
|
114
155
|
| ❌ A skill marketplace | ✅ Debugging knowledge from real sessions |
|
|
115
156
|
|
|
157
|
+
### What it can and cannot answer
|
|
158
|
+
|
|
159
|
+

|
|
160
|
+
|
|
161
|
+
It answers for **the failures it has indexed**, not general knowledge. A query that finds nothing returns
|
|
162
|
+
`no_match` plus a ready-to-call intake — a miss is how a gap gets recorded, so a miss is an answer too.
|
|
163
|
+
|
|
116
164
|
### Lesson vs Skill
|
|
117
165
|
|
|
118
166
|
A **skill** teaches an agent *how to do something*. A **lesson** records *what went wrong before, and how
|
|
@@ -121,21 +169,53 @@ a general memory layer, not a vector database. → [FAQ](FAQ.md)
|
|
|
121
169
|
|
|
122
170
|
## Benchmark: how much of a lesson does a model reproduce when handed one?
|
|
123
171
|
|
|
124
|
-
Weekly benchmark (Cloudflare Workers AI
|
|
125
|
-
|
|
126
|
-
`with_lesson` arm is *that same lesson*, and the score is `lesson_hit_rate`: **the share of the injected lesson's commands reproduced in the answer**.
|
|
172
|
+
Weekly benchmark (Cloudflare Workers AI). **Read the metric before the numbers** — the scenario in this benchmark is each lesson's own title, the "matching lesson" injected into the `with_lesson` arm is *that same lesson*, and the
|
|
173
|
+
score is `lesson_hit_rate`: **the share of the injected lesson's commands reproduced in the answer**.
|
|
127
174
|
No retrieval is called and correctness is not checked, so this is the **recitation** half of RAG, not
|
|
128
|
-
evidence that search works
|
|
175
|
+
evidence that search works.
|
|
176
|
+
|
|
177
|
+
Latest aggregated data: [`docs/benchmarks/latest.json`](docs/benchmarks/latest.json) (2026-09-22, two
|
|
178
|
+
independent runs of ≈500 scenarios each):
|
|
179
|
+
|
|
180
|
+
| Condition | Run 1 hit rate | Run 2 hit rate | Avg | n (per run) | Actionable |
|
|
181
|
+
|---|---|---|---|---|---|
|
|
182
|
+
| plain (no lesson) | 0.239 | 0.233 | **23.3%** | ≈510 | 82–83% |
|
|
183
|
+
| with_lesson (pasted) | 0.464 | 0.461 | **46.1%** | ≈512 | 76–77% |
|
|
129
184
|
|
|
130
|
-
|
|
185
|
+
**Reproducibility.** Two runs with identical config produce hit rates within 0.3% of each other
|
|
186
|
+
(0.464 vs 0.461 for `with_lesson`; 0.239 vs 0.233 for `plain`), confirming the metric is stable.
|
|
187
|
+
|
|
188
|
+
**Aggregation.** Each run evaluates every lesson in the corpus as a scenario. The `with_lesson` arm pastes the matching lesson
|
|
189
|
+
into the prompt; `plain` uses no lesson. `actionable` is a boolean per scenario indicating whether the
|
|
190
|
+
model produced a usable answer. Actionable rates are stable across runs (76–77% with lesson, 82–83% plain).
|
|
191
|
+
|
|
192
|
+
**Trend** (weekly snapshots):
|
|
193
|
+
|
|
194
|
+
| Date | with_lesson hit rate | plain hit rate | n |
|
|
131
195
|
|---|---|---|---|
|
|
132
|
-
|
|
|
133
|
-
|
|
|
196
|
+
| 2026-08-30 | 46.4% | 23.9% | 358 |
|
|
197
|
+
| 2026-08-31 | 49.1% | 25.1% | 398 |
|
|
198
|
+
| 2026-09-06 | 48.3% | 24.1% | 455 |
|
|
199
|
+
| 2026-09-14 | 46.6% | 23.4% | 494 |
|
|
200
|
+
| 2026-09-21 | 46.1% | 23.3% | 512 |
|
|
201
|
+
|
|
202
|
+
```
|
|
203
|
+
with_lesson hit rate (weekly)
|
|
204
|
+
49.1% │ ▄
|
|
205
|
+
48.3% │ █ ▄
|
|
206
|
+
46.6% │ █ █ ▄
|
|
207
|
+
46.4% │ ▄ █ █ █ ▄
|
|
208
|
+
46.1% │ █ █ █ █ █
|
|
209
|
+
└──────────────────
|
|
210
|
+
08 08 09 09 09
|
|
211
|
+
30 31 06 14 21
|
|
212
|
+
```
|
|
134
213
|
|
|
135
214
|
A model repeats more of a document it was handed, and the weaker the model the bigger the relative
|
|
136
215
|
difference. That is *necessary* for the product to help and it is not sufficient — the claim "search finds the
|
|
137
216
|
right lesson for a failure you described" is measured nowhere yet. Details:
|
|
138
|
-
[
|
|
217
|
+
[`docs/benchmarks/latest.json`](docs/benchmarks/latest.json) · per-run files in
|
|
218
|
+
[`docs/benchmarks/`](docs/benchmarks/) · metric definition: `METRIC_DEFINITION` in
|
|
139
219
|
[`scripts/benchmark_workers_ai.py`](scripts/benchmark_workers_ai.py)
|
|
140
220
|
|
|
141
221
|
→ [Full changelog](CHANGELOG.md) · [Release notes](https://github.com/Ikalus1988/MisakaNet/releases)
|
|
@@ -147,6 +227,7 @@ and where this design loses:
|
|
|
147
227
|
|---|---|---|
|
|
148
228
|
| Hit rate | share of the **injected** lesson's commands reproduced in the answer — a recitation check; the scenario is that lesson's own title and no retrieval happens | it is the ceiling on usefulness, not the measure of it: a corpus can be recitable and still unfindable |
|
|
149
229
|
| Gain (with − without) | how much more of that lesson appears when it is pasted in | separates "the model can use a lesson" from "the model guessed the same words" — it says nothing about finding the lesson |
|
|
230
|
+
| Actionable | whether the model produced a usable answer at all (boolean per scenario) | a high hit rate on an answer that is not actionable is noise; this tracks whether the model engages with the problem |
|
|
150
231
|
| Cost / latency | tokens and wall-clock per answer | the whole premise is cheaper than re-debugging, so it has to stay cheap |
|
|
151
232
|
|
|
152
233
|
**Where it loses on purpose:** BM25 matches words, not meaning. A failure described in vocabulary the
|
package/README.zh-CN.md
CHANGED
|
@@ -102,9 +102,9 @@ python3 search_knowledge.py "GitHub token 401"
|
|
|
102
102
|
|
|
103
103
|
```bash
|
|
104
104
|
# npm 安装(推荐)
|
|
105
|
-
dsh plugin add misakanet
|
|
105
|
+
dsh plugin --profile web add misakanet
|
|
106
106
|
# 或直接从 git 安装(同一 bundle)
|
|
107
|
-
# dsh plugin add git+https://github.com/Ikalus1988/MisakaNet.git
|
|
107
|
+
# dsh plugin --profile web add git+https://github.com/Ikalus1988/MisakaNet.git
|
|
108
108
|
|
|
109
109
|
# 让 failure-memory SKILL 可被发现(DSH 扫描 ~/.dsh/skills 与项目 .dsh/skills)
|
|
110
110
|
mkdir -p ~/.dsh/skills
|
|
@@ -164,6 +164,13 @@ MisakaNet 对不同用户的用途不同:
|
|
|
164
164
|
|
|
165
165
|
> 👉 第一次来?[看 MisakaNet Journey →](https://misakanet.org/journey/)
|
|
166
166
|
|
|
167
|
+
### 它能回答什么,不能回答什么
|
|
168
|
+
|
|
169
|
+

|
|
170
|
+
|
|
171
|
+
它只回答**已经收录过的失败**,不是通用知识。查不到时会返回 `no_match` 和一条可直接调用的 `intake`
|
|
172
|
+
指引 —— 未命中正是一条缺口被记下来的方式,所以它同样是一个答案。
|
|
173
|
+
|
|
167
174
|
### Lesson 和 Skill 有什么区别?
|
|
168
175
|
|
|
169
176
|
MisakaNet 的 lesson **不是** skill。
|
package/index.js
CHANGED
|
@@ -120,3 +120,73 @@ export async function apply(ctx, config = {}) {
|
|
|
120
120
|
ctx?.logger?.warn?.(`misakanet: MCP client not mounted: ${error?.message ?? error}`);
|
|
121
121
|
}
|
|
122
122
|
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* The row's `Config`: what the Loader validates the bundle patch's `config:` against, and what the plugin
|
|
126
|
+
* page turns into a form — the host's own words for it are "the cordis `Config` validator and the
|
|
127
|
+
* Config-form generation's served schema" (`dsh-context`'s `index.d.ts` says the same thing about its own).
|
|
128
|
+
*
|
|
129
|
+
* Built with a **top-level `await` inside a `try`**, not a static import. `@deepseek-ai/schemastery` is a
|
|
130
|
+
* host dependency, but this package is also installed by skill-only consumers that never load this module,
|
|
131
|
+
* and a module-level import failure would take the whole row down rather than only its form. Without it the
|
|
132
|
+
* row keeps working from the patch and only the GUI form is lost — the same "absence is not failure" rule
|
|
133
|
+
* `apply()` follows for the MCP client.
|
|
134
|
+
*/
|
|
135
|
+
/**
|
|
136
|
+
* Import schemastery from wherever this install can actually reach it.
|
|
137
|
+
*
|
|
138
|
+
* A profile that **installed** this package resolves the bare specifier on its own: Node walks up from
|
|
139
|
+
* `…/profiles/web/node_modules/misakanet/` and finds the profile's copy. A profile that **linked** a working
|
|
140
|
+
* tree does not — Node resolves the link to its real path, so the walk starts in the repository and never
|
|
141
|
+
* sees the profile. That is the shape this repository's own contributor profiles (and the owner's live one)
|
|
142
|
+
* use, so the second attempt resolves from the `dsh` entry point that started the host, where schemastery is
|
|
143
|
+
* a dependency of DSH itself.
|
|
144
|
+
*/
|
|
145
|
+
async function loadSchemastery() {
|
|
146
|
+
const attempts = ['@deepseek-ai/schemastery'];
|
|
147
|
+
try {
|
|
148
|
+
const { createRequire } = await import('node:module');
|
|
149
|
+
const { realpathSync } = await import('node:fs');
|
|
150
|
+
const { pathToFileURL } = await import('node:url');
|
|
151
|
+
const hostEntry = process.argv[1];
|
|
152
|
+
// Both spellings matter: the bin is usually a **symlink**, and the package's own node_modules sits
|
|
153
|
+
// beside its real path — resolving from the link's directory finds the global root instead.
|
|
154
|
+
const from = [];
|
|
155
|
+
if (hostEntry) from.push(hostEntry);
|
|
156
|
+
try { from.push(realpathSync(hostEntry)); } catch (error) { /* no real path to add */ }
|
|
157
|
+
for (const entry of from) {
|
|
158
|
+
try {
|
|
159
|
+
const resolved = createRequire(entry).resolve('@deepseek-ai/schemastery');
|
|
160
|
+
// `require.resolve` hands back a filesystem path, and a Windows one is not a valid ESM specifier
|
|
161
|
+
// (`C:` parses as a scheme). The bare specifier above is left alone; only paths are wrapped.
|
|
162
|
+
const url = pathToFileURL(resolved).href;
|
|
163
|
+
if (!attempts.includes(url)) attempts.push(url);
|
|
164
|
+
} catch (error) { /* this entry cannot see it */ }
|
|
165
|
+
}
|
|
166
|
+
} catch (error) { /* keep the bare specifier as the only attempt */ }
|
|
167
|
+
for (const specifier of attempts) {
|
|
168
|
+
try {
|
|
169
|
+
const loaded = await import(specifier);
|
|
170
|
+
return loaded.default ?? loaded;
|
|
171
|
+
} catch (error) { /* try the next location */ }
|
|
172
|
+
}
|
|
173
|
+
return undefined;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
let Config;
|
|
177
|
+
try {
|
|
178
|
+
const z = await loadSchemastery();
|
|
179
|
+
if (z === undefined) throw new Error('schemastery is not resolvable from this install');
|
|
180
|
+
Config = z.object({
|
|
181
|
+
transport: z.string().default(DEFAULT_MCP_CONFIG.transport),
|
|
182
|
+
serverName: z.string().default(DEFAULT_MCP_CONFIG.serverName),
|
|
183
|
+
url: z.string().default(DEFAULT_MCP_CONFIG.url),
|
|
184
|
+
headers: z.dict(z.string()).default({ ...DEFAULT_MCP_CONFIG.headers }),
|
|
185
|
+
toolCallTimeoutMs: z.number().default(DEFAULT_MCP_CONFIG.toolCallTimeoutMs),
|
|
186
|
+
failOnStartupError: z.boolean().default(DEFAULT_MCP_CONFIG.failOnStartupError),
|
|
187
|
+
});
|
|
188
|
+
} catch (error) {
|
|
189
|
+
Config = undefined;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
export { Config };
|