dsh-nerd-mode 0.0.0-stage → 0.2.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/NOTICE.md +38 -0
- package/README.md +162 -2
- package/README.zh.md +163 -0
- package/assets/icon-dark.svg +5 -0
- package/assets/icon-light.svg +5 -0
- package/client.js +161 -0
- package/cordis.patch.yml +19 -0
- package/lib/fold.js +39 -0
- package/lib/index.js +93 -0
- package/package.json +56 -4
- package/skills/answer-me-with-html/SKILL.md +197 -0
- package/skills/answer-me-with-html/licenses/OFL-Bangers.txt +93 -0
- package/skills/answer-me-with-html/references/settings.md +19 -0
- package/skills/answer-me-with-html/references/video.md +36 -0
- package/skills/answer-me-with-html/scripts/am.mjs +12417 -0
- package/skills/convert-documents-to-markdown/SKILL.md +26 -0
- package/skills/diagram/SKILL.md +136 -0
- package/skills/humanizer/.claude-plugin/marketplace.json +18 -0
- package/skills/humanizer/.claude-plugin/plugin.json +15 -0
- package/skills/humanizer/.cursor-plugin/plugin.json +12 -0
- package/skills/humanizer/.github/ISSUE_TEMPLATE/config.yml +8 -0
- package/skills/humanizer/.github/ISSUE_TEMPLATE/new-pattern.yml +24 -0
- package/skills/humanizer/.github/ISSUE_TEMPLATE/rewrite-problem.yml +44 -0
- package/skills/humanizer/.github/workflows/validate.yml +29 -0
- package/skills/humanizer/AGENTS.md +54 -0
- package/skills/humanizer/CHANGELOG.md +116 -0
- package/skills/humanizer/LICENSE +21 -0
- package/skills/humanizer/README.md +206 -0
- package/skills/humanizer/SKILL.md +397 -0
- package/skills/humanizer/agents/openai.yaml +4 -0
- package/skills/humanizer/scripts/validate-package.py +146 -0
- package/skills/study/SKILL.md +86 -0
- package/skills/study-plus/SKILL.md +185 -0
- package/skills/teach/GLOSSARY-FORMAT.md +35 -0
- package/skills/teach/LEARNING-RECORD-FORMAT.md +46 -0
- package/skills/teach/MISSION-FORMAT.md +31 -0
- package/skills/teach/RESOURCES-FORMAT.md +32 -0
- package/skills/teach/SKILL.md +140 -0
- package/skills/teach/agents/openai.yaml +5 -0
- package/skills/writing-beats/SKILL.md +66 -0
- package/skills/writing-beats/agents/openai.yaml +5 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 study-plus-dsh contributors
|
|
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/NOTICE.md
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Bundled skills and their authors
|
|
2
|
+
|
|
3
|
+
This package is MIT licensed. It also bundles skills written by other people. Each keeps its own license, and its author is named here.
|
|
4
|
+
|
|
5
|
+
| Skill | Author | License |
|
|
6
|
+
|---|---|---|
|
|
7
|
+
| `study`, `study-plus`, `diagram` | This package | MIT |
|
|
8
|
+
| `teach`, `writing-beats` | Matt Pocock, [mattpocock/skills](https://github.com/mattpocock/skills) | MIT |
|
|
9
|
+
| `humanizer` | Siqi Chen | MIT, full text in `skills/humanizer/LICENSE` |
|
|
10
|
+
| `answer-me-with-html` | QingYunA, [QingYunA/answer-me-with-html](https://github.com/QingYunA/answer-me-with-html) | MIT. The Bangers font is under SIL OFL 1.1, full text in `skills/answer-me-with-html/licenses/OFL-Bangers.txt` |
|
|
11
|
+
| `convert-documents-to-markdown` | firecrawl | MIT, stated in its frontmatter |
|
|
12
|
+
|
|
13
|
+
## MIT notice
|
|
14
|
+
|
|
15
|
+
Copyright (c) 2026 Matt Pocock
|
|
16
|
+
Copyright (c) 2025 Siqi Chen
|
|
17
|
+
Copyright (c) 2026 Answer me with HTML contributors
|
|
18
|
+
Copyright (c) firecrawl
|
|
19
|
+
|
|
20
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
21
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
22
|
+
in the Software without restriction, including without limitation the rights
|
|
23
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
24
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
25
|
+
furnished to do so, subject to the following conditions:
|
|
26
|
+
|
|
27
|
+
The above copyright notice and this permission notice shall be included in all
|
|
28
|
+
copies or substantial portions of the Software.
|
|
29
|
+
|
|
30
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
31
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
32
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
33
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
34
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
35
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
36
|
+
SOFTWARE.
|
|
37
|
+
|
|
38
|
+
If you own one of these skills and want it removed or credited differently, open an issue in this repository.
|
package/README.md
CHANGED
|
@@ -1,3 +1,163 @@
|
|
|
1
|
-
|
|
1
|
+
[](./README.md) [](./README.zh.md)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
<picture>
|
|
4
|
+
<source media="(prefers-color-scheme: dark)" srcset="assets/icon-dark.svg">
|
|
5
|
+
<img src="assets/icon-light.svg" width="120" height="120" alt="Nerd Mode">
|
|
6
|
+
</picture>
|
|
7
|
+
|
|
8
|
+
# Nerd Mode for DeepSeek Harness
|
|
9
|
+
|
|
10
|
+
Learning in a chat usually ends when the answer arrives: nothing is checked, and nothing survives the conversation. Nerd Mode changes what dsh does with a question. It teaches in steps, it stops where the choice matters, and it can keep a dated record, so a subject lasts weeks instead of one sitting.
|
|
11
|
+
|
|
12
|
+
## Requirements
|
|
13
|
+
|
|
14
|
+
- DeepSeek Harness with a profile.
|
|
15
|
+
- Node.js 22.19 or newer.
|
|
16
|
+
- Windows, macOS, or Linux.
|
|
17
|
+
|
|
18
|
+
## Install
|
|
19
|
+
|
|
20
|
+
From npm:
|
|
21
|
+
|
|
22
|
+
```powershell
|
|
23
|
+
dsh plugin --profile <profile> add dsh-nerd-mode
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
From GitHub:
|
|
27
|
+
|
|
28
|
+
```powershell
|
|
29
|
+
dsh plugin --profile <profile> add github:bocchii-the-code/dsh-nerd-mode
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
From a local folder or tarball:
|
|
33
|
+
|
|
34
|
+
```powershell
|
|
35
|
+
dsh plugin --profile <profile> add C:\path\to\dsh-nerd-mode
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Restart dsh. Every mode gains the `/nerd-mode` command and a `Nerd mode` pill in the composer bar. The mode picker gains no new entry: the plugin mounts at profile level, not as a preset.
|
|
39
|
+
|
|
40
|
+
## Usage
|
|
41
|
+
|
|
42
|
+
Two skills, two sizes. Both teach one thing at a time and both stop to ask. They differ in what they keep.
|
|
43
|
+
|
|
44
|
+
### Quick lesson: `/study`
|
|
45
|
+
|
|
46
|
+
**What it does.** Walks one concept or one task from the first step to the last, and stops once at the fork: the point where the choice changes the result. For a concept it explains in layers, from intuition to terms to formal detail. For a task it produces the artifact and writes one line of reason beside each step. It reads no file and writes no file, so it works in any folder and leaves nothing behind.
|
|
47
|
+
|
|
48
|
+
**When to use it.** A question you want to understand now and will probably not return to.
|
|
49
|
+
|
|
50
|
+
- Reading a paper and a term stops you.
|
|
51
|
+
- A homework problem you have to finish tonight.
|
|
52
|
+
- A file whose logic you need to follow before you change it.
|
|
53
|
+
- A small decision where you want the trade-off spelled out before you pick.
|
|
54
|
+
|
|
55
|
+
**How to use it.**
|
|
56
|
+
|
|
57
|
+
```text
|
|
58
|
+
/study why does Adam divide by 1 - beta^t
|
|
59
|
+
/study walk me through the preconditioner in this file # with code
|
|
60
|
+
/study help me finish problem 3, and explain each step # with homework
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Type the command, or turn the switch on and just ask. With the switch on, a learning-shaped request gets this shape by default.
|
|
64
|
+
|
|
65
|
+
**What you get.** A title, the central idea, numbered steps, and a symbol table when the symbols get dense. One worked example, the common mistake, and the single stop at the fork. For a task, the finished artifact with its reasoning.
|
|
66
|
+
|
|
67
|
+
**What it does not do.** No file appears, and nothing is scored. None of it survives the conversation.
|
|
68
|
+
|
|
69
|
+
### Long lesson: `/study-plus`
|
|
70
|
+
|
|
71
|
+
**What it does.** Builds a concept graph for one topic, then teaches one concept per session against a record of what you have already demonstrated. The record is four markdown files in the workspace. Every session reads them before the first line, updates them at the end, and dates every claim about what you know.
|
|
72
|
+
|
|
73
|
+
**When to use it.** A subject you will still be learning next month.
|
|
74
|
+
|
|
75
|
+
- You are working through a textbook, a course, or a paper properly.
|
|
76
|
+
- You want to know what to study next, and a chat only answers what you ask.
|
|
77
|
+
- You want evidence of progress, not an impression of it.
|
|
78
|
+
- You keep looking things up and forgetting them.
|
|
79
|
+
|
|
80
|
+
**How to use it.** First session, later sessions, and the target.
|
|
81
|
+
|
|
82
|
+
```text
|
|
83
|
+
/study-plus Shampoo and Adam optimizers # first session builds the graph
|
|
84
|
+
/study-plus # later sessions continue the topic
|
|
85
|
+
/study-plus I want to reach the matrix square root # set a target
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
First session: it proposes 15 to 30 concepts with prerequisite links and waits. You approve or edit one row, then name what you already know well enough to skip. Then it teaches one concept in five steps: recall one earlier concept cold, teach to completion, three unseen questions, a teach-back, and a dated record.
|
|
89
|
+
|
|
90
|
+
Later sessions read the four files first, so the first line names the next concept, the reason, and the date of the evidence behind it.
|
|
91
|
+
|
|
92
|
+
**What you get.** A concept order, one concept taught to completion, a graded check, and a record that survives restarts.
|
|
93
|
+
|
|
94
|
+
**What it does not do.** It schedules no reviews and never guesses that you know something. Only an answer you produced changes the record.
|
|
95
|
+
|
|
96
|
+
### What each one leaves behind
|
|
97
|
+
|
|
98
|
+
| | `/study`, quick lesson | `/study-plus`, long lesson |
|
|
99
|
+
|---|---|---|
|
|
100
|
+
| Writes files | none | `study/<topic>/`: `graph.md`, `state.md`, `log.md`, `plan.md` |
|
|
101
|
+
| Reads files | none | those four, before the first line |
|
|
102
|
+
| Remembered next session | no | yes, with dates |
|
|
103
|
+
| Graded | no | pass and miss, rubric written first |
|
|
104
|
+
| Typical span | one sitting, one idea | 15 to 30 concepts over weeks |
|
|
105
|
+
|
|
106
|
+
If a `study/` folder appears in your workspace, that was `/study-plus`. `/study` never creates one.
|
|
107
|
+
|
|
108
|
+
### Which one
|
|
109
|
+
|
|
110
|
+
- A question you will not return to: `/study`.
|
|
111
|
+
- A subject you will return to for weeks: `/study-plus`.
|
|
112
|
+
- Started with `/study` and keep coming back? Move up. Build the graph once, and the earlier conversation still informs it.
|
|
113
|
+
|
|
114
|
+
An example. You are reading the Shampoo paper and hit the preconditioner. `/study what does the Shampoo preconditioner actually do` settles it in one sitting. If you decide to read the paper properly over a month, open `/study-plus Shampoo and Adam optimizers` and let it order the concepts first.
|
|
115
|
+
|
|
116
|
+
### Commands
|
|
117
|
+
|
|
118
|
+
```text
|
|
119
|
+
/nerd-mode on teaching posture for this conversation
|
|
120
|
+
/nerd-mode off
|
|
121
|
+
/study <concept or task>
|
|
122
|
+
/study-plus <topic> recorded session with the four study files
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
The pill in the composer bar sends `/nerd-mode`. It sits left of Full Throttle, stays visible in both states, and goes dim when off.
|
|
126
|
+
|
|
127
|
+
## What the switch does
|
|
128
|
+
|
|
129
|
+
- It changes text, not tools. The tool set and the prompt cache stay stable.
|
|
130
|
+
- Teaching applies to learning-shaped requests only: explain a concept, tutor homework, walk through code, prepare for an exam. A feature request, a search, a config edit, or a command runs as usual.
|
|
131
|
+
- The switch is per conversation. Its state lives in the session log, so compaction and resume keep it.
|
|
132
|
+
- If the command fails, a toast at the top of the window names the reason, and the pill keeps its state.
|
|
133
|
+
- Subagents run their own session, so each starts with the switch off.
|
|
134
|
+
- It cannot delete a base mode's persona text. It outranks that text by declaration.
|
|
135
|
+
|
|
136
|
+
## Skills included
|
|
137
|
+
|
|
138
|
+
- `study`: the guide. No file, no grade.
|
|
139
|
+
- `study-plus`: the recorded session. Five steps, concept graph, evidence log.
|
|
140
|
+
- `diagram`: one SVG figure per idea. Written for this package.
|
|
141
|
+
- `answer-me-with-html`: one-page HTML explainers, by QingYunA.
|
|
142
|
+
- `teach`: a dated teaching workspace, by Matt Pocock.
|
|
143
|
+
- `writing-beats`: beat-by-beat article structure, by Matt Pocock.
|
|
144
|
+
- `humanizer`: rewrite AI-sounding prose, by Siqi Chen.
|
|
145
|
+
- `convert-documents-to-markdown`: Word, PDF, and ebook conversion, by firecrawl.
|
|
146
|
+
|
|
147
|
+
## Notes
|
|
148
|
+
|
|
149
|
+
- The plugin loads its own `skills/` folder from `cordis.patch.yml` with a `!!js` expression. Review patch changes as host-process code.
|
|
150
|
+
- If you rename the package, update the `resolve('dsh-nerd-mode/package.json')` string in `cordis.patch.yml`.
|
|
151
|
+
- Bundled third-party skills keep their own licenses. See [NOTICE.md](./NOTICE.md).
|
|
152
|
+
- Design notes: [SPEC.md](./SPEC.md), [GLOSSARY.md](./GLOSSARY.md), `docs/adr/`.
|
|
153
|
+
- Tested with `@deepseek-ai/dsh` 0.2.1-rc.3 on Node 22.
|
|
154
|
+
|
|
155
|
+
## Uninstall
|
|
156
|
+
|
|
157
|
+
```powershell
|
|
158
|
+
dsh plugin --profile <profile> remove dsh-nerd-mode
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## License
|
|
162
|
+
|
|
163
|
+
MIT. Bundled skills keep their own licenses; see [NOTICE.md](./NOTICE.md).
|
package/README.zh.md
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
[](./README.md) [](./README.zh.md)
|
|
2
|
+
|
|
3
|
+
<picture>
|
|
4
|
+
<source media="(prefers-color-scheme: dark)" srcset="assets/icon-dark.svg">
|
|
5
|
+
<img src="assets/icon-light.svg" width="120" height="120" alt="Nerd Mode">
|
|
6
|
+
</picture>
|
|
7
|
+
|
|
8
|
+
# Nerd Mode:dsh 学习开关
|
|
9
|
+
|
|
10
|
+
聊天里的学习通常在答案到达时就结束了:没有检验,也留不下任何东西。Nerd Mode 改的是 dsh 面对一个问题时做的事。它一步一步地教,在该做选择的地方停下来,并且能留下带日期的记录,让一个主题活过几周,而不只是一次对话。
|
|
11
|
+
|
|
12
|
+
## 运行环境
|
|
13
|
+
|
|
14
|
+
- 装有 profile 的 DeepSeek Harness。
|
|
15
|
+
- Node.js 22.19 或更新。
|
|
16
|
+
- Windows、macOS 或 Linux。
|
|
17
|
+
|
|
18
|
+
## 安装
|
|
19
|
+
|
|
20
|
+
从 npm:
|
|
21
|
+
|
|
22
|
+
```powershell
|
|
23
|
+
dsh plugin --profile <profile> add dsh-nerd-mode
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
从 GitHub:
|
|
27
|
+
|
|
28
|
+
```powershell
|
|
29
|
+
dsh plugin --profile <profile> add github:bocchii-the-code/dsh-nerd-mode
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
从本地目录或压缩包:
|
|
33
|
+
|
|
34
|
+
```powershell
|
|
35
|
+
dsh plugin --profile <profile> add C:\path\to\dsh-nerd-mode
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
重启 dsh。每个模式都会多出 `/nerd-mode` 命令,输入框工具栏多一个 `Nerd mode` 胶囊。模式选择器不会多出新条目:插件挂在 profile 层,不是预设。
|
|
39
|
+
|
|
40
|
+
## 使用方法
|
|
41
|
+
|
|
42
|
+
两个技能,两种尺度。都一次只讲一件事,都会停下来问你。区别在于它们留下什么。
|
|
43
|
+
|
|
44
|
+
### 快速课程:`/study`
|
|
45
|
+
|
|
46
|
+
**它做什么。** 把一个概念或一个任务从第一步走到最后一步,只在分叉点停一次:那里换个选择,结果就不一样。概念按层次讲,先直觉,再术语,最后形式细节。任务则直接产出,每一步旁边写一行理由。它不读文件也不写文件,所以在任何文件夹里都能用,用完什么都不留。
|
|
47
|
+
|
|
48
|
+
**什么时候用它。** 现在就想弄懂、之后大概不会再回来的问题。
|
|
49
|
+
|
|
50
|
+
- 读论文卡在一个术语上。
|
|
51
|
+
- 今晚必须交的一道作业。
|
|
52
|
+
- 改代码之前,要先把这段逻辑理顺。
|
|
53
|
+
- 一个不大的选择,想先看清取舍再决定。
|
|
54
|
+
|
|
55
|
+
**怎么用。**
|
|
56
|
+
|
|
57
|
+
```text
|
|
58
|
+
/study 为什么 Adam 要除以 1 - β^t
|
|
59
|
+
/study 帮我把这个文件里的预条件子讲清楚 # 带代码
|
|
60
|
+
/study 帮我把第三题做完,每一步都说原因 # 带作业
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
敲命令,或者打开开关直接问。开关打开时,学习类的请求默认就是这个形状。
|
|
64
|
+
|
|
65
|
+
**你会拿到什么。** 标题、中心思想、编号步骤,符号多时再加一张符号表。一个具体例子、常见错误,以及在分叉处停的那一次。任务是另外给你做完的东西和每一步的理由。
|
|
66
|
+
|
|
67
|
+
**它不做什么。** 不会出现任何文件,也不打分。对话一结束,它就什么都不记得了。
|
|
68
|
+
|
|
69
|
+
### 长课程:`/study-plus`
|
|
70
|
+
|
|
71
|
+
**它做什么。** 为一个主题建一张概念图,然后每次会话只教一个概念,对着"你已经做出来过什么"的记录来教。记录是工作区里的四个 markdown 文件。每次开口前先读,每次结束时写,凡是说你会的句子都带日期。
|
|
72
|
+
|
|
73
|
+
**什么时候用它。** 下个月你还在学的东西。
|
|
74
|
+
|
|
75
|
+
- 认真读一本教材、一门课或一篇论文。
|
|
76
|
+
- 需要知道下一步该学什么,而不只是现在该问什么。
|
|
77
|
+
- 想要进度的证据,而不是感觉。
|
|
78
|
+
- 你总在反复查同一批东西,查完就忘。
|
|
79
|
+
|
|
80
|
+
**怎么用。** 第一次、之后、以及设目标。
|
|
81
|
+
|
|
82
|
+
```text
|
|
83
|
+
/study-plus 洗发水与 Adam 优化器 # 第一次建图
|
|
84
|
+
/study-plus # 之后继续同一话题
|
|
85
|
+
/study-plus 我想学到矩阵平方根 # 设一个目标
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
第一次:它给出 15 到 30 个概念和前置关系,等你确认。你删改一行,再说哪些你已经会了可以跳过。然后它一次教一个概念,五步走:先冷问一个旧概念、讲到完整、三道没见过的题、一次复述、写一条带日期的记录。
|
|
89
|
+
|
|
90
|
+
之后的会话先读那四个文件,所以开口第一句就是下一个概念是什么、为什么是它、支撑它的证据是哪一天。
|
|
91
|
+
|
|
92
|
+
**你会拿到什么。** 一个概念顺序、一个讲透的概念、一次批改过的检验,以及重启也还在的记录。
|
|
93
|
+
|
|
94
|
+
**它不做什么。** 不排复习时间表,也不猜你会什么。只有你自己做出来的答案才能改变记录。
|
|
95
|
+
|
|
96
|
+
### 两者会留下什么
|
|
97
|
+
|
|
98
|
+
| | `/study` 快速课程 | `/study-plus` 长课程 |
|
|
99
|
+
|---|---|---|
|
|
100
|
+
| 写文件 | 没有 | `study/<主题>/` 下四个文件 |
|
|
101
|
+
| 读文件 | 没有 | 开口前先读那四个 |
|
|
102
|
+
| 下次还记得 | 不记得 | 记得,带日期 |
|
|
103
|
+
| 批改 | 不批 | 先写评分标准,再判 pass 和 miss |
|
|
104
|
+
| 典型长度 | 一次坐完,一个概念 | 15 到 30 个概念,跨几周 |
|
|
105
|
+
|
|
106
|
+
工作区里如果出现 `study/` 文件夹,那是 `/study-plus` 做的。`/study` 从不创建它。
|
|
107
|
+
|
|
108
|
+
### 怎么选
|
|
109
|
+
|
|
110
|
+
- 问完就不会再回来的问题,用 `/study`。
|
|
111
|
+
- 要连着几周的东西,用 `/study-plus`。
|
|
112
|
+
- 先用 `/study`,发现自己一直在回来,就升档。概念图建一次,之前聊过的内容照样用得上。
|
|
113
|
+
|
|
114
|
+
举个例子。你在读 Shampoo 那篇论文,卡在预条件子上。`/study Shampoo 的预条件子到底在做什么`,一次坐完。如果你决定认真读完这篇论文,就开 `/study-plus 洗发水与 Adam 优化器`,让它先把顺序排出来。
|
|
115
|
+
|
|
116
|
+
### 命令
|
|
117
|
+
|
|
118
|
+
```text
|
|
119
|
+
/nerd-mode on 这次对话进入教学姿势
|
|
120
|
+
/nerd-mode off
|
|
121
|
+
/study <概念或任务>
|
|
122
|
+
/study-plus <主题> 带四个学习文件的记录型会话
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
输入框工具栏里的胶囊发的就是 `/nerd-mode`。它排在 Full Throttle 左边,一直显示,关闭时变暗。
|
|
126
|
+
|
|
127
|
+
## 开关做了什么
|
|
128
|
+
|
|
129
|
+
- 它改的是文字,不是工具。工具目录和提示缓存都不变。
|
|
130
|
+
- 只对学习类请求生效:讲清概念、辅导作业、讲解代码、准备考试。写功能、查资料、改配置、跑命令照常。
|
|
131
|
+
- 开关只作用于这一次会话。状态存在会话日志里,压缩上下文、恢复会话都不丢。
|
|
132
|
+
- 命令执行失败时,窗口顶部会弹一条说明原因的提示,胶囊保持原状态。
|
|
133
|
+
- 子代理各自跑自己的会话,所以默认都是关闭的。
|
|
134
|
+
- 它删不掉基础模式的人格文字,只能声明自己的规则优先。
|
|
135
|
+
|
|
136
|
+
## 内置技能
|
|
137
|
+
|
|
138
|
+
- `study`:引导式讲解。不写文件,不打分。
|
|
139
|
+
- `study-plus`:记录型会话。五步、概念图、证据日志。
|
|
140
|
+
- `diagram`:一个概念一张 SVG 图。为本包编写。
|
|
141
|
+
- `answer-me-with-html`:一页式 HTML 图解,作者 QingYunA。
|
|
142
|
+
- `teach`:带日期的教学工作区,作者 Matt Pocock。
|
|
143
|
+
- `writing-beats`:逐拍结构的文章写法,作者 Matt Pocock。
|
|
144
|
+
- `humanizer`:把 AI 味的文字改回人话,作者 Siqi Chen。
|
|
145
|
+
- `convert-documents-to-markdown`:Word、PDF、电子书转换,作者 firecrawl。
|
|
146
|
+
|
|
147
|
+
## 说明
|
|
148
|
+
|
|
149
|
+
- 插件用 `!!js` 表达式从 `cordis.patch.yml` 加载自己的 `skills/` 目录。补丁是宿主进程代码,改之前先读。
|
|
150
|
+
- 如果你改了包名,记得同步 `cordis.patch.yml` 里的 `resolve('dsh-nerd-mode/package.json')`。
|
|
151
|
+
- 随包的第三方技能各自保留许可,见 [NOTICE.md](./NOTICE.md)。
|
|
152
|
+
- 设计记录:[SPEC.md](./SPEC.md)、[GLOSSARY.md](./GLOSSARY.md)、`docs/adr/`。
|
|
153
|
+
- 在 `@deepseek-ai/dsh` 0.2.1-rc.3 和 Node 22 上测过。
|
|
154
|
+
|
|
155
|
+
## 卸载
|
|
156
|
+
|
|
157
|
+
```powershell
|
|
158
|
+
dsh plugin --profile <profile> remove dsh-nerd-mode
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## 许可
|
|
162
|
+
|
|
163
|
+
MIT。随包的第三方技能各自保留许可,见 [NOTICE.md](./NOTICE.md)。
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 120 120" role="img" aria-label="Nerd Mode">
|
|
2
|
+
<path d="M12 112 C15 100 24 94 39 90 C35 84 32 78 29 73 C26 68 28 64 32 61 L35 58 L35 18 C35 10 39 7 44 7 C49 7 53 11 53 18 L53 49 C57 43 62 42 65 46 C69 50 66 55 63 59 L59 63 C65 60 70 61 72 65 C74 69 71 74 67 78 C63 82 62 87 63 91 C65 87 68 82 69 76 C70 68 68 61 68 52 C68 42 72 34 79 28 C87 22 98 23 105 31 C111 38 114 48 112 60 C110 75 103 85 92 89 C105 93 114 101 117 112 L117 116 L12 116 Z" fill="none" stroke="#f0f6fc" stroke-width="4.6" stroke-linecap="round" stroke-linejoin="round"/>
|
|
3
|
+
<path d="M77 48 C77 45 80 43 84 43 L87 43 C91 43 93 46 93 50 L93 55 C93 59 90 62 86 62 L82 62 C79 62 77 59 77 56 Z M99 48 C99 45 102 43 106 43 L109 43 C113 43 115 46 115 50 L115 55 C115 59 112 62 108 62 L104 62 C101 62 99 59 99 56 Z" fill="#2f81f7" stroke="#f0f6fc" stroke-width="4.2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
4
|
+
<path d="M93 51 L99 51" fill="none" stroke="#f0f6fc" stroke-width="4" stroke-linecap="round"/>
|
|
5
|
+
</svg>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 120 120" role="img" aria-label="Nerd Mode">
|
|
2
|
+
<path d="M12 112 C15 100 24 94 39 90 C35 84 32 78 29 73 C26 68 28 64 32 61 L35 58 L35 18 C35 10 39 7 44 7 C49 7 53 11 53 18 L53 49 C57 43 62 42 65 46 C69 50 66 55 63 59 L59 63 C65 60 70 61 72 65 C74 69 71 74 67 78 C63 82 62 87 63 91 C65 87 68 82 69 76 C70 68 68 61 68 52 C68 42 72 34 79 28 C87 22 98 23 105 31 C111 38 114 48 112 60 C110 75 103 85 92 89 C105 93 114 101 117 112 L117 116 L12 116 Z" fill="none" stroke="#1f2328" stroke-width="4.6" stroke-linecap="round" stroke-linejoin="round"/>
|
|
3
|
+
<path d="M77 48 C77 45 80 43 84 43 L87 43 C91 43 93 46 93 50 L93 55 C93 59 90 62 86 62 L82 62 C79 62 77 59 77 56 Z M99 48 C99 45 102 43 106 43 L109 43 C113 43 115 46 115 50 L115 55 C115 59 112 62 108 62 L104 62 C101 62 99 59 99 56 Z" fill="#2f81f7" stroke="#1f2328" stroke-width="4.2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
4
|
+
<path d="M93 51 L99 51" fill="none" stroke="#1f2328" stroke-width="4" stroke-linecap="round"/>
|
|
5
|
+
</svg>
|
package/client.js
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
window.__ModuleLoader__.load({
|
|
2
|
+
id: 'dsh-nerd-mode/client',
|
|
3
|
+
factory(require) {
|
|
4
|
+
const React = require('react');
|
|
5
|
+
const { Toast } = require('@deepseek-ai/dsh-client-ui-primitives');
|
|
6
|
+
|
|
7
|
+
const SLOT = 'conversation.input.left';
|
|
8
|
+
const LABEL = 'Nerd mode';
|
|
9
|
+
|
|
10
|
+
// 16px book, same footprint as the Full Throttle bolt.
|
|
11
|
+
const BOOK = React.createElement(
|
|
12
|
+
'svg',
|
|
13
|
+
{
|
|
14
|
+
'aria-hidden': 'true',
|
|
15
|
+
fill: 'none',
|
|
16
|
+
height: 16,
|
|
17
|
+
stroke: 'currentColor',
|
|
18
|
+
strokeLinecap: 'round',
|
|
19
|
+
strokeLinejoin: 'round',
|
|
20
|
+
strokeWidth: 1.6,
|
|
21
|
+
viewBox: '0 0 16 16',
|
|
22
|
+
width: 16,
|
|
23
|
+
},
|
|
24
|
+
React.createElement('path', {
|
|
25
|
+
d: 'M2.5 3.2A1.7 1.7 0 0 1 4.2 1.5H7.5v11H4.2a1.7 1.7 0 0 0-1.7 1.7z',
|
|
26
|
+
}),
|
|
27
|
+
React.createElement('path', {
|
|
28
|
+
d: 'M13.5 3.2a1.7 1.7 0 0 0-1.7-1.7H8.5v11h3.3a1.7 1.7 0 0 1 1.7 1.7z',
|
|
29
|
+
}),
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
// The theme owns the colors; only the state picks which alias to read.
|
|
33
|
+
function pillStyle(active) {
|
|
34
|
+
if (active) {
|
|
35
|
+
const business = 'var(--dsw-alias-state-business-primary)';
|
|
36
|
+
return {
|
|
37
|
+
background: `color-mix(in srgb, ${business} 16%, transparent)`,
|
|
38
|
+
boxShadow: `inset 0 0 0 1px color-mix(in srgb, ${business} 55%, transparent)`,
|
|
39
|
+
color: business,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
background: 'var(--dsw-alias-fill-tsp-secondary)',
|
|
44
|
+
boxShadow: 'none',
|
|
45
|
+
color: 'var(--dsw-alias-label-tertiary)',
|
|
46
|
+
opacity: 0.65,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Unknown commands resolve as { ok: true, value: undefined }; they never
|
|
51
|
+
// reach the command executor and write nothing to the session log.
|
|
52
|
+
function failureText(result) {
|
|
53
|
+
if (!result?.ok) {
|
|
54
|
+
return `Nerd mode did not switch: ${result?.error?.message ?? 'the host rejected the command'}`;
|
|
55
|
+
}
|
|
56
|
+
if (result.value == null) {
|
|
57
|
+
return 'Nerd mode did not switch: /nerd-mode is not available in this build.';
|
|
58
|
+
}
|
|
59
|
+
const outcome = result.value.result;
|
|
60
|
+
if (outcome?.kind === 'error') {
|
|
61
|
+
return `Nerd mode did not switch: ${outcome.text ?? 'the command failed'}`;
|
|
62
|
+
}
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function NerdModeToggle({ useProjection, execute }) {
|
|
67
|
+
const state = useProjection('studyMode');
|
|
68
|
+
const active = state?.active === true;
|
|
69
|
+
const [busy, setBusy] = React.useState(false);
|
|
70
|
+
const [failure, setFailure] = React.useState(null);
|
|
71
|
+
const [toast, setToast] = React.useState(null);
|
|
72
|
+
|
|
73
|
+
React.useEffect(() => {
|
|
74
|
+
setFailure(null);
|
|
75
|
+
setToast(null);
|
|
76
|
+
}, [active]);
|
|
77
|
+
|
|
78
|
+
const onClick = async () => {
|
|
79
|
+
if (busy) return;
|
|
80
|
+
setBusy(true);
|
|
81
|
+
setFailure(null);
|
|
82
|
+
setToast(null);
|
|
83
|
+
try {
|
|
84
|
+
const result = await execute(active ? '/nerd-mode off' : '/nerd-mode on');
|
|
85
|
+
const text = failureText(result);
|
|
86
|
+
if (text !== null) {
|
|
87
|
+
setFailure(text);
|
|
88
|
+
setToast({ id: Date.now(), text });
|
|
89
|
+
}
|
|
90
|
+
} catch (error) {
|
|
91
|
+
const text = `Nerd mode did not switch: ${error?.message ?? 'the host rejected the command'}`;
|
|
92
|
+
setFailure(text);
|
|
93
|
+
setToast({ id: Date.now(), text });
|
|
94
|
+
} finally {
|
|
95
|
+
setBusy(false);
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
return React.createElement(
|
|
100
|
+
React.Fragment,
|
|
101
|
+
null,
|
|
102
|
+
React.createElement(
|
|
103
|
+
'button',
|
|
104
|
+
{
|
|
105
|
+
type: 'button',
|
|
106
|
+
role: 'switch',
|
|
107
|
+
'aria-checked': active,
|
|
108
|
+
'aria-label': LABEL,
|
|
109
|
+
'data-state': active ? 'on' : 'off',
|
|
110
|
+
title: failure ?? (active ? 'Nerd mode is on' : 'Nerd mode is off'),
|
|
111
|
+
disabled: busy,
|
|
112
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
113
|
+
onClick,
|
|
114
|
+
style: {
|
|
115
|
+
alignItems: 'center',
|
|
116
|
+
border: 'none',
|
|
117
|
+
borderRadius: 'var(--dsw-radius-sm)',
|
|
118
|
+
cursor: busy ? 'progress' : 'pointer',
|
|
119
|
+
display: 'inline-flex',
|
|
120
|
+
fontFamily: 'inherit',
|
|
121
|
+
fontSize: 13,
|
|
122
|
+
fontWeight: 500,
|
|
123
|
+
gap: 6,
|
|
124
|
+
height: 28,
|
|
125
|
+
lineHeight: '20px',
|
|
126
|
+
padding: '0 8px',
|
|
127
|
+
transition: 'background 120ms ease, color 120ms ease',
|
|
128
|
+
...pillStyle(active),
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
BOOK,
|
|
132
|
+
React.createElement('span', null, LABEL),
|
|
133
|
+
),
|
|
134
|
+
toast === null
|
|
135
|
+
? null
|
|
136
|
+
: React.createElement(Toast, {
|
|
137
|
+
key: toast.id,
|
|
138
|
+
text: toast.text,
|
|
139
|
+
onDone: () => setToast(null),
|
|
140
|
+
}),
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return {
|
|
145
|
+
inject: ['slots', 'remote.commands'],
|
|
146
|
+
apply(ctx) {
|
|
147
|
+
ctx.slots.inject(SLOT, () =>
|
|
148
|
+
ctx.slots.register({
|
|
149
|
+
name: SLOT,
|
|
150
|
+
id: 'nerd-mode',
|
|
151
|
+
order: -1,
|
|
152
|
+
registrant: 'dsh-nerd-mode',
|
|
153
|
+
inject: (sessionId) => ({
|
|
154
|
+
execute: (command) => ctx.remote.commands.execute(sessionId, command, []),
|
|
155
|
+
}),
|
|
156
|
+
}, NerdModeToggle),
|
|
157
|
+
);
|
|
158
|
+
},
|
|
159
|
+
};
|
|
160
|
+
},
|
|
161
|
+
});
|
package/cordis.patch.yml
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Nerd mode is a profile-level plugin, not a preset. See docs/adr/0008.
|
|
2
|
+
- insert:
|
|
3
|
+
- id: dsh-nerd-mode
|
|
4
|
+
name: dsh-nerd-mode
|
|
5
|
+
config:
|
|
6
|
+
section: |
|
|
7
|
+
Nerd mode is on for this conversation. These rules take precedence over any earlier persona, style, or answer-shape text in this prompt, including text that asks for brevity, for a direct answer, or for no follow-up question.
|
|
8
|
+
|
|
9
|
+
A learning-shaped request gets the guided shape. Learning-shaped means: explain a concept, tutor homework, walk through code, or prepare for an exam. Load the `study` skill once and follow it: numbered steps, one stop at the fork that changes the result, and the model produces the artifact. Write no file. Read no `study/` file. Do not grade, score, or log.
|
|
10
|
+
|
|
11
|
+
Every other request keeps the base mode's behavior: produce the artifact, run the command, make the edit. Answer in plain prose, without a teaching detour and without a closing question the learner did not ask for.
|
|
12
|
+
|
|
13
|
+
A request for a dated, recorded session is `/study-plus`. Say so once, and wait.
|
|
14
|
+
- id: study-plus-skills
|
|
15
|
+
name: '@deepseek-ai/dsh-skill-filesystem'
|
|
16
|
+
config:
|
|
17
|
+
providerName: study-plus
|
|
18
|
+
includeDefaultRoots: false
|
|
19
|
+
bundledSkillDir: !!js process.getBuiltinModule('node:path').join(process.getBuiltinModule('node:path').dirname(process.getBuiltinModule('node:module').createRequire(baseUrl).resolve('dsh-nerd-mode/package.json')), 'skills')
|
package/lib/fold.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Nerd mode state machine, kept free of host imports so it can be tested
|
|
3
|
+
* with plain node. State folds the session log: `command/run` records the
|
|
4
|
+
* request, `command/done` commits it. Nothing else is written, because an
|
|
5
|
+
* unknown stored event type stops a session from reopening.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// Stored state keeps `studyMode`; renaming it would orphan every session that
|
|
9
|
+
// already holds a value. See ADR 0009.
|
|
10
|
+
export const KEY = 'studyMode'
|
|
11
|
+
export const COMMAND = 'nerd-mode'
|
|
12
|
+
|
|
13
|
+
/** @returns {{ active: boolean, running: { commandId: string, wanted: boolean } | null }} */
|
|
14
|
+
export function init() {
|
|
15
|
+
return { active: false, running: null }
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Fold one session event into the state.
|
|
20
|
+
* @param state - current state; never mutated
|
|
21
|
+
* @param event - a session log event
|
|
22
|
+
* @returns the next state, or the same object when the event is unrelated
|
|
23
|
+
*/
|
|
24
|
+
export function fold(state, event) {
|
|
25
|
+
const data = event?.data
|
|
26
|
+
|
|
27
|
+
if (event?.type === 'command/run' && data?.name === COMMAND) {
|
|
28
|
+
// A bare /nerd-mode means on, matching /plan.
|
|
29
|
+
const wanted = (data.args ?? 'on').trim().toLowerCase() !== 'off'
|
|
30
|
+
return { ...state, running: { commandId: data.commandId, wanted } }
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (event?.type === 'command/done' && data?.commandId === state.running?.commandId) {
|
|
34
|
+
const { wanted } = state.running
|
|
35
|
+
return { ...state, active: data.kind === 'success' ? wanted : state.active, running: null }
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return state
|
|
39
|
+
}
|