dsh-thesis 1.0.0 → 2.0.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/LICENSE +21 -21
- package/NOTICE.md +1 -1
- package/README.md +48 -204
- package/docs/autopilot.md +73 -0
- package/docs/config.md +113 -0
- package/{DESIGN.md → docs/design.md} +94 -73
- package/docs/host-api.md +728 -640
- package/docs/release.md +126 -0
- package/docs/tools.md +76 -0
- package/docs/troubleshooting.md +88 -0
- package/docs/usage.md +87 -0
- package/lib/autopilot/index.d.ts +38 -0
- package/lib/autopilot/index.js +159 -0
- package/lib/autopilot/intent.d.ts +40 -0
- package/lib/autopilot/intent.js +82 -0
- package/lib/autopilot/messages.d.ts +22 -0
- package/lib/autopilot/messages.js +35 -0
- package/lib/autopilot/types.d.ts +60 -0
- package/lib/autopilot/types.js +10 -0
- package/lib/codewalk/engine.d.ts +1 -1
- package/lib/codewalk/engine.js +1 -1
- package/lib/codewalk/gate.d.ts +1 -1
- package/lib/codewalk/gate.js +1 -1
- package/lib/codewalk/host-types.d.ts +4 -31
- package/lib/codewalk/prestep.js +1 -1
- package/lib/codewalk/tools.js +2 -2
- package/lib/config.d.ts +17 -0
- package/lib/config.js +9 -1
- package/lib/dedup/index.js +0 -6
- package/lib/gates/messages.d.ts +7 -3
- package/lib/gates/messages.js +7 -4
- package/lib/index.d.ts +3 -1
- package/lib/index.js +10 -7
- package/lib/ingest/index.d.ts +1 -1
- package/lib/ingest/index.js +1 -3
- package/lib/intake/gate-rules.d.ts +6 -5
- package/lib/intake/gate-rules.js +6 -2
- package/lib/intake/index.d.ts +0 -17
- package/lib/intake/index.js +0 -51
- package/lib/intake/questions.d.ts +1 -1
- package/lib/intake/questions.js +1 -1
- package/lib/paper/lib/docx.js +70 -70
- package/lib/paper/lib/layout.d.ts +1 -1
- package/lib/paper/lib/layout.js +372 -372
- package/lib/paper/lib/ledger.d.ts +1 -1
- package/lib/paper/lib/ledger.js +1 -1
- package/lib/paper/lib/lit-cache.js +7 -7
- package/lib/paper/register.d.ts +2 -2
- package/lib/paper/register.js +2 -8
- package/lib/paper/tools/decision.js +5 -5
- package/lib/paper/tools/init.d.ts +1 -1
- package/lib/paper/tools/init.js +1 -1
- package/lib/paper/tools/lit.js +32 -32
- package/lib/ppt/index.d.ts +1 -2
- package/lib/ppt/index.js +1 -2
- package/lib/shared/define-tool.d.ts +1 -1
- package/lib/shared/define-tool.js +1 -1
- package/package.json +26 -21
- package/skills/code-walkthrough/SKILL.md +5 -3
- package/skills/thesis-defense/SKILL.md +1 -1
- package/skills/thesis-pipeline/SKILL.md +3 -3
- package/lib/codewalk/commands.d.ts +0 -23
- package/lib/codewalk/commands.js +0 -168
- package/lib/commands.d.ts +0 -33
- package/lib/commands.js +0 -60
- package/lib/dedup/commands.d.ts +0 -21
- package/lib/dedup/commands.js +0 -93
- package/lib/ingest/commands.d.ts +0 -23
- package/lib/ingest/commands.js +0 -74
- package/lib/paper/commands.d.ts +0 -13
- package/lib/paper/commands.js +0 -84
- package/lib/ppt/commands.d.ts +0 -28
- package/lib/ppt/commands.js +0 -71
package/docs/release.md
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# 发布
|
|
2
|
+
|
|
3
|
+
发版由 GitHub Actions 完成([`.github/workflows/publish.yml`](../.github/workflows/publish.yml))。
|
|
4
|
+
**打 tag 即发布**,本地不需要 `npm login`,也不需要任何 npm token。
|
|
5
|
+
|
|
6
|
+
认证走 **Trusted Publishing(OIDC 可信发布)**:npm 只接受「这个仓库的这个 workflow」发来的包,
|
|
7
|
+
凭据是每次运行临时签发的,不落盘、不过期、也没有 2FA 输 OTP 的问题;provenance 由 npm 自动附上。
|
|
8
|
+
|
|
9
|
+
## 一次性设置(只做一次)
|
|
10
|
+
|
|
11
|
+
1. 打开 <https://www.npmjs.com/package/dsh-thesis/access> → **Trusted Publishers** →
|
|
12
|
+
**Select publisher: GitHub Actions**,填四个字段:
|
|
13
|
+
|
|
14
|
+
| 字段 | 填什么 |
|
|
15
|
+
|---|---|
|
|
16
|
+
| Organization or user | `booondenz` |
|
|
17
|
+
| Repository | `dsh-thesis` |
|
|
18
|
+
| Workflow filename | `publish.yml`(只写文件名,不带路径)|
|
|
19
|
+
| Environment name | **留空**(除非 workflow 里写了 `environment:`)|
|
|
20
|
+
|
|
21
|
+
2. 确认仓库是 **public**:私有仓库发不出 provenance。
|
|
22
|
+
3. 不需要 `NPM_TOKEN`,**之前建过的话建议在 Settings → Secrets 里删掉**,免得以后误用。
|
|
23
|
+
|
|
24
|
+
> 配置要先「验证」过一次才算生效:2026-10 起,长期没成功发布过的可信发布配置会自动过期。
|
|
25
|
+
> 所以配完就立刻发一次版。
|
|
26
|
+
|
|
27
|
+
## 备选:用 token(不推荐)
|
|
28
|
+
|
|
29
|
+
如果哪天可信发布不可用,也可以在 npm 建 **Classic → Automation** 类型的 token
|
|
30
|
+
(Granular token 在开了 2FA 的账号上会报 `EOTP`,除非它明确允许绕过 2FA),
|
|
31
|
+
存成仓库 secret `NPM_TOKEN`,然后在 workflow 的 publish 步骤加回:
|
|
32
|
+
|
|
33
|
+
```yaml
|
|
34
|
+
env:
|
|
35
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
并把 `setup-node` 的 `with:` 里加回 `registry-url: https://registry.npmjs.org`。
|
|
39
|
+
Automation token 专为 CI 设计,不受 2FA 影响。
|
|
40
|
+
|
|
41
|
+
## 发一次版
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
npm version patch --no-git-tag-version # 或 minor / major,或手动改 package.json
|
|
45
|
+
git add package.json package-lock.json
|
|
46
|
+
git commit -m "chore: release v2.0.1"
|
|
47
|
+
git tag v2.0.1
|
|
48
|
+
git push origin main --tags
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Action 会依次做:
|
|
52
|
+
|
|
53
|
+
| 步骤 | 失败就停 |
|
|
54
|
+
|---|---|
|
|
55
|
+
| `npm ci` | 锁文件与 package.json 不同步会在这里红 |
|
|
56
|
+
| tag 与 `package.json` 版本一致 | 防止「tag 写 v2.0.1、包里是 2.0.0」|
|
|
57
|
+
| 该版本是否已存在于 npm | 已存在则**跳过发布**(不会红,也不会覆盖)|
|
|
58
|
+
| `npm pack --dry-run` | 发布内容一目了然(日志里能看到文件清单)|
|
|
59
|
+
| `npm publish` | 内部触发 `prepublishOnly` 守卫:构建 + 类型 + 单测 + 审计 + 端到端;provenance 由可信发布自动附带 |
|
|
60
|
+
| 建 GitHub Release | 标题用 tag,正文自动生成 |
|
|
61
|
+
|
|
62
|
+
发布成功后 npm 页面会带一个 **Provenance** 徽章,点进去能看到是哪次 commit、哪次 workflow 构建的。
|
|
63
|
+
|
|
64
|
+
## 在网页上发版(完全不碰命令行)
|
|
65
|
+
|
|
66
|
+
1. 打开 <https://github.com/booondenz/dsh-thesis/releases/new>;
|
|
67
|
+
2. **Choose a tag** 里输入 `v2.0.1`,点下拉第一条 **Create new tag: v2.0.1 on publish**;
|
|
68
|
+
3. **Target** 选 `main`,并确认它指向 bump 版本的那个 commit(否则 tag 会打在别的提交上,
|
|
69
|
+
workflow 第一步的版本比对就会红);
|
|
70
|
+
4. 标题写 `v2.0.1`,正文可以留空——workflow 里是 `gh release view || gh release create`,
|
|
71
|
+
发现 Release 已存在会跳过;
|
|
72
|
+
5. **Publish release**。
|
|
73
|
+
|
|
74
|
+
创建 tag 本身就是一次 `push`,所以 `publish.yml` 会被触发。两条路等价:也可以先
|
|
75
|
+
`git push origin v2.0.1` 再建 Release,或者只推 tag 不建 Release(workflow 会替你建)。
|
|
76
|
+
|
|
77
|
+
## 确认发成功了
|
|
78
|
+
|
|
79
|
+
| 看哪 | 期望 |
|
|
80
|
+
|---|---|
|
|
81
|
+
| Actions → **publish** | 这次 run 是绿的;Summary 里有一行 `https://www.npmjs.com/package/dsh-thesis/v/2.0.1` |
|
|
82
|
+
| `npm view dsh-thesis version` | `2.0.1`(registry 立刻生效,网页可能还要一分钟)|
|
|
83
|
+
| `npm view dsh-thesis dist-tags` | `{ latest: '2.0.1' }` |
|
|
84
|
+
| <https://www.npmjs.com/package/dsh-thesis> | 版本号旁出现 **Provenance** 徽章 |
|
|
85
|
+
| 仓库 **Releases** | 多了一条 `v2.0.1` |
|
|
86
|
+
|
|
87
|
+
Actions 里**根本没出现 publish 这个 run**,说明 tag 没推上去(或名字不是 `v` 开头);
|
|
88
|
+
出现 run 但红在第一步,通常是 tag 与 `package.json` 版本对不上。
|
|
89
|
+
|
|
90
|
+
## 发完之后:让 DSH 用上新版
|
|
91
|
+
|
|
92
|
+
profile 把版本钉在 `~/.dsh/profiles/<profile>/package.json` 里(例如 `"dsh-thesis": "1.0.1"`),
|
|
93
|
+
所以 npm 上发了新版**不会自动生效**。到插件管理器里移除再装一次(会取 `latest`),或者把那条依赖
|
|
94
|
+
改成 `"^2.0.1"` 后重装,然后**重启 DSH**——2.0 删掉了全部斜杠命令,不是热更新能覆盖的。
|
|
95
|
+
|
|
96
|
+
## 手动触发
|
|
97
|
+
|
|
98
|
+
Actions → publish → Run workflow:只做打包预览,**不会发布**。用来确认「这次发出去的包里到底有什么」。
|
|
99
|
+
想真发版,还是打 tag。
|
|
100
|
+
|
|
101
|
+
## 失败排查
|
|
102
|
+
|
|
103
|
+
| 现象 | 原因 |
|
|
104
|
+
|---|---|
|
|
105
|
+
| `EOTP` / `This operation requires a one-time password` | 用的是需要 OTP 的 token(2FA 账号的 Granular / Publish token)。CI 里没人能输 OTP:改用可信发布,或换 Classic → Automation token |
|
|
106
|
+
| `401 Unauthorized` | token 过期(Automation token 有 90/180 天寿命),或可信发布配置里 workflow 文件名写错 |
|
|
107
|
+
| `npm ci … not in sync` | 改了 `package.json` 的依赖/peer 却没跑 `npm install --package-lock-only` |
|
|
108
|
+
| `403 … cannot publish over previously published version` | 版本号没升;这条在 workflow 里已被「已存在则跳过」挡住,手动发版时要注意 |
|
|
109
|
+
| 守卫里 `单元/契约测试` 红 | 本地 `npm test` 先复现;守卫跑的就是它 |
|
|
110
|
+
| 守卫警告「未找到 DSH 安装」 | CI 里正常(没有宿主);**发版前请在本地跑一次 `npm run test:host-load` 与 `npm run test:host`** |
|
|
111
|
+
|
|
112
|
+
## 撤回与补救
|
|
113
|
+
|
|
114
|
+
- **已发布的版本不能改**,只能 `npm deprecate dsh-thesis@2.0.1 "原因与替代版本"`。
|
|
115
|
+
- 72 小时内理论上可以 `npm unpublish`,但那会让依赖它的人突然装不上,**不要用**。
|
|
116
|
+
- 发错了就立刻发一个 patch:`2.0.2`。
|
|
117
|
+
|
|
118
|
+
## 仍然可以本地发布
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
npm login
|
|
122
|
+
npm publish --access public # 会跑同一个 prepublishOnly 守卫,会交互式要 OTP
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
本地发布用的是你登录后的凭据(可以输 OTP),不需要 token,也不需要可信发布配置。
|
|
126
|
+
CI 只是把「构建 → 校验 → 发布」串起来,判据完全一样。
|
package/docs/tools.md
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# 工具与技能
|
|
2
|
+
|
|
3
|
+
工具名、命令面、技能名都是**对外契约**:改名就是破坏性变更。`npm run audit` 会把这三样
|
|
4
|
+
都核对一遍(21 个工具 / 0 条斜杠命令 / 11 个技能 + 命名与 BOM 检查)。
|
|
5
|
+
|
|
6
|
+
## 命名空间
|
|
7
|
+
|
|
8
|
+
| 前缀 | 管什么 |
|
|
9
|
+
|---|---|
|
|
10
|
+
| `thesis_*` | 论文工作区里的东西(材料、要求、章节、检查、构建、答辩素材、幻灯) |
|
|
11
|
+
| `defense_code_*` | 答辩层的代码演练(把系统拆成讲得清的模块) |
|
|
12
|
+
| `fact_*` | 跨会话事实(学校规范、导师要求、写作偏好) |
|
|
13
|
+
|
|
14
|
+
## `thesis_*`(15 个)
|
|
15
|
+
|
|
16
|
+
| 工具 | 一句话 | 关键约束 |
|
|
17
|
+
|---|---|---|
|
|
18
|
+
| `thesis_ingest` | 把材料读成文本与结构摘要 | docx/xlsx/pptx/pdf/md/csv/bib + 源码目录;源码只给结构,不贴正文;已存在的摘要不覆盖 |
|
|
19
|
+
| `thesis_intake` | 一次问一个要求问题,问成《意图规格》 | 必答项不齐拒绝 `done`;材料里能读出来的不重复问 |
|
|
20
|
+
| `thesis_init` | 建论文工作区 | 空目录才能建;九阶段目录 + 台账 + 七章模板 + 技能包 + git |
|
|
21
|
+
| `thesis_progress` | 看进度 / 过 G1-G4 | 关卡是**拒绝**不是提醒;关联任务未完成不许过关 |
|
|
22
|
+
| `thesis_decide` | 记一条关键决定 | 内容/理由/备选三段,写进决定日志 |
|
|
23
|
+
| `thesis_lit_search` | 真实检索文献 | Semantic Scholar → DBLP → arXiv → Crossref 降级;写检索缓存与审计记录 |
|
|
24
|
+
| `thesis_lit_save` | 收录进 `refs.bib` | **只接受检索缓存里的 id**(零假文献的落点);DOI 重复自动跳过 |
|
|
25
|
+
| `thesis_lit_note` | 生成阅读笔记骨架 | 五节模板;已存在不覆盖 |
|
|
26
|
+
| `thesis_review` | 单章六项评审 | 字数区间 / 大纲小节 / 引用编号 / 图表编号 / 未完成标记 / G2 清单 |
|
|
27
|
+
| `thesis_check` | 全文五项检查 | 引用双向一致、字数、图表编号、术语定义顺序、学校模板探测 |
|
|
28
|
+
| `thesis_stylecheck` | 六条 AI 味启发式 | 模板套话、空洞结论、自我暴露、翻译腔、句式单一、无锚点长段落 |
|
|
29
|
+
| `thesis_build` | 出 `论文.docx` | 有 pandoc 用 pandoc + 学校模板,没有用内置零依赖生成器(显式标注) |
|
|
30
|
+
| `thesis_originality` | 本地降重度量 | scan / verify / report;**不接收费查重**,报告里是本地估算 |
|
|
31
|
+
| `thesis_defense` | 答辩素材 + 六类问题库 | 每个问题带证据锚点(哪个文件哪一行) |
|
|
32
|
+
| `thesis_slides` | 答辩幻灯 | Marp 兼容 Markdown;outline / convert / check / guide;pptx 依赖外部引擎 |
|
|
33
|
+
|
|
34
|
+
## `defense_code_*`(3 个)
|
|
35
|
+
|
|
36
|
+
| 工具 | 一句话 |
|
|
37
|
+
|---|---|
|
|
38
|
+
| `defense_code_status` | 我的系统我讲得清吗(阶段、里程碑、验证门、未过的问题) |
|
|
39
|
+
| `defense_code_next` | 下一个该弄懂的模块(todo + 评分要点) |
|
|
40
|
+
| `defense_code_update` | 登记 / 推进 / 评分 / 重试(每次改动立即落盘) |
|
|
41
|
+
|
|
42
|
+
语言矩阵内置 Go / TS / Python / Rust;其它语言在配置里补 `codeWalkthrough.gates`。
|
|
43
|
+
|
|
44
|
+
## `fact_*`(3 个)
|
|
45
|
+
|
|
46
|
+
| 工具 | 一句话 |
|
|
47
|
+
|---|---|
|
|
48
|
+
| `fact_search` | 上次记下的学校规范还在吗(key/value 子串检索) |
|
|
49
|
+
| `fact_remember` | 记住一条跨会话仍成立的稳定事实 |
|
|
50
|
+
| `fact_context` | 把这个课题已知的稳定事实一次性拉回来 |
|
|
51
|
+
|
|
52
|
+
只记**跨会话仍然成立**的东西(学校规范、导师偏好、课题稳定事实);进度、临时任务、一次性
|
|
53
|
+
实验数字不进记忆,那些在台账与实验记录里。
|
|
54
|
+
|
|
55
|
+
## 技能(11 个)
|
|
56
|
+
|
|
57
|
+
随插件发布,`thesis_init` 把它们复制进论文仓库 `.dsh/skills/`,跟着论文一起 git 版本化。
|
|
58
|
+
|
|
59
|
+
| 技能 | 解决什么 |
|
|
60
|
+
|---|---|
|
|
61
|
+
| `thesis-pipeline` | 全流程总纲:阶段、关卡、工具地图、会话入口顺序 |
|
|
62
|
+
| `thesis-opener` | 选题与开题(课题怎么定、开题报告怎么写) |
|
|
63
|
+
| `thesis-literature` | 文献调研:检索策略、阅读笔记、综述组织 |
|
|
64
|
+
| `thesis-eng-design` | 需求 / 设计 / 选型论证的写法 |
|
|
65
|
+
| `thesis-writing` | 逐章写作规范与验收标准 |
|
|
66
|
+
| `thesis-citation` | GB/T 7714 引用格式(只解决「格式对不对」) |
|
|
67
|
+
| `thesis-defense` | 答辩素材、问题库、幻灯与讲稿 |
|
|
68
|
+
| `code-walkthrough` | 把系统拆成答辩讲得清的模块(配 `defense_code_*`) |
|
|
69
|
+
| `paper-intake` | 材料到手后的追问方法论(怎么问出可证伪的要求) |
|
|
70
|
+
| `paper-dedup` | 原创性与降重:本地度量、改写处方、复测 |
|
|
71
|
+
| `thesis-inquiry` | 写作要求被质疑、导师口径模糊时怎么问清 |
|
|
72
|
+
|
|
73
|
+
## 没有斜杠命令
|
|
74
|
+
|
|
75
|
+
`ctx.commands` 一次都不注册。入口是自动驾驶([autopilot.md](./autopilot.md)),
|
|
76
|
+
或者直接跟模型说话让它调工具。
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# 排查
|
|
2
|
+
|
|
3
|
+
## 装了但没反应 / 工具看不见
|
|
4
|
+
|
|
5
|
+
宿主在装载前会校验 `package.json` 里 `@deepseek-ai/dsh*` 的 `peerDependencies`,
|
|
6
|
+
**不满足就把这一行静默 `disabled`**(stderr 只有一句 `dsh: disabling profile plugin row …`)。
|
|
7
|
+
本插件声明:
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
@deepseek-ai/dsh-tools: >=0.2.0-rc.2 <0.3.0-0
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
排查顺序:
|
|
14
|
+
|
|
15
|
+
1. 确认 dsh 版本:`dsh --version`。跨小版本(0.3+)时这条 range 就要放宽,不能硬装。
|
|
16
|
+
2. 跑 `npm run test:host-load`:它用**宿主自己的预检函数**判断真实副本会不会被停用。
|
|
17
|
+
3. 跑 `npm run test:host`:真实 cordis 装配 + 真实工具注册表。
|
|
18
|
+
4. 装了插件管理器却报 `installation rejected`:多半是旧版本缓存。`dsh plugin add dsh-thesis@<确切版本>` 钉住版本,
|
|
19
|
+
或 `pnpm cache delete dsh-thesis` 后再装。
|
|
20
|
+
|
|
21
|
+
## 重启后还是旧行为
|
|
22
|
+
|
|
23
|
+
- `dsh plugin add` 装的是 **npm 上的那一版**,改了源码不重装不会生效;本地开发用
|
|
24
|
+
`node scripts/install-into-profile.ts --profile web`(把 profile 指到本仓库,重启生效)。
|
|
25
|
+
- DSH 没有 TS 加载器:**必须先 `npm run build`**(产出 `lib/`),直接指向源码不会工作。
|
|
26
|
+
- 确认改到的是同一个 profile:`--profile web` 要和实际启动参数一致。
|
|
27
|
+
|
|
28
|
+
## 说了话但没弹那道选择题
|
|
29
|
+
|
|
30
|
+
自动驾驶只在「**论文工作区** + **主 agent** + **还没有意图规格**」时问。看会话日志:
|
|
31
|
+
|
|
32
|
+
| 日志 | 含义 |
|
|
33
|
+
|---|---|
|
|
34
|
+
| `已有意图规格` | `00-管理/意图规格.md` 已存在,不再重复问(删掉它或换工作区可重新选)|
|
|
35
|
+
| `意图选择题没有拿到答案` | UI 不接受非工具调用的问题卡片,或你取消了 |
|
|
36
|
+
| `宿主没有 userQuestions 服务` | 这套组合没有问答面 |
|
|
37
|
+
| `宿主没有 goals 服务` | 只会跑一轮,不自动续轮 |
|
|
38
|
+
|
|
39
|
+
前三行都意味着:插件有意**不猜**你的意图。直接说话即可,工具都在。
|
|
40
|
+
|
|
41
|
+
## 关卡没问就过了
|
|
42
|
+
|
|
43
|
+
`autopilot.gateApproval` 被设成了 `false`。改成 `true` 就恢复「过人卡必须由人拍板」。
|
|
44
|
+
|
|
45
|
+
## PDF 读不出文字
|
|
46
|
+
|
|
47
|
+
扫描版(没有文本层)、加密 PDF、只有 CID 字体且无 ToUnicode 映射的 PDF 抽不出内容。
|
|
48
|
+
工具会**如实说明原因**,不会编造。处理办法:先用 OCR 或另存一份带文本层的 PDF 再摄取。
|
|
49
|
+
|
|
50
|
+
## `.pptx` 没生成
|
|
51
|
+
|
|
52
|
+
幻灯的真相是 Markdown(`07-答辩/PPT.md`),`.pptx` 交给外部工具:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
npx -y @marp-team/marp-cli 07-答辩/PPT.md --pptx
|
|
56
|
+
# 或
|
|
57
|
+
pandoc 07-答辩/PPT.md -o 07-答辩/PPT.pptx
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
两者都没有时,`thesis_slides convert` 会写一份 `07-答辩/PPT转换说明.md`(探测结果 + 确切命令 + 退出码),
|
|
61
|
+
**绝不假装成功**。装了 marp 之后重跑即可。
|
|
62
|
+
|
|
63
|
+
## 旧格式打不开
|
|
64
|
+
|
|
65
|
+
`.doc` / `.xls` / `.ppt` 不支持,先另存为 `.docx` / `.xlsx` / `.pptx`。
|
|
66
|
+
|
|
67
|
+
## 工具写到别的目录去了?
|
|
68
|
+
|
|
69
|
+
不会,但会**报错**:配了 `workspace` 却找不到 `00-管理/进度台账.md` 时,工具直接失败而不是退回 cwd 探测。
|
|
70
|
+
这正是防「写错地方」的设计。要么改 `workspace`,要么先在工作区跑 `thesis_init`。
|
|
71
|
+
|
|
72
|
+
## 读文件失败 vs 文件不存在
|
|
73
|
+
|
|
74
|
+
两者严格区分:读失败(权限 / IO)会抛错并保持原文件不动,绝不会用默认值覆盖。
|
|
75
|
+
「读不出来 ≠ 不存在」是整个仓库的硬约束。
|
|
76
|
+
|
|
77
|
+
## 中文乱码
|
|
78
|
+
|
|
79
|
+
工作区里的文件统一 UTF-8(无 BOM)。Windows 上用 PowerShell 查看时加 `-Encoding utf8`:
|
|
80
|
+
|
|
81
|
+
```powershell
|
|
82
|
+
Get-Content 00-管理\进度台账.md -Encoding utf8
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## 代价与限速
|
|
86
|
+
|
|
87
|
+
- 自动续跑每一轮都是一次完整模型调用,`autopilot.maxGoalRounds` 是唯一刹车;调小它比事后心疼便宜。
|
|
88
|
+
- 外部命令(pandoc / marp / git)走 `spawnSync`:有超时,**没有信号传递**(按下停止不会杀掉子进程)。
|
package/docs/usage.md
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# 使用手册
|
|
2
|
+
|
|
3
|
+
> 只想知道怎么装:见 [README](../README.md)。这里讲**用起来是什么样**。
|
|
4
|
+
|
|
5
|
+
## 前置条件
|
|
6
|
+
|
|
7
|
+
- DSH 里装好 `dsh-thesis`,重启后可见 `thesis_*` / `fact_*` / `defense_code_*` 三组工具。
|
|
8
|
+
- **把会话开在论文目录里**最省事:多数工具从会话 cwd 向上探测 `00-管理/进度台账.md` 来定位工作区。
|
|
9
|
+
- 也可以显式指定:`config: { workspace: /path/to/你的论文 }`。配了它就**只认它**,路径写错会直接报错,
|
|
10
|
+
绝不会写到别的目录去。
|
|
11
|
+
|
|
12
|
+
工作区可以是空的(还没有论文),`thesis_init` 会把九阶段目录、台账、决定日志、七章模板和技能包一次性建好。
|
|
13
|
+
|
|
14
|
+
## 第一次会话
|
|
15
|
+
|
|
16
|
+
把材料丢进工作区(或告诉它绝对路径),说一句:
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
这是我的论文材料,帮我做毕业设计
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
插件接管后是这样走的:
|
|
23
|
+
|
|
24
|
+
1. **弹一道选择题**(只有一次):从零走到答辩 / 只补合规与答辩 / 只做答辩准备 / 先别自动跑。
|
|
25
|
+
细节见 [autopilot.md](./autopilot.md)。
|
|
26
|
+
2. 选定后建目标、自动一轮轮跑:材料摄取 → 逐题追问 → 文献 → 设计 → 实现 → 测试 → 论文 → 合规 → 答辩。
|
|
27
|
+
3. 只在 **G1-G4 人工关卡**停下来,让你在审批界面点「允许」或「拒绝」。
|
|
28
|
+
|
|
29
|
+
没有材料也能用:「我要做毕业设计,还没定题」→ 走选题工作坊,先定课题再进流水线。
|
|
30
|
+
|
|
31
|
+
## 九阶段与关卡
|
|
32
|
+
|
|
33
|
+
| 阶段 | 产出物 | 验收标准 | 人工关卡 |
|
|
34
|
+
|---|---|---|---|
|
|
35
|
+
| 1 选题 | 选题确认书 | 课题明确、工作量合理、答辩友好 | **G1** |
|
|
36
|
+
| 2 开题 | 开题报告 + 任务书 | 导师认可;结构与规范达标 | **G3** |
|
|
37
|
+
| 3 文献调研 | 文献库 + 笔记 + 综述素材 | 15-30 篇真实文献;每篇有笔记 | — |
|
|
38
|
+
| 4 系统设计 | 需求/设计/选型文档 | 方案可落地;选型有论证 | — |
|
|
39
|
+
| 5 系统实现 | 可运行系统 + git 提交 | 功能真实可跑 | — |
|
|
40
|
+
| 6 系统测试 | 测试报告 + 真实结果 | 结果可复现;零伪造 | — |
|
|
41
|
+
| 7 论文撰写 | 七章正文 | 逐章人工验收 | **G2**(每章一次) |
|
|
42
|
+
| 8 定稿与合规 | 论文.docx + 检查报告 | 格式/引用/自查全部通过 | **G4** |
|
|
43
|
+
| 9 答辩 | 幻灯 + 演练记录 | 能讲清设计与实现 | — |
|
|
44
|
+
|
|
45
|
+
关卡由 `thesis_progress` 在工具层强制:未过该阶段的入口关卡时,任务推进会被**拒绝**(不是提醒)。
|
|
46
|
+
|
|
47
|
+
## 材料与追问
|
|
48
|
+
|
|
49
|
+
- `thesis_ingest <绝对路径>`:docx / xlsx / pptx / pdf / md / csv / bib,以及源码目录(只给文件、行数、
|
|
50
|
+
声明与技术栈,**不贴源码正文**)。产出 `00-管理/材料清单.md` 与逐文件摘要;已存在的摘要绝不覆盖。
|
|
51
|
+
- `thesis_intake`:一次只问一个问题,每问都带「为什么问 / 影响哪个产出 / 合格答案形态」。
|
|
52
|
+
材料里能读出来的不重复问;必答项不齐时拒绝 `done`。答案落盘成 `00-管理/意图规格.md`(唯一真相)。
|
|
53
|
+
- 断点续问:状态在 `.paper/intake.json`(相对工作区根),换会话接着问,不重复。
|
|
54
|
+
|
|
55
|
+
## 常见动作
|
|
56
|
+
|
|
57
|
+
| 想做的事 | 怎么说 / 调什么 |
|
|
58
|
+
|---|---|
|
|
59
|
+
| 换学校模板 | 把模板放进 `06-论文/assets/学校模板/`,再跑 `thesis_check`(探测到就用,探测不到显式标注「非学校模板」)|
|
|
60
|
+
| 只改某一章 | 直接说「改第三章的方法部分」,改完 `thesis_review 03-设计` |
|
|
61
|
+
| 回填学校查重结果 | `thesis_originality action=report detected_rate=12 detected_system=知网` |
|
|
62
|
+
| 出 Word | `thesis_build`(有 pandoc 用 pandoc + 模板,没有就用内置零依赖生成器)|
|
|
63
|
+
| 只做答辩 | `thesis_defense` → `thesis_slides` → 代码演练 `defense_code_*` |
|
|
64
|
+
| 记住学校规范 | `fact_remember key=school.dedup.system value="知网,查重阈值 20%"` |
|
|
65
|
+
| 看进度 | `thesis_progress action=report` |
|
|
66
|
+
|
|
67
|
+
## 产出物
|
|
68
|
+
|
|
69
|
+
| 产物 | 位置 |
|
|
70
|
+
|---|---|
|
|
71
|
+
| 意图规格(唯一真相) | `00-管理/意图规格.md` |
|
|
72
|
+
| 材料清单 + 逐文件摘要 | `00-管理/材料清单.md`、`00-管理/材料/*.md` |
|
|
73
|
+
| 进度台账 / 决定日志 / 时间线 | `00-管理/` |
|
|
74
|
+
| 文献库与检索审计 | `02-文献/refs.bib`、`检索记录.md`、`笔记/` |
|
|
75
|
+
| 章节与 Word | `06-论文/章节/*.md`、`06-论文/产出/论文.docx` |
|
|
76
|
+
| 答辩素材 / 幻灯 / 问题库 | `07-答辩/` |
|
|
77
|
+
| 检查报告(引用 / 格式 / AI 味 / 降重) | `08-合规/` |
|
|
78
|
+
|
|
79
|
+
## 中断与续跑
|
|
80
|
+
|
|
81
|
+
会话断了不要紧:进度、决定、追问状态、检索缓存全在工作区文件里。重开一个会话说一句
|
|
82
|
+
「接着做」即可——`thesis_progress action=report` 会把当前阶段、未过的关卡与下一步报出来。
|
|
83
|
+
|
|
84
|
+
## 多条流水线同时进行
|
|
85
|
+
|
|
86
|
+
一个工作区 = 一个课题。不同课题就不同目录,各开各的会话;跨会话的稳定事实(学校规范、
|
|
87
|
+
导师偏好)走 `fact_*`,那是全局共享的。
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 自动驾驶:插件在后台把流程推起来,人只在两处出现——**开头选一次意图**、**过关卡时拍一次板**。
|
|
3
|
+
*
|
|
4
|
+
* 为什么不让人敲命令:命令是给人操作 CLI 的入口,而这里真正的主角是模型与流水线。
|
|
5
|
+
* 插件要做的不是再提供一套动词,而是:
|
|
6
|
+
*
|
|
7
|
+
* 1. `agent/pre-step`:认出「这是论文工作区、用户还没定过意图」→ 问一道选择题
|
|
8
|
+
* (`ctx.userQuestions.ask`,三四档常见起点)→ 把答案写进决定日志 →
|
|
9
|
+
* `ctx.goals.create` 建目标(宿主的 goal-round-driver 此后自动续轮)→
|
|
10
|
+
* 注入一条 operating contract(怎么推进、怎么并行、哪里必须停)。
|
|
11
|
+
* 2. `tools/pre-execute`:模型要过 G1-G4 时拦一次 `ask`,由人在审批界面拍板。
|
|
12
|
+
*
|
|
13
|
+
* 两条铁律:**只对主 agent 生效**(子 agent 委派深度 > 0 一律跳过)、
|
|
14
|
+
* **只对论文工作区生效**(找不到台账就完全不介入,别的项目里装了这个插件也不受干扰)。
|
|
15
|
+
*
|
|
16
|
+
* @module dsh-thesis/autopilot
|
|
17
|
+
*/
|
|
18
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
19
|
+
import type { AutopilotOptions } from '../config.ts';
|
|
20
|
+
import type { AutopilotAnswerItem, AutopilotAgent } from './types.ts';
|
|
21
|
+
/** 一个 agent 的委派深度:与宿主 `delegationDepthOf` 同一条规则(头里的深度只增不减)。 */
|
|
22
|
+
export declare function agentDepth(agent: AutopilotAgent): number;
|
|
23
|
+
/** 从结构化答案里取出被选中的标签(兼容多选与自定义输入)。 */
|
|
24
|
+
export declare function selectedLabel(answer: {
|
|
25
|
+
readonly answers?: readonly AutopilotAnswerItem[];
|
|
26
|
+
} | undefined): string | undefined;
|
|
27
|
+
/** 装配参数:配置里的自动驾驶块 + 意图规格落盘位置(与 intake 共用同一份配置)。 */
|
|
28
|
+
export interface AutopilotInstallOptions extends AutopilotOptions {
|
|
29
|
+
/** 意图规格文件相对论文工作区根的位置。 */
|
|
30
|
+
readonly specRel: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* 装上自动驾驶的两处监听。
|
|
34
|
+
*
|
|
35
|
+
* 顺序关键:`agent/pre-step` 先 `await next()` 再注入(与写作意图闸门同一约定),
|
|
36
|
+
* 任何异常都吞成「不介入」,绝不把错误抛进 agent 循环。
|
|
37
|
+
*/
|
|
38
|
+
export declare function installAutopilot(ctx: Context, options: AutopilotInstallOptions): void;
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 自动驾驶:插件在后台把流程推起来,人只在两处出现——**开头选一次意图**、**过关卡时拍一次板**。
|
|
3
|
+
*
|
|
4
|
+
* 为什么不让人敲命令:命令是给人操作 CLI 的入口,而这里真正的主角是模型与流水线。
|
|
5
|
+
* 插件要做的不是再提供一套动词,而是:
|
|
6
|
+
*
|
|
7
|
+
* 1. `agent/pre-step`:认出「这是论文工作区、用户还没定过意图」→ 问一道选择题
|
|
8
|
+
* (`ctx.userQuestions.ask`,三四档常见起点)→ 把答案写进决定日志 →
|
|
9
|
+
* `ctx.goals.create` 建目标(宿主的 goal-round-driver 此后自动续轮)→
|
|
10
|
+
* 注入一条 operating contract(怎么推进、怎么并行、哪里必须停)。
|
|
11
|
+
* 2. `tools/pre-execute`:模型要过 G1-G4 时拦一次 `ask`,由人在审批界面拍板。
|
|
12
|
+
*
|
|
13
|
+
* 两条铁律:**只对主 agent 生效**(子 agent 委派深度 > 0 一律跳过)、
|
|
14
|
+
* **只对论文工作区生效**(找不到台账就完全不介入,别的项目里装了这个插件也不受干扰)。
|
|
15
|
+
*
|
|
16
|
+
* @module dsh-thesis/autopilot
|
|
17
|
+
*/
|
|
18
|
+
import { findThesisRoot } from "../paper/lib/project.js";
|
|
19
|
+
import { runDecision } from "../paper/tools/decision.js";
|
|
20
|
+
import { choiceOfLabel, INTENT_QUESTION_ID, intentQuestion } from "./intent.js";
|
|
21
|
+
import { gateApprovalReason, makeAutopilotMessage } from "./messages.js";
|
|
22
|
+
/** 一个 agent 的委派深度:与宿主 `delegationDepthOf` 同一条规则(头里的深度只增不减)。 */
|
|
23
|
+
export function agentDepth(agent) {
|
|
24
|
+
const fromHeader = agent.session?.header?.subagentDepth ?? 0;
|
|
25
|
+
const fromOptions = agent.options?.subagentDepth ?? 0;
|
|
26
|
+
return Math.max(fromHeader, fromOptions);
|
|
27
|
+
}
|
|
28
|
+
/** 从结构化答案里取出被选中的标签(兼容多选与自定义输入)。 */
|
|
29
|
+
export function selectedLabel(answer) {
|
|
30
|
+
const item = answer?.answers?.find(entry => entry.id === INTENT_QUESTION_ID) ?? answer?.answers?.[0];
|
|
31
|
+
if (item === undefined)
|
|
32
|
+
return undefined;
|
|
33
|
+
const picked = item.selected?.[0];
|
|
34
|
+
if (typeof picked === 'string' && picked.trim() !== '')
|
|
35
|
+
return picked;
|
|
36
|
+
if (typeof item.custom === 'string' && item.custom.trim() !== '')
|
|
37
|
+
return item.custom;
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
/** 意图规格是否已经存在(存在就不再打扰:用户已经定过要求,或已经跑过一轮)。 */
|
|
41
|
+
async function specExists(ctx, root, specRel, signal) {
|
|
42
|
+
try {
|
|
43
|
+
await ctx.fs.readText(await ctx.fs.resolve(`${root}/${specRel}`, { signal }), signal);
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* 装上自动驾驶的两处监听。
|
|
52
|
+
*
|
|
53
|
+
* 顺序关键:`agent/pre-step` 先 `await next()` 再注入(与写作意图闸门同一约定),
|
|
54
|
+
* 任何异常都吞成「不介入」,绝不把错误抛进 agent 循环。
|
|
55
|
+
*/
|
|
56
|
+
export function installAutopilot(ctx, options) {
|
|
57
|
+
if (!options.enabled)
|
|
58
|
+
return;
|
|
59
|
+
const started = new Set();
|
|
60
|
+
ctx.on('agent/pre-step', async (payload, next) => {
|
|
61
|
+
const downstream = await next();
|
|
62
|
+
if (downstream.kind !== 'enter')
|
|
63
|
+
return downstream;
|
|
64
|
+
const agent = payload.agent;
|
|
65
|
+
if (agent === undefined)
|
|
66
|
+
return downstream;
|
|
67
|
+
if (agentDepth(agent) > 0)
|
|
68
|
+
return downstream;
|
|
69
|
+
const key = agent.id ?? 'anonymous';
|
|
70
|
+
if (started.has(key))
|
|
71
|
+
return downstream;
|
|
72
|
+
let root = null;
|
|
73
|
+
try {
|
|
74
|
+
root = await findThesisRoot(ctx.fs, agent.session?.header?.cwd, payload.signal);
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
// 配置的 workspace 写错、台账读不出来:都不属于「自动驾驶」该处理的场景。
|
|
78
|
+
return downstream;
|
|
79
|
+
}
|
|
80
|
+
if (root === null)
|
|
81
|
+
return downstream;
|
|
82
|
+
started.add(key);
|
|
83
|
+
if (await specExists(ctx, root, options.specRel, payload.signal)) {
|
|
84
|
+
ctx.logger.info('dsh-thesis: 已有意图规格,自动驾驶不再重复询问,按现有规格推进。');
|
|
85
|
+
return downstream;
|
|
86
|
+
}
|
|
87
|
+
const choice = await askIntent(ctx, agent, payload.signal);
|
|
88
|
+
if (choice === undefined)
|
|
89
|
+
return downstream;
|
|
90
|
+
try {
|
|
91
|
+
await runDecision(ctx.fs, { content: `自动驾驶启动:本次意图 = 「${choice.label}」(用户在启动选择题里确认;目标上限 ${options.maxGoalRounds} 轮)` }, root, payload.signal);
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
ctx.logger.warn(`dsh-thesis: 自动驾驶意图写进决定日志失败:${error instanceof Error ? error.message : String(error)}`);
|
|
95
|
+
}
|
|
96
|
+
armGoal(ctx, agent, choice, options.maxGoalRounds);
|
|
97
|
+
return { kind: 'enter', messages: [...downstream.messages, makeAutopilotMessage(choice, options.maxGoalRounds)] };
|
|
98
|
+
});
|
|
99
|
+
if (options.gateApproval)
|
|
100
|
+
installGateApproval(ctx);
|
|
101
|
+
}
|
|
102
|
+
/** 问那一道选择题;拿不到答案(没有答题面 / 用户取消 / 选了「先别自动跑」)时返回 undefined。 */
|
|
103
|
+
async function askIntent(ctx, agent, signal) {
|
|
104
|
+
const service = ctx.get('userQuestions');
|
|
105
|
+
if (service === undefined || typeof service.ask !== 'function') {
|
|
106
|
+
ctx.logger.info('dsh-thesis: 宿主没有 userQuestions 服务,自动驾驶跳过意图询问(改为按现有上下文推进)。');
|
|
107
|
+
return undefined;
|
|
108
|
+
}
|
|
109
|
+
try {
|
|
110
|
+
const answer = await service.ask({ questions: [intentQuestion()], agent, ...(signal === undefined ? {} : { signal }) });
|
|
111
|
+
const label = selectedLabel(answer);
|
|
112
|
+
if (label === undefined)
|
|
113
|
+
return undefined;
|
|
114
|
+
const choice = choiceOfLabel(label);
|
|
115
|
+
// 认不出的标签(例如用户自己输入了别的)按「关掉自动驾驶」处理,绝不猜。
|
|
116
|
+
if (choice === undefined || choice.objective === '') {
|
|
117
|
+
ctx.logger.info(`dsh-thesis: 用户没有选择自动推进(${label})。`);
|
|
118
|
+
return undefined;
|
|
119
|
+
}
|
|
120
|
+
return choice;
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
ctx.logger.info(`dsh-thesis: 意图选择题没有拿到答案(${error instanceof Error ? error.message : String(error)}),本次不自动推进。`);
|
|
124
|
+
return undefined;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/** 建目标:宿主的目标轮驱动器会按它自动续轮,直到完成或轮数用尽。 */
|
|
128
|
+
function armGoal(ctx, agent, choice, maxGoalRounds) {
|
|
129
|
+
const goals = ctx.get('goals');
|
|
130
|
+
if (goals === undefined || typeof goals.create !== 'function') {
|
|
131
|
+
ctx.logger.info('dsh-thesis: 宿主没有 goals 服务,自动驾驶只推进当前一轮(不会自动续轮)。');
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
try {
|
|
135
|
+
goals.create(agent, { objective: choice.objective, maxGoalRounds });
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
ctx.logger.warn(`dsh-thesis: 建目标失败,本轮流完就停:${error instanceof Error ? error.message : String(error)}`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/** 人工关卡拦截:模型要过 G1-G4 时,先让人在审批界面拍一次板。 */
|
|
142
|
+
function installGateApproval(ctx) {
|
|
143
|
+
ctx.on('tools/pre-execute', async (exec, next) => {
|
|
144
|
+
if (exec.agent === undefined)
|
|
145
|
+
return next();
|
|
146
|
+
if (exec.name !== 'thesis_progress')
|
|
147
|
+
return next();
|
|
148
|
+
const args = exec.arguments;
|
|
149
|
+
if (args === undefined || args.action !== 'gate' || args.pass !== true)
|
|
150
|
+
return next();
|
|
151
|
+
const gate = typeof args.gate === 'string' ? args.gate.toUpperCase() : '关卡';
|
|
152
|
+
const chapter = typeof args.chapter === 'string' ? args.chapter : undefined;
|
|
153
|
+
const note = typeof args.note === 'string' ? args.note : undefined;
|
|
154
|
+
return {
|
|
155
|
+
kind: 'ask',
|
|
156
|
+
reason: gateApprovalReason({ gate, ...(chapter === undefined ? {} : { chapter }), ...(note === undefined ? {} : { note }) }),
|
|
157
|
+
};
|
|
158
|
+
});
|
|
159
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 自动驾驶的文案与意图选项:**一次只问一个问题**,答案决定接下来跑到哪一步。
|
|
3
|
+
*
|
|
4
|
+
* 这里的文本是插件直接呈现给用户的(不是给模型的),所以用词要能让人一眼选:
|
|
5
|
+
* 三档常见起点 + 一个「先别自动跑」。选完就不再打断,直到撞上人工关卡。
|
|
6
|
+
*
|
|
7
|
+
* @module dsh-thesis/autopilot
|
|
8
|
+
*/
|
|
9
|
+
/** 意图选择题的问题 id(宿主按 id 把答案回传)。 */
|
|
10
|
+
export declare const INTENT_QUESTION_ID = "dsh-thesis.intent";
|
|
11
|
+
/** 一档意图:选项文案 + 目标 + 启动指令里要向模型交代的边界。 */
|
|
12
|
+
export interface IntentChoice {
|
|
13
|
+
/** 选项标签(用户看到的那一行)。 */
|
|
14
|
+
readonly label: string;
|
|
15
|
+
/** 选项说明(UI 可渲染在标签下方)。 */
|
|
16
|
+
readonly description: string;
|
|
17
|
+
/** 写进 goal 的目标(宿主按它渲染续跑提示)。 */
|
|
18
|
+
readonly objective: string;
|
|
19
|
+
/** 注入给模型的第一条指令正文;空串表示「用户不要自动跑」。 */
|
|
20
|
+
readonly instruction: string;
|
|
21
|
+
}
|
|
22
|
+
/** 「先别自动跑」的选项标签:回答它等于关掉本次自动驾驶。 */
|
|
23
|
+
export declare const HANDS_OFF_LABEL = "\u5148\u522B\u81EA\u52A8\u8DD1\uFF0C\u6211\u81EA\u5DF1\u6765";
|
|
24
|
+
/** 三档起点 + 一个关闭项(顺序即 UI 顺序)。 */
|
|
25
|
+
export declare const INTENT_CHOICES: readonly IntentChoice[];
|
|
26
|
+
/** 把用户选的标签映射回一档意图;认不出来时返回 undefined(按「关掉」处理)。 */
|
|
27
|
+
export declare function choiceOfLabel(label: string): IntentChoice | undefined;
|
|
28
|
+
/** 构造那一道选择题。 */
|
|
29
|
+
export declare function intentQuestion(): {
|
|
30
|
+
readonly id: string;
|
|
31
|
+
readonly header: string;
|
|
32
|
+
readonly question: string;
|
|
33
|
+
readonly detail: string;
|
|
34
|
+
readonly options: readonly {
|
|
35
|
+
readonly label: string;
|
|
36
|
+
readonly description: string;
|
|
37
|
+
}[];
|
|
38
|
+
};
|
|
39
|
+
/** 启动指令消息的正文(含「这条不是用户需求」的免责声明)。 */
|
|
40
|
+
export declare function autopilotInstruction(choice: IntentChoice, maxGoalRounds: number): string;
|