dsh-thesis 1.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/DESIGN.md +390 -0
- package/LICENSE +21 -0
- package/NOTICE.md +10 -0
- package/README.md +253 -0
- package/cordis.patch.yml +17 -0
- package/docs/host-api.md +640 -0
- package/lib/codewalk/commands.d.ts +23 -0
- package/lib/codewalk/commands.js +168 -0
- package/lib/codewalk/engine.d.ts +108 -0
- package/lib/codewalk/engine.js +449 -0
- package/lib/codewalk/errors.d.ts +31 -0
- package/lib/codewalk/errors.js +20 -0
- package/lib/codewalk/fs-types.d.ts +34 -0
- package/lib/codewalk/fs-types.js +10 -0
- package/lib/codewalk/gate.d.ts +30 -0
- package/lib/codewalk/gate.js +60 -0
- package/lib/codewalk/host-types.d.ts +198 -0
- package/lib/codewalk/host-types.js +11 -0
- package/lib/codewalk/prestep.d.ts +17 -0
- package/lib/codewalk/prestep.js +62 -0
- package/lib/codewalk/register.d.ts +23 -0
- package/lib/codewalk/register.js +31 -0
- package/lib/codewalk/skill.d.ts +15 -0
- package/lib/codewalk/skill.js +57 -0
- package/lib/codewalk/tools.d.ts +18 -0
- package/lib/codewalk/tools.js +314 -0
- package/lib/codewalk/types.d.ts +151 -0
- package/lib/codewalk/types.js +9 -0
- package/lib/commands.d.ts +33 -0
- package/lib/commands.js +60 -0
- package/lib/config.d.ts +125 -0
- package/lib/config.js +139 -0
- package/lib/dedup/commands.d.ts +21 -0
- package/lib/dedup/commands.js +93 -0
- package/lib/dedup/index.d.ts +75 -0
- package/lib/dedup/index.js +331 -0
- package/lib/dedup/normalize.d.ts +125 -0
- package/lib/dedup/normalize.js +329 -0
- package/lib/dedup/report.d.ts +114 -0
- package/lib/dedup/report.js +309 -0
- package/lib/dedup/rewrite.d.ts +71 -0
- package/lib/dedup/rewrite.js +228 -0
- package/lib/dedup/similarity.d.ts +169 -0
- package/lib/dedup/similarity.js +323 -0
- package/lib/gates/dangerous.d.ts +22 -0
- package/lib/gates/dangerous.js +47 -0
- package/lib/gates/detect.d.ts +54 -0
- package/lib/gates/detect.js +106 -0
- package/lib/gates/messages.d.ts +39 -0
- package/lib/gates/messages.js +74 -0
- package/lib/gates/prompt.d.ts +21 -0
- package/lib/gates/prompt.js +56 -0
- package/lib/gates/writing-intent.d.ts +49 -0
- package/lib/gates/writing-intent.js +68 -0
- package/lib/index.d.ts +36 -0
- package/lib/index.js +76 -0
- package/lib/ingest/code.d.ts +71 -0
- package/lib/ingest/code.js +356 -0
- package/lib/ingest/commands.d.ts +23 -0
- package/lib/ingest/commands.js +74 -0
- package/lib/ingest/docx.d.ts +29 -0
- package/lib/ingest/docx.js +92 -0
- package/lib/ingest/index.d.ts +179 -0
- package/lib/ingest/index.js +640 -0
- package/lib/ingest/ooxml.d.ts +58 -0
- package/lib/ingest/ooxml.js +393 -0
- package/lib/ingest/pdf.d.ts +86 -0
- package/lib/ingest/pdf.js +1016 -0
- package/lib/ingest/pptx.d.ts +32 -0
- package/lib/ingest/pptx.js +116 -0
- package/lib/ingest/text.d.ts +25 -0
- package/lib/ingest/text.js +180 -0
- package/lib/ingest/types.d.ts +48 -0
- package/lib/ingest/types.js +47 -0
- package/lib/ingest/xlsx.d.ts +72 -0
- package/lib/ingest/xlsx.js +411 -0
- package/lib/ingest/zip.d.ts +76 -0
- package/lib/ingest/zip.js +393 -0
- package/lib/intake/definitions.d.ts +65 -0
- package/lib/intake/definitions.js +42 -0
- package/lib/intake/gate-rules.d.ts +57 -0
- package/lib/intake/gate-rules.js +118 -0
- package/lib/intake/gate.d.ts +24 -0
- package/lib/intake/gate.js +86 -0
- package/lib/intake/index.d.ts +76 -0
- package/lib/intake/index.js +468 -0
- package/lib/intake/questions.d.ts +169 -0
- package/lib/intake/questions.js +720 -0
- package/lib/intake/spec.d.ts +66 -0
- package/lib/intake/spec.js +221 -0
- package/lib/intake/state.d.ts +192 -0
- package/lib/intake/state.js +420 -0
- package/lib/memory/recall.d.ts +69 -0
- package/lib/memory/recall.js +177 -0
- package/lib/memory/register.d.ts +37 -0
- package/lib/memory/register.js +52 -0
- package/lib/memory/service.d.ts +39 -0
- package/lib/memory/service.js +39 -0
- package/lib/memory/store.d.ts +45 -0
- package/lib/memory/store.js +123 -0
- package/lib/memory/tools.d.ts +19 -0
- package/lib/memory/tools.js +195 -0
- package/lib/memory/types.d.ts +55 -0
- package/lib/memory/types.js +6 -0
- package/lib/paper/commands.d.ts +13 -0
- package/lib/paper/commands.js +84 -0
- package/lib/paper/lib/aicheck.d.ts +38 -0
- package/lib/paper/lib/aicheck.js +241 -0
- package/lib/paper/lib/bibtex.d.ts +21 -0
- package/lib/paper/lib/bibtex.js +114 -0
- package/lib/paper/lib/check.d.ts +32 -0
- package/lib/paper/lib/check.js +215 -0
- package/lib/paper/lib/defense.d.ts +48 -0
- package/lib/paper/lib/defense.js +220 -0
- package/lib/paper/lib/docx.d.ts +35 -0
- package/lib/paper/lib/docx.js +213 -0
- package/lib/paper/lib/layout.d.ts +41 -0
- package/lib/paper/lib/layout.js +572 -0
- package/lib/paper/lib/ledger.d.ts +112 -0
- package/lib/paper/lib/ledger.js +349 -0
- package/lib/paper/lib/lit-api.d.ts +59 -0
- package/lib/paper/lib/lit-api.js +296 -0
- package/lib/paper/lib/lit-cache.d.ts +32 -0
- package/lib/paper/lib/lit-cache.js +91 -0
- package/lib/paper/lib/project.d.ts +29 -0
- package/lib/paper/lib/project.js +93 -0
- package/lib/paper/lib/review.d.ts +37 -0
- package/lib/paper/lib/review.js +194 -0
- package/lib/paper/lib/zip.d.ts +14 -0
- package/lib/paper/lib/zip.js +124 -0
- package/lib/paper/register.d.ts +20 -0
- package/lib/paper/register.js +183 -0
- package/lib/paper/tools/aicheck.d.ts +6 -0
- package/lib/paper/tools/aicheck.js +38 -0
- package/lib/paper/tools/build.d.ts +27 -0
- package/lib/paper/tools/build.js +166 -0
- package/lib/paper/tools/check.d.ts +7 -0
- package/lib/paper/tools/check.js +79 -0
- package/lib/paper/tools/decision.d.ts +13 -0
- package/lib/paper/tools/decision.js +53 -0
- package/lib/paper/tools/defense.d.ts +11 -0
- package/lib/paper/tools/defense.js +74 -0
- package/lib/paper/tools/init.d.ts +23 -0
- package/lib/paper/tools/init.js +99 -0
- package/lib/paper/tools/lit.d.ts +27 -0
- package/lib/paper/tools/lit.js +236 -0
- package/lib/paper/tools/progress.d.ts +18 -0
- package/lib/paper/tools/progress.js +77 -0
- package/lib/paper/tools/review.d.ts +11 -0
- package/lib/paper/tools/review.js +41 -0
- package/lib/ppt/actions.d.ts +97 -0
- package/lib/ppt/actions.js +263 -0
- package/lib/ppt/check.d.ts +64 -0
- package/lib/ppt/check.js +185 -0
- package/lib/ppt/commands.d.ts +28 -0
- package/lib/ppt/commands.js +71 -0
- package/lib/ppt/convert.d.ts +146 -0
- package/lib/ppt/convert.js +423 -0
- package/lib/ppt/index.d.ts +45 -0
- package/lib/ppt/index.js +57 -0
- package/lib/ppt/marp.d.ts +74 -0
- package/lib/ppt/marp.js +165 -0
- package/lib/ppt/outline.d.ts +206 -0
- package/lib/ppt/outline.js +695 -0
- package/lib/shared/define-tool.d.ts +77 -0
- package/lib/shared/define-tool.js +235 -0
- package/lib/shared/fs-errors.d.ts +50 -0
- package/lib/shared/fs-errors.js +90 -0
- package/lib/shared/index.d.ts +31 -0
- package/lib/shared/index.js +32 -0
- package/lib/shared/spawn.d.ts +38 -0
- package/lib/shared/spawn.js +50 -0
- package/lib/shared/text.d.ts +14 -0
- package/lib/shared/text.js +26 -0
- package/package.json +82 -0
- package/skills/code-walkthrough/SKILL.md +94 -0
- package/skills/code-walkthrough/references/examples.md +129 -0
- package/skills/paper-dedup/SKILL.md +58 -0
- package/skills/paper-intake/SKILL.md +64 -0
- package/skills/thesis-citation/SKILL.md +67 -0
- package/skills/thesis-defense/SKILL.md +87 -0
- package/skills/thesis-eng-design/SKILL.md +97 -0
- package/skills/thesis-inquiry/SKILL.md +55 -0
- package/skills/thesis-inquiry/references/intent-spec-template.md +39 -0
- package/skills/thesis-literature/SKILL.md +56 -0
- package/skills/thesis-opener/SKILL.md +77 -0
- package/skills/thesis-pipeline/SKILL.md +121 -0
- package/skills/thesis-writing/SKILL.md +86 -0
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 本插件可选消费的宿主表面的结构化契约:命令注册表、shell 执行器,以及接收
|
|
3
|
+
* 命令的 agent。
|
|
4
|
+
*
|
|
5
|
+
* 刻意**不**从 `@deepseek-ai/dsh-*` 导入:已发布的 rc.1 依赖树引用了未发布的包,
|
|
6
|
+
* 因此外部 bundle 不能安装 dsh 包。这些接口只声明插件真正读取的字段;宿主真实的
|
|
7
|
+
* 服务在运行期满足它们。必需的 `fs` 接缝在 `fs-types.ts` 里。
|
|
8
|
+
*
|
|
9
|
+
* @module dsh-thesis/codewalk
|
|
10
|
+
*/
|
|
11
|
+
/** shell 执行器捕获的一条输出流。 */
|
|
12
|
+
export interface CollectedOutputShape {
|
|
13
|
+
/** 捕获到的文本 —— 发生截断时是这条流的**尾部**。 */
|
|
14
|
+
readonly text: string;
|
|
15
|
+
/** 为 true 表示 `text` 中丢弃了字节。 */
|
|
16
|
+
readonly truncated: boolean;
|
|
17
|
+
/** 保存**完整**流的文件路径(若可用)。 */
|
|
18
|
+
readonly spillPath?: string;
|
|
19
|
+
}
|
|
20
|
+
/** 前台 shell 结果:非零退出会正常 resolve,绝不 reject。 */
|
|
21
|
+
export interface ShellRunResultShape {
|
|
22
|
+
/** 退出码;进程被信号杀死时为 null。 */
|
|
23
|
+
readonly exitCode: number | null;
|
|
24
|
+
/** 终止信号(如 'SIGTERM');正常退出时为 null。 */
|
|
25
|
+
readonly signal: string | null;
|
|
26
|
+
/** 为 true 表示执行器自身的超时杀掉了命令。 */
|
|
27
|
+
readonly timedOut: boolean;
|
|
28
|
+
/** 为 true 表示调用方的 AbortSignal 杀掉了命令。 */
|
|
29
|
+
readonly aborted: boolean;
|
|
30
|
+
/** 本次运行实际生效的超时。 */
|
|
31
|
+
readonly timeoutMs: number;
|
|
32
|
+
readonly stdout: CollectedOutputShape;
|
|
33
|
+
readonly stderr: CollectedOutputShape;
|
|
34
|
+
}
|
|
35
|
+
/** 插件会设置的 shell 执行请求子集。 */
|
|
36
|
+
export interface ShellExecSpecShape {
|
|
37
|
+
/** 完整命令行,如 "go build ./..."。 */
|
|
38
|
+
readonly command: string;
|
|
39
|
+
readonly workdir?: string;
|
|
40
|
+
readonly timeoutMs?: number;
|
|
41
|
+
readonly stdoutMaxBytes?: number;
|
|
42
|
+
readonly signal?: AbortSignal;
|
|
43
|
+
/** 由调用会话解析出的本次调用沙箱策略。 */
|
|
44
|
+
readonly sandboxPolicy?: unknown;
|
|
45
|
+
}
|
|
46
|
+
/** shell 接缝(`ctx.shell`);每个宿主由一个 bash provider 提供。 */
|
|
47
|
+
export interface ShellServiceShape {
|
|
48
|
+
run(spec: ShellExecSpecShape): Promise<ShellRunResultShape>;
|
|
49
|
+
}
|
|
50
|
+
/** 命令被调用时所针对的接收 agent 切片。 */
|
|
51
|
+
export interface AgentShape {
|
|
52
|
+
readonly session: {
|
|
53
|
+
readonly header: {
|
|
54
|
+
/** 会话工作目录;DSH 契约里可缺省(例如无工作区的会话)。 */
|
|
55
|
+
readonly cwd?: string;
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
/** 传给某个已注册命令 handler 的调用信息。 */
|
|
60
|
+
export interface CommandInvocationShape {
|
|
61
|
+
readonly commandId: unknown;
|
|
62
|
+
readonly agent: AgentShape;
|
|
63
|
+
readonly rawInput: string;
|
|
64
|
+
readonly signal: AbortSignal;
|
|
65
|
+
}
|
|
66
|
+
/** 由调度 UI 直接渲染的命令结果。 */
|
|
67
|
+
export type CommandResultShape = {
|
|
68
|
+
readonly kind: 'success';
|
|
69
|
+
readonly text?: string;
|
|
70
|
+
} | {
|
|
71
|
+
readonly kind: 'error';
|
|
72
|
+
readonly text: string;
|
|
73
|
+
};
|
|
74
|
+
/** 插件自有命令注册(`ctx.commands.register`)。 */
|
|
75
|
+
export interface CommandDefinitionShape {
|
|
76
|
+
readonly name: string;
|
|
77
|
+
readonly description: string;
|
|
78
|
+
readonly input?: {
|
|
79
|
+
readonly hint: string;
|
|
80
|
+
};
|
|
81
|
+
readonly recordInput?: boolean;
|
|
82
|
+
handler(invocation: CommandInvocationShape): CommandResultShape | Promise<CommandResultShape>;
|
|
83
|
+
}
|
|
84
|
+
/** 命令注册表(`ctx.commands`);在 headless 组合里是可选的。 */
|
|
85
|
+
export interface CommandsServiceShape {
|
|
86
|
+
register(definition: CommandDefinitionShape): unknown;
|
|
87
|
+
}
|
|
88
|
+
/** 面向模型的消息或工具渲染中的一个文本内容块。 */
|
|
89
|
+
export interface TextBlockShape {
|
|
90
|
+
readonly type: 'text';
|
|
91
|
+
readonly text: string;
|
|
92
|
+
}
|
|
93
|
+
/** 工具注册表(`ctx.tools`);在无执行器的组合里是可选的。 */
|
|
94
|
+
export interface ToolsServiceShape {
|
|
95
|
+
register(definition: ToolDefinitionShape): unknown;
|
|
96
|
+
}
|
|
97
|
+
/** 一个已注册的工具:JSON Schema 参数 + 执行 + 渲染。 */
|
|
98
|
+
export interface ToolDefinitionShape {
|
|
99
|
+
readonly name: string;
|
|
100
|
+
readonly description: string;
|
|
101
|
+
/** 参数的 JSON Schema 对象。 */
|
|
102
|
+
readonly parameters: Record<string, unknown>;
|
|
103
|
+
readonly output: {
|
|
104
|
+
readonly schema: Record<string, unknown>;
|
|
105
|
+
render(args: unknown, value: unknown): TextBlockShape[];
|
|
106
|
+
};
|
|
107
|
+
execute(args: unknown, exec: ToolRunContextShape): Promise<unknown>;
|
|
108
|
+
readonly timeoutMs?: number;
|
|
109
|
+
}
|
|
110
|
+
/** 交给工具主体的运行期上下文。 */
|
|
111
|
+
export interface ToolRunContextShape {
|
|
112
|
+
readonly callId: unknown;
|
|
113
|
+
/** 本次调用所代表的 agent;在无执行器的循环里缺席。 */
|
|
114
|
+
readonly agent?: AgentShape;
|
|
115
|
+
readonly signal: AbortSignal;
|
|
116
|
+
}
|
|
117
|
+
/** 为 pre-step 上下文注入的一条临时 user 角色消息。 */
|
|
118
|
+
export interface InjectedUserMessageShape {
|
|
119
|
+
readonly id: string;
|
|
120
|
+
readonly role: 'user';
|
|
121
|
+
readonly content: readonly TextBlockShape[];
|
|
122
|
+
readonly source: {
|
|
123
|
+
readonly kind: 'plugin';
|
|
124
|
+
readonly plugin: string;
|
|
125
|
+
readonly form: string;
|
|
126
|
+
readonly sections: readonly {
|
|
127
|
+
readonly name: string;
|
|
128
|
+
readonly text: string;
|
|
129
|
+
}[];
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
/** 插件扩展的 `agent/pre-step` waterfall 决策。 */
|
|
133
|
+
export interface PreStepDecisionShape {
|
|
134
|
+
readonly kind: 'enter' | 'reject';
|
|
135
|
+
readonly messages: readonly InjectedUserMessageShape[];
|
|
136
|
+
}
|
|
137
|
+
/** 一次 `agent/pre-step` waterfall 派发的载荷。 */
|
|
138
|
+
export interface PreStepPayloadShape {
|
|
139
|
+
readonly agent: AgentShape;
|
|
140
|
+
readonly turn: number;
|
|
141
|
+
readonly step: number;
|
|
142
|
+
readonly signal: AbortSignal;
|
|
143
|
+
}
|
|
144
|
+
/** 技能摘要携带的模型/用户可调用性开关。 */
|
|
145
|
+
export interface SkillInvocationPolicyShape {
|
|
146
|
+
readonly modelInvocable: boolean;
|
|
147
|
+
readonly userInvocable: boolean;
|
|
148
|
+
}
|
|
149
|
+
/** provider 特有的相对技能资源基址。 */
|
|
150
|
+
export type SkillResourceBaseShape = {
|
|
151
|
+
readonly kind: 'directory';
|
|
152
|
+
readonly path: string;
|
|
153
|
+
} | {
|
|
154
|
+
readonly kind: 'url';
|
|
155
|
+
readonly url: string;
|
|
156
|
+
} | {
|
|
157
|
+
readonly kind: 'opaque';
|
|
158
|
+
readonly description: string;
|
|
159
|
+
};
|
|
160
|
+
/** 一条 provider 目录条目。 */
|
|
161
|
+
export interface SkillCandidateShape {
|
|
162
|
+
readonly name: string;
|
|
163
|
+
readonly description: string;
|
|
164
|
+
readonly whenToUse?: string;
|
|
165
|
+
readonly invocation: SkillInvocationPolicyShape;
|
|
166
|
+
readonly provider: string;
|
|
167
|
+
readonly source: string;
|
|
168
|
+
readonly resourceBase?: SkillResourceBaseShape;
|
|
169
|
+
/** 同名技能里 rank 更小者胜出。 */
|
|
170
|
+
readonly rank: number;
|
|
171
|
+
/** provider 自有的不透明句柄,会原样传回 `provider.get()`。 */
|
|
172
|
+
readonly locator: unknown;
|
|
173
|
+
readonly path?: string;
|
|
174
|
+
readonly metadata?: Readonly<Record<string, unknown>>;
|
|
175
|
+
}
|
|
176
|
+
/** `provider.get()` 返回的完整已解析技能正文。 */
|
|
177
|
+
export interface SkillDefinitionShape {
|
|
178
|
+
readonly name: string;
|
|
179
|
+
readonly description: string;
|
|
180
|
+
readonly whenToUse?: string;
|
|
181
|
+
readonly invocation: SkillInvocationPolicyShape;
|
|
182
|
+
readonly provider: string;
|
|
183
|
+
readonly source: string;
|
|
184
|
+
readonly resourceBase?: SkillResourceBaseShape;
|
|
185
|
+
readonly content: string;
|
|
186
|
+
readonly path?: string;
|
|
187
|
+
readonly metadata?: Readonly<Record<string, unknown>>;
|
|
188
|
+
}
|
|
189
|
+
/** 注册在 `ctx.skills` 上的一个技能来源。 */
|
|
190
|
+
export interface SkillsProviderShape {
|
|
191
|
+
readonly name: string;
|
|
192
|
+
list(options: unknown): Promise<readonly SkillCandidateShape[]>;
|
|
193
|
+
get(candidate: SkillCandidateShape, options: unknown): Promise<SkillDefinitionShape | undefined>;
|
|
194
|
+
}
|
|
195
|
+
/** 技能注册表(`ctx.skills`);在最小组合里是可选的。 */
|
|
196
|
+
export interface SkillsServiceShape {
|
|
197
|
+
registerProvider(create: (control: unknown) => SkillsProviderShape): () => void;
|
|
198
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 本插件可选消费的宿主表面的结构化契约:命令注册表、shell 执行器,以及接收
|
|
3
|
+
* 命令的 agent。
|
|
4
|
+
*
|
|
5
|
+
* 刻意**不**从 `@deepseek-ai/dsh-*` 导入:已发布的 rc.1 依赖树引用了未发布的包,
|
|
6
|
+
* 因此外部 bundle 不能安装 dsh 包。这些接口只声明插件真正读取的字段;宿主真实的
|
|
7
|
+
* 服务在运行期满足它们。必需的 `fs` 接缝在 `fs-types.ts` 里。
|
|
8
|
+
*
|
|
9
|
+
* @module dsh-thesis/codewalk
|
|
10
|
+
*/
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pre-step 进度注入:当会话 cwd 下存在进行中的代码演练时,每个 agent step 都会
|
|
3
|
+
* 收到一张紧凑的进度卡片,因此无论是续接的会话还是全新的会话,都不必从零重建
|
|
4
|
+
* 这次演练的全部上下文。
|
|
5
|
+
*
|
|
6
|
+
* 卡片只在状态文件确实变化时才重新注入(按 agent 用 `updatedAt` 跟踪),把
|
|
7
|
+
* token 开销压到「每次状态变更一张卡」。
|
|
8
|
+
*
|
|
9
|
+
* @module dsh-thesis/codewalk
|
|
10
|
+
*/
|
|
11
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
12
|
+
import { AiLearningEngine } from './engine.ts';
|
|
13
|
+
import type { InjectedUserMessageShape } from './host-types.ts';
|
|
14
|
+
/** 为一份状态快照构造注入用的进度消息。 */
|
|
15
|
+
export declare function buildProgressMessage(state: Awaited<ReturnType<AiLearningEngine['load']>> & object): InjectedUserMessageShape;
|
|
16
|
+
/** 注册 pre-step 监听器;只在状态变化时重新注入。 */
|
|
17
|
+
export declare function registerPreStep(ctx: Context, engine: AiLearningEngine): void;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pre-step 进度注入:当会话 cwd 下存在进行中的代码演练时,每个 agent step 都会
|
|
3
|
+
* 收到一张紧凑的进度卡片,因此无论是续接的会话还是全新的会话,都不必从零重建
|
|
4
|
+
* 这次演练的全部上下文。
|
|
5
|
+
*
|
|
6
|
+
* 卡片只在状态文件确实变化时才重新注入(按 agent 用 `updatedAt` 跟踪),把
|
|
7
|
+
* token 开销压到「每次状态变更一张卡」。
|
|
8
|
+
*
|
|
9
|
+
* @module dsh-thesis/codewalk
|
|
10
|
+
*/
|
|
11
|
+
import { AiLearningEngine } from "./engine.js";
|
|
12
|
+
import { newMessageId } from "./tools.js";
|
|
13
|
+
/** 为一份状态快照构造注入用的进度消息。 */
|
|
14
|
+
export function buildProgressMessage(state) {
|
|
15
|
+
const text = [
|
|
16
|
+
'当前工作区有一个进行中的代码演练(把自己的系统拆成讲得清的模块,并用可评分的追问确认你答辩时讲得出实现细节)。请带学生把它走完。',
|
|
17
|
+
'',
|
|
18
|
+
'和学生一起推进:带他做完当前里程碑的 todo,逐个提出追问,先沿提示阶梯升级再公布答案,并对照期望要点评分。用 defense_code_status、defense_code_next、defense_code_update 三个工具;只有学生说“做完了”才跑 "/thesis-defense check <milestone>"。',
|
|
19
|
+
'',
|
|
20
|
+
].join('\n');
|
|
21
|
+
const full = `${text}${JSON.stringify(state, null, 2)}`;
|
|
22
|
+
return {
|
|
23
|
+
id: newMessageId(),
|
|
24
|
+
role: 'user',
|
|
25
|
+
content: [{ type: 'text', text: full }],
|
|
26
|
+
source: {
|
|
27
|
+
kind: 'plugin',
|
|
28
|
+
plugin: 'dsh-thesis',
|
|
29
|
+
form: 'snapshot',
|
|
30
|
+
sections: [{ name: '代码演练进度', text: full }],
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
/** 注册 pre-step 监听器;只在状态变化时重新注入。 */
|
|
35
|
+
export function registerPreStep(ctx, engine) {
|
|
36
|
+
const lastInjected = new WeakMap();
|
|
37
|
+
// 宿主的 `agent/pre-step` waterfall 由本 bundle 无法安装的包声明,
|
|
38
|
+
// 因此事件名按无类型方式派发。
|
|
39
|
+
const on = ctx.on.bind(ctx);
|
|
40
|
+
on('agent/pre-step', async (payload, next) => {
|
|
41
|
+
const { agent, signal } = payload;
|
|
42
|
+
const decision = await next();
|
|
43
|
+
if (decision.kind === 'reject' || signal.aborted)
|
|
44
|
+
return decision;
|
|
45
|
+
const cwd = agent?.session?.header?.cwd;
|
|
46
|
+
if (typeof cwd !== 'string')
|
|
47
|
+
return decision;
|
|
48
|
+
let state;
|
|
49
|
+
try {
|
|
50
|
+
state = await engine.load(cwd);
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
return decision;
|
|
54
|
+
}
|
|
55
|
+
if (state === undefined || state.phase === 'complete')
|
|
56
|
+
return decision;
|
|
57
|
+
if (lastInjected.get(agent) === state.updatedAt)
|
|
58
|
+
return decision;
|
|
59
|
+
lastInjected.set(agent, state.updatedAt);
|
|
60
|
+
return { kind: 'enter', messages: [...decision.messages, buildProgressMessage(state)] };
|
|
61
|
+
}, { prepend: true });
|
|
62
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 代码演练模块的装配入口(`apply` 之外唯一需要调用的函数)。
|
|
3
|
+
*
|
|
4
|
+
* 模块的角色:把 AI 写的系统代码拆成「能跑的骨架 + 可评分的追问」,
|
|
5
|
+
* 保证学生答辩时讲得出自己系统的实现与取舍。引擎守住流程,模型负责教学。
|
|
6
|
+
*
|
|
7
|
+
* 装配顺序与 `src/index.ts` 的无关,四个表面互不依赖:
|
|
8
|
+
* 引擎 → `paperCodeWalkthrough` 服务 → 命令 / 模型工具 / pre-step 注入 / 技能提供者。
|
|
9
|
+
*
|
|
10
|
+
* 注意:本文件只做**装配**,不导入 `src/config.ts` 的运行时值(只导入类型),
|
|
11
|
+
* 因此单测可以在不安装 schemastery 的前提下直接 `import` 它。
|
|
12
|
+
*
|
|
13
|
+
* @module dsh-thesis/codewalk
|
|
14
|
+
*/
|
|
15
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
16
|
+
import type { CodeWalkthroughOptions } from '../config.ts';
|
|
17
|
+
/**
|
|
18
|
+
* 用宿主 `dsh-thesis` 的配置装配代码演练模块。
|
|
19
|
+
*
|
|
20
|
+
* @param ctx 插件 fiber 的上下文(需要 `fs`;`tools`/`skills` 可选)。
|
|
21
|
+
* @param options 来自 `resolveConfig(config).codeWalkthrough` 的已解析配置。
|
|
22
|
+
*/
|
|
23
|
+
export declare function registerCodewalk(ctx: Context, options: CodeWalkthroughOptions): void;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 代码演练模块的装配入口(`apply` 之外唯一需要调用的函数)。
|
|
3
|
+
*
|
|
4
|
+
* 模块的角色:把 AI 写的系统代码拆成「能跑的骨架 + 可评分的追问」,
|
|
5
|
+
* 保证学生答辩时讲得出自己系统的实现与取舍。引擎守住流程,模型负责教学。
|
|
6
|
+
*
|
|
7
|
+
* 装配顺序与 `src/index.ts` 的无关,四个表面互不依赖:
|
|
8
|
+
* 引擎 → `paperCodeWalkthrough` 服务 → 命令 / 模型工具 / pre-step 注入 / 技能提供者。
|
|
9
|
+
*
|
|
10
|
+
* 注意:本文件只做**装配**,不导入 `src/config.ts` 的运行时值(只导入类型),
|
|
11
|
+
* 因此单测可以在不安装 schemastery 的前提下直接 `import` 它。
|
|
12
|
+
*
|
|
13
|
+
* @module dsh-thesis/codewalk
|
|
14
|
+
*/
|
|
15
|
+
import { AiLearningEngine } from "./engine.js";
|
|
16
|
+
import { registerPreStep } from "./prestep.js";
|
|
17
|
+
import { registerSkill } from "./skill.js";
|
|
18
|
+
import { registerTools } from "./tools.js";
|
|
19
|
+
/**
|
|
20
|
+
* 用宿主 `dsh-thesis` 的配置装配代码演练模块。
|
|
21
|
+
*
|
|
22
|
+
* @param ctx 插件 fiber 的上下文(需要 `fs`;`tools`/`skills` 可选)。
|
|
23
|
+
* @param options 来自 `resolveConfig(config).codeWalkthrough` 的已解析配置。
|
|
24
|
+
*/
|
|
25
|
+
export function registerCodewalk(ctx, options) {
|
|
26
|
+
const engine = new AiLearningEngine(ctx, options);
|
|
27
|
+
ctx.provide('paperCodeWalkthrough', engine);
|
|
28
|
+
registerTools(ctx, engine);
|
|
29
|
+
registerPreStep(ctx, engine);
|
|
30
|
+
registerSkill(ctx);
|
|
31
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 随包发布的 `code-walkthrough` 技能提供者(答辩层的代码演练方法论)。
|
|
3
|
+
*
|
|
4
|
+
* 把「答辩前把自己的系统讲清楚」的方法论打包成一个 Markdown 技能
|
|
5
|
+
* (与 `@deepseek-ai/dsh-skill-badge` 同一套做法):只登记一个不可变候选,
|
|
6
|
+
* 正文从包的 `skills/code-walkthrough/` 目录读取,并把该目录暴露为资源基址,
|
|
7
|
+
* 因此正文里的 `references/*.md` 可以按需通过技能工具加载。
|
|
8
|
+
* 方法论始终是可编辑的 Markdown —— 插件代码只承载机制。
|
|
9
|
+
*
|
|
10
|
+
* @module dsh-thesis/codewalk
|
|
11
|
+
*/
|
|
12
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
13
|
+
export declare const SKILL_NAME = "code-walkthrough";
|
|
14
|
+
/** 组合了技能注册表时注册这个随包技能提供者。 */
|
|
15
|
+
export declare function registerSkill(ctx: Context): void;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 随包发布的 `code-walkthrough` 技能提供者(答辩层的代码演练方法论)。
|
|
3
|
+
*
|
|
4
|
+
* 把「答辩前把自己的系统讲清楚」的方法论打包成一个 Markdown 技能
|
|
5
|
+
* (与 `@deepseek-ai/dsh-skill-badge` 同一套做法):只登记一个不可变候选,
|
|
6
|
+
* 正文从包的 `skills/code-walkthrough/` 目录读取,并把该目录暴露为资源基址,
|
|
7
|
+
* 因此正文里的 `references/*.md` 可以按需通过技能工具加载。
|
|
8
|
+
* 方法论始终是可编辑的 Markdown —— 插件代码只承载机制。
|
|
9
|
+
*
|
|
10
|
+
* @module dsh-thesis/codewalk
|
|
11
|
+
*/
|
|
12
|
+
import { readFile } from 'node:fs/promises';
|
|
13
|
+
import { fileURLToPath } from 'node:url';
|
|
14
|
+
const SKILL_DIR_URL = new URL('../../skills/code-walkthrough/', import.meta.url);
|
|
15
|
+
const SKILL_BODY_URL = new URL('SKILL.md', SKILL_DIR_URL);
|
|
16
|
+
/** 技能正文的磁盘路径;`readFile` 在本仓库的类型面里只接受字符串路径。 */
|
|
17
|
+
const SKILL_BODY_PATH = fileURLToPath(SKILL_BODY_URL);
|
|
18
|
+
const RESOURCE_BASE = { kind: 'directory', path: fileURLToPath(SKILL_DIR_URL) };
|
|
19
|
+
export const SKILL_NAME = 'code-walkthrough';
|
|
20
|
+
const PROVIDER_NAME = 'dsh-thesis';
|
|
21
|
+
const DESCRIPTION = '把自己系统(常常是 AI 写的)拆成能讲清的模块,并用可评分的追问确认你在答辩席上讲得出实现细节与取舍。' +
|
|
22
|
+
'答辩几乎必问「你的系统怎么实现的」「为什么这么设计」,答不上来是最常见的失分点。' +
|
|
23
|
+
'触发场景:「答辩前我要搞懂自己系统的实现」「老师会问实现细节」「把这些代码拆成我讲得清的部分」。';
|
|
24
|
+
const WHEN_TO_USE = '当用户说「答辩前要把自己的系统讲明白」「老师会问实现细节/为什么这么设计」「帮我理清这套代码好答辩」,' +
|
|
25
|
+
'或在 `thesis_defense` 生成了预答辩问题库、需要逐个准备「实现细节」类问题时触发。';
|
|
26
|
+
const INVOCATION = { modelInvocable: true, userInvocable: true };
|
|
27
|
+
const CANDIDATE = {
|
|
28
|
+
name: SKILL_NAME,
|
|
29
|
+
description: DESCRIPTION,
|
|
30
|
+
whenToUse: WHEN_TO_USE,
|
|
31
|
+
invocation: INVOCATION,
|
|
32
|
+
provider: PROVIDER_NAME,
|
|
33
|
+
source: 'bundled',
|
|
34
|
+
resourceBase: RESOURCE_BASE,
|
|
35
|
+
// 低于所有本地文件系统来源(100–600),因此用户自己的同名技能会优先;
|
|
36
|
+
// 同时足够高,不会抢别的技能。
|
|
37
|
+
rank: 900,
|
|
38
|
+
locator: SKILL_BODY_URL,
|
|
39
|
+
};
|
|
40
|
+
const provider = {
|
|
41
|
+
name: PROVIDER_NAME,
|
|
42
|
+
list: () => Promise.resolve([CANDIDATE]),
|
|
43
|
+
async get(_candidate) {
|
|
44
|
+
return {
|
|
45
|
+
...CANDIDATE,
|
|
46
|
+
...(CANDIDATE.whenToUse !== undefined ? { whenToUse: CANDIDATE.whenToUse } : {}),
|
|
47
|
+
content: await readFile(SKILL_BODY_PATH, 'utf8'),
|
|
48
|
+
};
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
/** 组合了技能注册表时注册这个随包技能提供者。 */
|
|
52
|
+
export function registerSkill(ctx) {
|
|
53
|
+
const skills = ctx.get('skills');
|
|
54
|
+
if (skills === undefined)
|
|
55
|
+
return;
|
|
56
|
+
skills.registerProvider(() => provider);
|
|
57
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 面向前模型的工具:`defense_code_status`、`defense_code_next`、`defense_code_update`。
|
|
3
|
+
*
|
|
4
|
+
* 这三个工具是模型操作引擎的手柄:分析架构、安排教学由模型完成,但每一次改动
|
|
5
|
+
* 都必须穿过引擎校验过的状态迁移,并立刻落盘。工具注册走 `ctx.tools`(只有在
|
|
6
|
+
* 组合了工具注册表时才注册);定义是纯对象,因此不需要任何 `@deepseek-ai/dsh-*`
|
|
7
|
+
* 的运行时导入。
|
|
8
|
+
*
|
|
9
|
+
* @module dsh-thesis/codewalk
|
|
10
|
+
*/
|
|
11
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
12
|
+
import { AiLearningEngine } from './engine.ts';
|
|
13
|
+
import { isLearningError } from './errors.ts';
|
|
14
|
+
/** 组合了工具注册表时,注册这三个面向前模型的工具。 */
|
|
15
|
+
export declare function registerTools(ctx: Context, engine: AiLearningEngine): void;
|
|
16
|
+
/** pre-step 注入用的随机 id 生成器;导出以便复用。 */
|
|
17
|
+
export declare function newMessageId(): string;
|
|
18
|
+
export { isLearningError };
|