@leterhong/multichat 1.6.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.
Files changed (214) hide show
  1. package/.agents/plugins/marketplace.json +32 -0
  2. package/.agents/plugins/plugins/developer-toolkit/.codex-plugin/plugin.json +24 -0
  3. package/.agents/plugins/plugins/developer-toolkit/skills/code-review/SKILL.md +9 -0
  4. package/.agents/plugins/plugins/developer-toolkit/skills/code-review/agents/openai.yaml +3 -0
  5. package/.agents/plugins/plugins/developer-toolkit/skills/release-notes/SKILL.md +9 -0
  6. package/.agents/plugins/plugins/developer-toolkit/skills/release-notes/agents/openai.yaml +3 -0
  7. package/.agents/plugins/plugins/developer-toolkit/skills/security-review/SKILL.md +9 -0
  8. package/.agents/plugins/plugins/developer-toolkit/skills/security-review/agents/openai.yaml +3 -0
  9. package/.agents/plugins/plugins/developer-toolkit/skills/test-plan/SKILL.md +9 -0
  10. package/.agents/plugins/plugins/developer-toolkit/skills/test-plan/agents/openai.yaml +3 -0
  11. package/.agents/plugins/plugins/writing-toolkit/.codex-plugin/plugin.json +24 -0
  12. package/.agents/plugins/plugins/writing-toolkit/skills/meeting-notes/SKILL.md +9 -0
  13. package/.agents/plugins/plugins/writing-toolkit/skills/meeting-notes/agents/openai.yaml +3 -0
  14. package/.agents/plugins/plugins/writing-toolkit/skills/resume-tune/SKILL.md +9 -0
  15. package/.agents/plugins/plugins/writing-toolkit/skills/resume-tune/agents/openai.yaml +3 -0
  16. package/.agents/plugins/plugins/writing-toolkit/skills/weekly-report/SKILL.md +9 -0
  17. package/.agents/plugins/plugins/writing-toolkit/skills/weekly-report/agents/openai.yaml +3 -0
  18. package/.agents/skills/.gitkeep +1 -0
  19. package/.agents/skills/wanghong-handwritten-ppt/SKILL.md +172 -0
  20. package/.agents/skills/wanghong-handwritten-ppt/assets/HTML-PPT-LICENSE +21 -0
  21. package/.agents/skills/wanghong-handwritten-ppt/assets/NEAT-ANNOTATIONS-LICENSE +21 -0
  22. package/.agents/skills/wanghong-handwritten-ppt/assets/animations.css +138 -0
  23. package/.agents/skills/wanghong-handwritten-ppt/assets/base.css +150 -0
  24. package/.agents/skills/wanghong-handwritten-ppt/assets/deepseek-example.css +893 -0
  25. package/.agents/skills/wanghong-handwritten-ppt/assets/neat-annotations.css +152 -0
  26. package/.agents/skills/wanghong-handwritten-ppt/assets/preview-cover.png +0 -0
  27. package/.agents/skills/wanghong-handwritten-ppt/assets/preview-diagram.png +0 -0
  28. package/.agents/skills/wanghong-handwritten-ppt/assets/preview-summary.png +0 -0
  29. package/.agents/skills/wanghong-handwritten-ppt/assets/preview-table.png +0 -0
  30. package/.agents/skills/wanghong-handwritten-ppt/assets/runtime.js +960 -0
  31. package/.agents/skills/wanghong-handwritten-ppt/assets/template.css +198 -0
  32. package/.agents/skills/wanghong-handwritten-ppt/evals/evals.json +20 -0
  33. package/.agents/skills/wanghong-handwritten-ppt/examples/deepseek-v4-flash/index.html +414 -0
  34. package/.agents/skills/wanghong-handwritten-ppt/examples/deepseek-v4-flash/style.css +897 -0
  35. package/.agents/skills/wanghong-handwritten-ppt/references/prompts.md +170 -0
  36. package/.agents/skills/wanghong-handwritten-ppt/references/style-guide.md +133 -0
  37. package/.agents/skills/wanghong-handwritten-ppt/scripts/check_deck.py +41 -0
  38. package/.agents/skills/wanghong-handwritten-ppt/scripts/prepare_render_html.py +137 -0
  39. package/.agents/skills/wanghong-handwritten-ppt/scripts/render.sh +110 -0
  40. package/.agents/skills/wanghong-handwritten-ppt/templates/deck.html +94 -0
  41. package/.agents/skills/wanghong-handwritten-ppt/tests/test_font_contract.py +73 -0
  42. package/LICENSE +21 -0
  43. package/README.md +186 -0
  44. package/backend/adapters/README.md +77 -0
  45. package/backend/adapters/anthropic.ts +115 -0
  46. package/backend/adapters/base.ts +47 -0
  47. package/backend/adapters/index.ts +41 -0
  48. package/backend/adapters/lmstudio.ts +7 -0
  49. package/backend/adapters/moonshot.ts +7 -0
  50. package/backend/adapters/ollama.ts +7 -0
  51. package/backend/adapters/openai-compatible.ts +51 -0
  52. package/backend/adapters/openai.ts +7 -0
  53. package/backend/adapters/qwen.ts +112 -0
  54. package/backend/adapters/wenxin.ts +136 -0
  55. package/backend/adapters/zhipu.ts +93 -0
  56. package/backend/dist/adapters/anthropic.js +130 -0
  57. package/backend/dist/adapters/anthropic.js.map +1 -0
  58. package/backend/dist/adapters/base.js +38 -0
  59. package/backend/dist/adapters/base.js.map +1 -0
  60. package/backend/dist/adapters/index.js +39 -0
  61. package/backend/dist/adapters/index.js.map +1 -0
  62. package/backend/dist/adapters/lmstudio.js +8 -0
  63. package/backend/dist/adapters/lmstudio.js.map +1 -0
  64. package/backend/dist/adapters/moonshot.js +8 -0
  65. package/backend/dist/adapters/moonshot.js.map +1 -0
  66. package/backend/dist/adapters/ollama.js +8 -0
  67. package/backend/dist/adapters/ollama.js.map +1 -0
  68. package/backend/dist/adapters/openai-compatible.js +47 -0
  69. package/backend/dist/adapters/openai-compatible.js.map +1 -0
  70. package/backend/dist/adapters/openai.js +8 -0
  71. package/backend/dist/adapters/openai.js.map +1 -0
  72. package/backend/dist/adapters/qwen.js +103 -0
  73. package/backend/dist/adapters/qwen.js.map +1 -0
  74. package/backend/dist/adapters/wenxin.js +114 -0
  75. package/backend/dist/adapters/wenxin.js.map +1 -0
  76. package/backend/dist/adapters/zhipu.js +86 -0
  77. package/backend/dist/adapters/zhipu.js.map +1 -0
  78. package/backend/dist/extensions/demo-mcp-server.js +75 -0
  79. package/backend/dist/extensions/demo-mcp-server.js.map +1 -0
  80. package/backend/dist/extensions/importer.js +828 -0
  81. package/backend/dist/extensions/importer.js.map +1 -0
  82. package/backend/dist/extensions/manager.js +1154 -0
  83. package/backend/dist/extensions/manager.js.map +1 -0
  84. package/backend/dist/lib/catalog.js +30 -0
  85. package/backend/dist/lib/catalog.js.map +1 -0
  86. package/backend/dist/lib/context.js +59 -0
  87. package/backend/dist/lib/context.js.map +1 -0
  88. package/backend/dist/lib/errors.js +75 -0
  89. package/backend/dist/lib/errors.js.map +1 -0
  90. package/backend/dist/lib/provider-store.js +116 -0
  91. package/backend/dist/lib/provider-store.js.map +1 -0
  92. package/backend/dist/lib/redact.js +11 -0
  93. package/backend/dist/lib/redact.js.map +1 -0
  94. package/backend/dist/lib/runtime-store.js +28 -0
  95. package/backend/dist/lib/runtime-store.js.map +1 -0
  96. package/backend/dist/lib/sqlite-store.js +218 -0
  97. package/backend/dist/lib/sqlite-store.js.map +1 -0
  98. package/backend/dist/lib/sse.js +46 -0
  99. package/backend/dist/lib/sse.js.map +1 -0
  100. package/backend/dist/lib/ssrf.js +131 -0
  101. package/backend/dist/lib/ssrf.js.map +1 -0
  102. package/backend/dist/lib/store.js +84 -0
  103. package/backend/dist/lib/store.js.map +1 -0
  104. package/backend/dist/lib/usage.js +219 -0
  105. package/backend/dist/lib/usage.js.map +1 -0
  106. package/backend/dist/lib/util.js +38 -0
  107. package/backend/dist/lib/util.js.map +1 -0
  108. package/backend/dist/lib/workspace-store.js +152 -0
  109. package/backend/dist/lib/workspace-store.js.map +1 -0
  110. package/backend/dist/mcp.js +429 -0
  111. package/backend/dist/mcp.js.map +1 -0
  112. package/backend/dist/routes/agents.js +51 -0
  113. package/backend/dist/routes/agents.js.map +1 -0
  114. package/backend/dist/routes/assistants.js +32 -0
  115. package/backend/dist/routes/assistants.js.map +1 -0
  116. package/backend/dist/routes/chat.js +697 -0
  117. package/backend/dist/routes/chat.js.map +1 -0
  118. package/backend/dist/routes/control-plane.js +200 -0
  119. package/backend/dist/routes/control-plane.js.map +1 -0
  120. package/backend/dist/routes/conversations.js +66 -0
  121. package/backend/dist/routes/conversations.js.map +1 -0
  122. package/backend/dist/routes/extensions-import.js +22 -0
  123. package/backend/dist/routes/extensions-import.js.map +1 -0
  124. package/backend/dist/routes/import.js +85 -0
  125. package/backend/dist/routes/import.js.map +1 -0
  126. package/backend/dist/routes/mcp-servers.js +56 -0
  127. package/backend/dist/routes/mcp-servers.js.map +1 -0
  128. package/backend/dist/routes/meta.js +37 -0
  129. package/backend/dist/routes/meta.js.map +1 -0
  130. package/backend/dist/routes/mock.js +28 -0
  131. package/backend/dist/routes/mock.js.map +1 -0
  132. package/backend/dist/routes/plugins.js +41 -0
  133. package/backend/dist/routes/plugins.js.map +1 -0
  134. package/backend/dist/routes/providers.js +197 -0
  135. package/backend/dist/routes/providers.js.map +1 -0
  136. package/backend/dist/routes/runs.js +57 -0
  137. package/backend/dist/routes/runs.js.map +1 -0
  138. package/backend/dist/routes/skills.js +73 -0
  139. package/backend/dist/routes/skills.js.map +1 -0
  140. package/backend/dist/routes/tools.js +40 -0
  141. package/backend/dist/routes/tools.js.map +1 -0
  142. package/backend/dist/routes/usage.js +14 -0
  143. package/backend/dist/routes/usage.js.map +1 -0
  144. package/backend/dist/routes/workspaces.js +158 -0
  145. package/backend/dist/routes/workspaces.js.map +1 -0
  146. package/backend/dist/runtime/agent.js +518 -0
  147. package/backend/dist/runtime/agent.js.map +1 -0
  148. package/backend/dist/server.js +103 -0
  149. package/backend/dist/server.js.map +1 -0
  150. package/backend/dist/types.js +3 -0
  151. package/backend/dist/types.js.map +1 -0
  152. package/backend/extensions/demo-mcp-server.js +70 -0
  153. package/backend/extensions/importer.ts +709 -0
  154. package/backend/extensions/manager.ts +1055 -0
  155. package/backend/lib/catalog.ts +28 -0
  156. package/backend/lib/context.ts +61 -0
  157. package/backend/lib/errors.ts +78 -0
  158. package/backend/lib/provider-store.ts +116 -0
  159. package/backend/lib/redact.ts +9 -0
  160. package/backend/lib/runtime-store.ts +38 -0
  161. package/backend/lib/sqlite-store.ts +220 -0
  162. package/backend/lib/sse.ts +42 -0
  163. package/backend/lib/ssrf.ts +120 -0
  164. package/backend/lib/store.ts +79 -0
  165. package/backend/lib/usage.ts +212 -0
  166. package/backend/lib/util.ts +31 -0
  167. package/backend/lib/workspace-store.ts +150 -0
  168. package/backend/mcp.ts +417 -0
  169. package/backend/package.json +34 -0
  170. package/backend/prompts.json +82 -0
  171. package/backend/routes/agents.ts +55 -0
  172. package/backend/routes/assistants.ts +30 -0
  173. package/backend/routes/chat.ts +660 -0
  174. package/backend/routes/control-plane.ts +165 -0
  175. package/backend/routes/conversations.ts +62 -0
  176. package/backend/routes/extensions-import.ts +15 -0
  177. package/backend/routes/import.ts +72 -0
  178. package/backend/routes/mcp-servers.ts +36 -0
  179. package/backend/routes/meta.ts +38 -0
  180. package/backend/routes/mock.ts +25 -0
  181. package/backend/routes/plugins.ts +27 -0
  182. package/backend/routes/providers.ts +166 -0
  183. package/backend/routes/runs.ts +55 -0
  184. package/backend/routes/skills.ts +52 -0
  185. package/backend/routes/tools.ts +40 -0
  186. package/backend/routes/usage.ts +13 -0
  187. package/backend/routes/workspaces.ts +124 -0
  188. package/backend/runtime/agent.ts +474 -0
  189. package/backend/server.ts +106 -0
  190. package/backend/types.ts +126 -0
  191. package/bin/multichat.mjs +535 -0
  192. package/frontend/dist/assets/agentPicker-C39VzmYa.js +13 -0
  193. package/frontend/dist/assets/compare-BpaGD32J.js +1 -0
  194. package/frontend/dist/assets/conversations-COuLmg99.js +7 -0
  195. package/frontend/dist/assets/data-ZH7Dux1K.js +1 -0
  196. package/frontend/dist/assets/extensionImport-CnTWKtWm.js +28 -0
  197. package/frontend/dist/assets/importExport-B3mB-9zs.js +70 -0
  198. package/frontend/dist/assets/index-CASVCOUO.js +34 -0
  199. package/frontend/dist/assets/index-DSvbjNLc.css +1 -0
  200. package/frontend/dist/assets/init-ZPK483vB.js +1 -0
  201. package/frontend/dist/assets/jsx-runtime-ZSsbr0oW.js +9 -0
  202. package/frontend/dist/assets/modal-CgHocv3n.js +2 -0
  203. package/frontend/dist/assets/modelPicker-EUmmVnbj.js +14 -0
  204. package/frontend/dist/assets/pluginsUI-B6jGUQkx.js +16 -0
  205. package/frontend/dist/assets/render-DgAg1K8A.js +1 -0
  206. package/frontend/dist/assets/send-BJhZ_5YA.js +14 -0
  207. package/frontend/dist/assets/settings-DdnYwZl-.js +2 -0
  208. package/frontend/dist/assets/shell-DFV2khQl.js +1 -0
  209. package/frontend/dist/assets/workbench-BY2J4vWC.js +41 -0
  210. package/frontend/dist/icon-maskable.svg +4 -0
  211. package/frontend/dist/icon.svg +4 -0
  212. package/frontend/dist/index.html +21 -0
  213. package/frontend/dist/manifest.webmanifest +26 -0
  214. package/package.json +58 -0
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "multichat-project",
3
+ "interface": {
4
+ "displayName": "MultiChat 项目插件"
5
+ },
6
+ "plugins": [
7
+ {
8
+ "name": "writing-toolkit",
9
+ "source": {
10
+ "source": "local",
11
+ "path": "./plugins/writing-toolkit"
12
+ },
13
+ "policy": {
14
+ "installation": "AVAILABLE",
15
+ "authentication": "ON_INSTALL"
16
+ },
17
+ "category": "Writing"
18
+ },
19
+ {
20
+ "name": "developer-toolkit",
21
+ "source": {
22
+ "source": "local",
23
+ "path": "./plugins/developer-toolkit"
24
+ },
25
+ "policy": {
26
+ "installation": "AVAILABLE",
27
+ "authentication": "ON_INSTALL"
28
+ },
29
+ "category": "Developer Tools"
30
+ }
31
+ ]
32
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "developer-toolkit",
3
+ "version": "1.0.0",
4
+ "description": "代码审查、测试设计、安全审查和发布说明工作流。",
5
+ "author": {
6
+ "name": "MultiChat"
7
+ },
8
+ "license": "MIT",
9
+ "keywords": ["development", "review", "testing", "security"],
10
+ "skills": "./skills/",
11
+ "interface": {
12
+ "displayName": "开发者工具包",
13
+ "shortDescription": "审查、测试、安全与发布工作流",
14
+ "longDescription": "为日常研发提供可复用的结构化工作流,并保持 Skill 与工具调用边界清晰。",
15
+ "developerName": "MultiChat",
16
+ "category": "Developer Tools",
17
+ "capabilities": ["Read", "Write"],
18
+ "defaultPrompt": [
19
+ "审查当前改动并按严重程度列出问题。",
20
+ "为这个接口设计覆盖边界条件的测试方案。",
21
+ "根据这些变更生成用户可读的发布说明。"
22
+ ]
23
+ }
24
+ }
@@ -0,0 +1,9 @@
1
+ ---
2
+ name: code-review
3
+ metadata: {"multichat-id":"sk_dev_code_review"}
4
+ description: 审查代码或 diff 的正确性、安全性、性能和可维护性;用户要求 code review、回归检查或合并前审查时使用。
5
+ ---
6
+
7
+ 先理解变更目标和受影响路径,再报告有具体证据、会影响行为的问题。按严重程度排序,每项给出位置、触发条件、影响和最小修复建议。
8
+
9
+ 优先发现数据损坏、安全事故、错误结果和兼容性回归。不要用纯风格偏好充数;若未发现问题,说明已检查的边界和仍缺少的验证证据。
@@ -0,0 +1,3 @@
1
+ interface:
2
+ display_name: "代码审查"
3
+ short_description: "发现有证据的正确性与安全问题"
@@ -0,0 +1,9 @@
1
+ ---
2
+ name: release-notes
3
+ metadata: {"multichat-id":"sk_dev_release_notes"}
4
+ description: 将提交记录、PR 或变更摘要整理为用户可读的发布说明;用户要求 changelog、版本说明或升级提示时使用。
5
+ ---
6
+
7
+ 从变更中提取用户可感知的新增、改进、修复、兼容性变化和升级注意事项。删除内部实现噪音,不扩大变更范围,不编造未验证功能。
8
+
9
+ 用清晰短句按类别组织。若存在破坏性变更,优先说明受影响用户、迁移步骤和回滚条件;没有相关内容的类别不要强行保留。
@@ -0,0 +1,3 @@
1
+ interface:
2
+ display_name: "发布说明"
3
+ short_description: "把技术变更整理为用户可读说明"
@@ -0,0 +1,9 @@
1
+ ---
2
+ name: security-review
3
+ metadata: {"multichat-id":"sk_dev_security"}
4
+ description: 审查应用代码、接口和配置中的可利用安全风险;用户明确要求安全检查、威胁分析或敏感信息排查时使用。
5
+ ---
6
+
7
+ 围绕信任边界和数据流检查注入、越权、SSRF、任意文件访问、命令执行、凭证泄露和资源耗尽。只报告能从现有代码或配置得到证据的问题。
8
+
9
+ 每项发现包含严重度、证据位置、攻击前提、影响、最小修复和验证方法。将尚未证实的风险明确标为假设,不提供越界的攻击执行步骤。
@@ -0,0 +1,3 @@
1
+ interface:
2
+ display_name: "安全审查"
3
+ short_description: "基于证据检查应用安全风险"
@@ -0,0 +1,9 @@
1
+ ---
2
+ name: test-plan
3
+ metadata: {"multichat-id":"sk_dev_test_plan"}
4
+ description: 为接口、功能或用户流程设计可执行测试方案;用户要求测试用例、回归范围或验收矩阵时使用。
5
+ ---
6
+
7
+ 根据需求或契约识别状态、边界和失败路径。覆盖成功、参数校验、权限、重复提交、并发、超时、重试和数据一致性中与当前变更有关的部分。
8
+
9
+ 每个用例写明优先级、前置条件、操作步骤和可观察的预期结果。区分自动化测试与人工验证;信息不足时列出阻塞假设。
@@ -0,0 +1,3 @@
1
+ interface:
2
+ display_name: "测试方案"
3
+ short_description: "生成覆盖边界与失败路径的测试矩阵"
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "writing-toolkit",
3
+ "version": "1.0.0",
4
+ "description": "可复用的中文周报、会议纪要和简历优化工作流。",
5
+ "author": {
6
+ "name": "MultiChat"
7
+ },
8
+ "license": "MIT",
9
+ "keywords": ["writing", "meeting", "resume"],
10
+ "skills": "./skills/",
11
+ "interface": {
12
+ "displayName": "写作工具包",
13
+ "shortDescription": "周报、会议纪要与简历优化工作流",
14
+ "longDescription": "把常用中文写作流程作为标准 Agent Skills 提供,按用户目标自动加载完整指令。",
15
+ "developerName": "MultiChat",
16
+ "category": "Writing",
17
+ "capabilities": ["Write"],
18
+ "defaultPrompt": [
19
+ "根据这些工作要点整理本周周报。",
20
+ "把这段会议记录整理为决议和待办。",
21
+ "在不虚构经历的前提下优化这份简历。"
22
+ ]
23
+ }
24
+ }
@@ -0,0 +1,9 @@
1
+ ---
2
+ name: meeting-notes
3
+ metadata: {"multichat-id":"sk_meeting_notes"}
4
+ description: 将会议录音转写、聊天记录或零散笔记整理为会议纪要;用户要求提炼决议、待办和负责人时使用。
5
+ ---
6
+
7
+ 区分事实、讨论意见、正式决议和待办事项。不要把提议写成已通过决议,也不要猜测缺失的负责人或截止时间。
8
+
9
+ 输出会议主题、参与人(仅在输入出现时)、关键讨论、决议事项、待办清单。待办用“事项 / 负责人 / 截止时间”表示,缺失字段标为“待确认”。
@@ -0,0 +1,3 @@
1
+ interface:
2
+ display_name: "会议纪要"
3
+ short_description: "提炼讨论、决议与待办"
@@ -0,0 +1,9 @@
1
+ ---
2
+ name: resume-tune
3
+ metadata: {"multichat-id":"sk_resume_tune"}
4
+ description: 优化中文或英文简历的经历表述;用户要求润色简历、突出成果或匹配岗位时使用,禁止虚构经历和数据。
5
+ ---
6
+
7
+ 保留原始事实、技术栈、职责范围和时间信息。优先用强动词开头,突出行动、范围和结果;没有量化数据时提出可补充项,不要替用户编造数字。
8
+
9
+ 先给出可直接替换的简历条目,再列出需要确认或补充的数据。若用户提供岗位描述,说明每项修改如何贴合岗位要求,但不要伪造关键词或经验。
@@ -0,0 +1,3 @@
1
+ interface:
2
+ display_name: "简历优化"
3
+ short_description: "强化成果表达且不虚构经历"
@@ -0,0 +1,9 @@
1
+ ---
2
+ name: weekly-report
3
+ metadata: {"multichat-id":"sk_weekly_report"}
4
+ description: 将零散工作要点整理为结构化中文周报;用户要求写周报、复盘本周工作或规划下周时使用。
5
+ ---
6
+
7
+ 先从输入中提取已完成、进行中、风险阻塞和下周计划。未提供的信息不要补写;负责人、日期和数字必须忠于原文。
8
+
9
+ 输出依次包含:本周完成、进行中、风险与阻塞、下周计划。使用简洁项目符号,合并重复事项,并把需要用户补充的信息明确标为“待补充”。
@@ -0,0 +1,3 @@
1
+ interface:
2
+ display_name: "周报生成"
3
+ short_description: "把工作要点整理为结构化周报"
@@ -0,0 +1 @@
1
+
@@ -0,0 +1,172 @@
1
+ ---
2
+ name: wanghong-handwritten-ppt
3
+ description: 将文章、讲稿或技术主题制作成王虹学术报告气质的 16:9 Notability 手写风 HTML 幻灯片,并逐页导出 PNG。触发词:王虹PPT风格、王虹手写PPT、Notability学术手写幻灯片、手写网页PPT、手写PPT、数学家手写报告风。
4
+ ---
5
+
6
+ # 王虹学术手写风 HTML 幻灯片
7
+
8
+ 把内容做成一套安静、工整、逻辑清楚、信息密度高的手写学术报告。视觉上接近 Notability 数字手写页,内容上强调一页一个问题和连续推导。
9
+
10
+ ## 适用场景
11
+
12
+ - 技术文章转演示文稿
13
+ - 论文、模型、工具或产品的原理讲解
14
+ - 需要 16:9 HTML 幻灯片和逐页 PNG 的任务
15
+ - 希望保留手写温度,同时要求中文清楚可读的报告
16
+
17
+ ## 先读材料
18
+
19
+ 1. 读取用户提供的文章、讲稿、数据和参考图。
20
+ 2. 需要复用完整视觉规范或提示词时,读取 `references/style-guide.md`。
21
+ 3. 需要查看成品结构时,打开 `examples/deepseek-v4-flash/index.html`。
22
+ 4. 需要快速开工时,从 `templates/deck.html` 复制一份新文件。
23
+
24
+ ## 完成标准
25
+
26
+ - 固定 16:9,浏览器中无滚动条和内容溢出。
27
+ - 封面保持极简,下半页至少留出一半空白。
28
+ - 正文每页回答一个清楚的问题,整套报告形成连续逻辑链。
29
+ - 字号、颜色和手绘线条统一,中文投影可读。
30
+ - 重要数字和结论同时出现在正文,手写标注只承担视觉提示。
31
+ - 支持左右键、空格翻页和全屏。
32
+ - 每页都有简短讲稿备注。
33
+ - 输出 HTML、全部 PNG 和一张总览图,并实际打开检查。
34
+
35
+ ## 工作流程
36
+
37
+ ### 1. 整理故事线
38
+
39
+ 先从原文提取:
40
+
41
+ - 报告要回答的总问题
42
+ - 观众需要先知道的背景
43
+ - 3 到 6 个核心判断
44
+ - 支撑判断的数据、对比、流程和例子
45
+ - 最后希望观众记住的一句话
46
+
47
+ 把内容拆成 12 到 24 页。推荐顺序:封面 → 变化发生了什么 → 为什么重要 → 证据与推导 → 怎么做 → 陷阱 → 结论。
48
+
49
+ 不要把文章段落直接塞进页面。每页只留 3 到 6 行关键文字,复杂信息转换成图、表、坐标轴或公式。
50
+
51
+ ### 2. 选择页面类型
52
+
53
+ 优先使用这些版式:
54
+
55
+ - 极简封面:单行标题、细横线、作者/场合/日期、大片留白
56
+ - 左文右图:三到五行解释配一个手绘示意图
57
+ - 流程页:三个框和箭头,最重要的一步用荧光色
58
+ - 坐标页:用两个轴解释成本、质量、速度或规模
59
+ - 对比页:两列、三列或一张紧凑表格
60
+ - 结论页:公式式收束,底部一条玫红结论框
61
+ - 结束页:一句感谢和署名,保持安静
62
+
63
+ ### 3. 使用固定视觉语言
64
+
65
+ - 背景:淡暖白,接近干净的数字纸张
66
+ - 主文字:深蓝黑
67
+ - 蓝色:标题下划线、坐标轴、推导主线
68
+ - 玫红:结论、警告、推荐框
69
+ - 绿色:成立条件、确认项、推荐档
70
+ - 荧光黄:极少量关键词
71
+ - 珊瑚粉:例外、损失或剩余部分
72
+
73
+ 字体固定使用 `HanziPen SC`,与 `assets/preview-cover.png` 里的字形保持一致。不设置其他中文字体候选。渲染环境缺少该字体时先安装,不得带着替代字形交付。
74
+
75
+ 避免圆角卡片、阴影、渐变、装饰图标、商业模板、照片背景和大面积色块。
76
+
77
+ ### 4. 使用 neat-annotations
78
+
79
+ 项目已在 `assets/neat-annotations.css` 中本地保存。它用手写箭头把短注释指向目标词,支持八个方向、颜色和自定义颜色。
80
+
81
+ 中文可以直接写入 `data-note`。同时在页面样式里覆盖:
82
+
83
+ ```css
84
+ :root {
85
+ --ann-font: "HanziPen SC";
86
+ --ann-label-max-width: 220px;
87
+ }
88
+ ```
89
+
90
+ 使用示例:
91
+
92
+ ```html
93
+ <span class="ann ann-n ann-green" data-note="甜点档">Q4_K_XL</span>
94
+ ```
95
+
96
+ 标注采用绝对定位。给箭头和文字预留空间,避免贴近页面边缘或相互遮挡。长中文结论仍写在正文中。
97
+
98
+ ### 5. 制作 HTML
99
+
100
+ 从 `templates/deck.html` 开始,保留这些本地资源:
101
+
102
+ ```html
103
+ <link rel="stylesheet" href="../assets/base.css">
104
+ <link rel="stylesheet" href="../assets/animations.css">
105
+ <link rel="stylesheet" href="../assets/neat-annotations.css">
106
+ <link rel="stylesheet" href="../assets/template.css">
107
+ <script src="../assets/runtime.js"></script>
108
+ ```
109
+
110
+ 每页使用:
111
+
112
+ ```html
113
+ <section class="slide" data-title="页面名称">
114
+ <h2 class="slide-title">这一页回答的问题</h2>
115
+ <!-- 页面内容 -->
116
+ <aside class="notes">演讲时补充的一到三句话。</aside>
117
+ </section>
118
+ ```
119
+
120
+ 图表优先用 SVG 手绘。线条使用 `stroke-linecap="round"`,适当叠加轻微位移滤镜,让直线保留手画感。
121
+
122
+ ### 6. 检查与导出
123
+
124
+ 先检查结构:
125
+
126
+ ```bash
127
+ python3 scripts/check_deck.py /absolute/path/to/index.html
128
+ ```
129
+
130
+ 再逐页导出:
131
+
132
+ ```bash
133
+ scripts/render.sh \
134
+ /absolute/path/to/index.html \
135
+ all \
136
+ /absolute/path/to/png-output \
137
+ /absolute/path/to/Hanzipen.ttc
138
+ ```
139
+
140
+ macOS 上可先在字体册下载“翩翩体-简”。脚本会把指定字体文件直接注入临时渲染页,并在导出前确认字体加载成功。缺少该字体或加载失败时停止导出。
141
+
142
+ 实际查看所有 PNG。重点检查:
143
+
144
+ - 中文是否清楚
145
+ - 标注是否遮挡正文
146
+ - 表格是否过密
147
+ - 代码和公式是否超出边界
148
+ - 结论框是否压住内容
149
+ - 每页是否仍然只讲一个问题
150
+
151
+ 发现问题后修改 HTML,再重新导出。交付前至少完成一次浏览器翻页测试和一次全页总览检查。
152
+
153
+ ## 输出目录建议
154
+
155
+ ```text
156
+ output/<主题>-handwritten-ppt/
157
+ index.html
158
+ style.css
159
+ assets/
160
+ png/
161
+ contact-sheet.png
162
+ prompts.md
163
+ ```
164
+
165
+ ## 随附内容
166
+
167
+ - `templates/deck.html`:可直接改写的基础模板
168
+ - `assets/template.css`:通用手写风样式
169
+ - `examples/deepseek-v4-flash/`:19 页完整示例
170
+ - `references/style-guide.md`:风格拆解、GPT Image 提示词和 HTML 提示词
171
+ - `scripts/check_deck.py`:结构检查
172
+ - `scripts/render.sh`:逐页 PNG 导出
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 lewis <sudolewis@gmail.com>
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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Maxim Syabro
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.
@@ -0,0 +1,138 @@
1
+ /* html-ppt :: animations.css
2
+ * Apply by adding class="anim-<name>" or data-anim="<name>".
3
+ * Durations are deliberately snappy; tweak --anim-dur per element.
4
+ */
5
+ :root{--anim-dur:.7s;--anim-ease:cubic-bezier(.4,0,.2,1)}
6
+
7
+ /* ---------- FADE DIRECTIONALS ---------- */
8
+ @keyframes kf-fade-up{from{opacity:0;transform:translateY(32px)}to{opacity:1;transform:none}}
9
+ @keyframes kf-fade-down{from{opacity:0;transform:translateY(-32px)}to{opacity:1;transform:none}}
10
+ @keyframes kf-fade-left{from{opacity:0;transform:translateX(-40px)}to{opacity:1;transform:none}}
11
+ @keyframes kf-fade-right{from{opacity:0;transform:translateX(40px)}to{opacity:1;transform:none}}
12
+ .anim-fade-up{animation:kf-fade-up var(--anim-dur) var(--anim-ease) both}
13
+ .anim-fade-down{animation:kf-fade-down var(--anim-dur) var(--anim-ease) both}
14
+ .anim-fade-left{animation:kf-fade-left var(--anim-dur) var(--anim-ease) both}
15
+ .anim-fade-right{animation:kf-fade-right var(--anim-dur) var(--anim-ease) both}
16
+
17
+ /* ---------- RISE / DROP / ZOOM / BLUR / GLITCH ---------- */
18
+ @keyframes kf-rise{from{opacity:0;transform:translateY(60px) scale(.97);filter:blur(6px)}to{opacity:1;transform:none;filter:none}}
19
+ @keyframes kf-drop{from{opacity:0;transform:translateY(-60px) scale(.97)}to{opacity:1;transform:none}}
20
+ @keyframes kf-zoom{0%{opacity:0;transform:scale(.6)}60%{transform:scale(1.04)}100%{opacity:1;transform:scale(1)}}
21
+ @keyframes kf-blur{from{opacity:0;filter:blur(18px)}to{opacity:1;filter:none}}
22
+ @keyframes kf-glitch{0%{opacity:0;transform:translateX(0);clip-path:inset(0 0 0 0)}
23
+ 20%{opacity:1;transform:translateX(-6px);clip-path:inset(20% 0 30% 0)}
24
+ 40%{transform:translateX(4px);clip-path:inset(50% 0 10% 0)}
25
+ 60%{transform:translateX(-3px);clip-path:inset(10% 0 60% 0)}
26
+ 80%{transform:translateX(2px);clip-path:inset(0 0 0 0)}
27
+ 100%{opacity:1;transform:none}}
28
+ .anim-rise-in{animation:kf-rise .9s var(--anim-ease) both}
29
+ .anim-drop-in{animation:kf-drop .8s var(--anim-ease) both}
30
+ .anim-zoom-pop{animation:kf-zoom .7s cubic-bezier(.22,1.3,.36,1) both}
31
+ .anim-blur-in{animation:kf-blur .8s var(--anim-ease) both}
32
+ .anim-glitch-in{animation:kf-glitch .8s steps(5,end) both}
33
+
34
+ /* ---------- TYPEWRITER ---------- */
35
+ .anim-typewriter{display:inline-block;overflow:hidden;white-space:nowrap;border-right:2px solid currentColor;
36
+ width:0;animation:kf-type 2.4s steps(40,end) forwards, kf-caret 1s step-end infinite}
37
+ @keyframes kf-type{to{width:100%}}
38
+ @keyframes kf-caret{50%{border-color:transparent}}
39
+
40
+ /* ---------- GLOW / SHIMMER / GRADIENT-FLOW ---------- */
41
+ @keyframes kf-neon{0%,100%{text-shadow:0 0 8px var(--accent),0 0 20px var(--accent)}
42
+ 50%{text-shadow:0 0 16px var(--accent),0 0 40px var(--accent),0 0 80px var(--accent)}}
43
+ .anim-neon-glow{animation:kf-neon 2s ease-in-out infinite}
44
+
45
+ .anim-shimmer-sweep{position:relative;overflow:hidden}
46
+ .anim-shimmer-sweep::after{content:"";position:absolute;inset:0;
47
+ background:linear-gradient(110deg,transparent 40%,rgba(255,255,255,.55) 50%,transparent 60%);
48
+ transform:translateX(-100%);animation:kf-shimmer 2.4s var(--anim-ease) infinite}
49
+ @keyframes kf-shimmer{to{transform:translateX(100%)}}
50
+
51
+ .anim-gradient-flow{background:linear-gradient(90deg,var(--accent),var(--accent-2,var(--accent)),var(--accent-3,var(--accent)),var(--accent));
52
+ background-size:300% 100%;-webkit-background-clip:text;background-clip:text;color:transparent;-webkit-text-fill-color:transparent;
53
+ animation:kf-gradflow 4s linear infinite}
54
+ @keyframes kf-gradflow{to{background-position:300% 0}}
55
+
56
+ /* ---------- STAGGER LIST ---------- */
57
+ .anim-stagger-list > *{opacity:0;animation:kf-rise .65s var(--anim-ease) both}
58
+ .anim-stagger-list > *:nth-child(1){animation-delay:.05s}
59
+ .anim-stagger-list > *:nth-child(2){animation-delay:.15s}
60
+ .anim-stagger-list > *:nth-child(3){animation-delay:.25s}
61
+ .anim-stagger-list > *:nth-child(4){animation-delay:.35s}
62
+ .anim-stagger-list > *:nth-child(5){animation-delay:.45s}
63
+ .anim-stagger-list > *:nth-child(6){animation-delay:.55s}
64
+ .anim-stagger-list > *:nth-child(7){animation-delay:.65s}
65
+ .anim-stagger-list > *:nth-child(8){animation-delay:.75s}
66
+ .anim-stagger-list > *:nth-child(n+9){animation-delay:.85s}
67
+
68
+ /* ---------- COUNTER-UP (JS-driven, marker class only) ---------- */
69
+ .counter{font-variant-numeric:tabular-nums}
70
+
71
+ /* ---------- SVG PATH DRAW ---------- */
72
+ .anim-path-draw path,.anim-path-draw line,.anim-path-draw polyline,.anim-path-draw circle,.anim-path-draw rect{
73
+ stroke-dasharray:1000;stroke-dashoffset:1000;animation:kf-draw 2s var(--anim-ease) forwards}
74
+ @keyframes kf-draw{to{stroke-dashoffset:0}}
75
+
76
+ /* ---------- PARALLAX TILT (hover) ---------- */
77
+ .anim-parallax-tilt{transform-style:preserve-3d;transition:transform .4s var(--anim-ease)}
78
+ .anim-parallax-tilt:hover{transform:perspective(900px) rotateX(6deg) rotateY(-8deg) translateZ(10px)}
79
+
80
+ /* ---------- CARD FLIP 3D ---------- */
81
+ @keyframes kf-flip{from{transform:perspective(1200px) rotateY(-90deg);opacity:0}
82
+ to{transform:perspective(1200px) rotateY(0);opacity:1}}
83
+ .anim-card-flip-3d{animation:kf-flip .9s var(--anim-ease) both;transform-style:preserve-3d;backface-visibility:hidden}
84
+
85
+ /* ---------- CUBE ROTATE 3D ---------- */
86
+ @keyframes kf-cube{from{transform:perspective(1200px) rotateX(20deg) rotateY(-90deg) translateZ(-200px);opacity:0}
87
+ to{transform:perspective(1200px) rotateX(0) rotateY(0) translateZ(0);opacity:1}}
88
+ .anim-cube-rotate-3d{animation:kf-cube 1s var(--anim-ease) both}
89
+
90
+ /* ---------- PAGE TURN 3D ---------- */
91
+ @keyframes kf-pageturn{from{transform:perspective(1600px) rotateY(-85deg);transform-origin:left center;opacity:0}
92
+ to{transform:perspective(1600px) rotateY(0);opacity:1}}
93
+ .anim-page-turn-3d{animation:kf-pageturn 1s var(--anim-ease) both;transform-origin:left center}
94
+
95
+ /* ---------- PERSPECTIVE ZOOM ---------- */
96
+ @keyframes kf-pzoom{from{opacity:0;transform:perspective(1400px) translateZ(-400px) rotateX(12deg)}
97
+ to{opacity:1;transform:none}}
98
+ .anim-perspective-zoom{animation:kf-pzoom 1s var(--anim-ease) both}
99
+
100
+ /* ---------- MARQUEE SCROLL ---------- */
101
+ .anim-marquee-scroll{display:flex;gap:48px;white-space:nowrap;animation:kf-marquee 20s linear infinite}
102
+ @keyframes kf-marquee{from{transform:translateX(0)}to{transform:translateX(-50%)}}
103
+
104
+ /* ---------- KEN BURNS ---------- */
105
+ @keyframes kf-kenburns{0%{transform:scale(1) translate(0,0)}100%{transform:scale(1.15) translate(-2%,-1%)}}
106
+ .anim-kenburns{animation:kf-kenburns 14s ease-in-out infinite alternate}
107
+
108
+ /* ---------- CONFETTI BURST (pseudo — pure CSS sparkles) ---------- */
109
+ .anim-confetti-burst{position:relative}
110
+ .anim-confetti-burst::before,.anim-confetti-burst::after{
111
+ content:"";position:absolute;top:50%;left:50%;width:8px;height:8px;border-radius:50%;
112
+ background:var(--accent);box-shadow:
113
+ 20px -30px 0 var(--accent-2,var(--accent)),-25px -20px 0 var(--accent-3,var(--accent)),
114
+ 30px 20px 0 var(--good,#1aaf6c),-30px 25px 0 var(--warn,#f5a524),
115
+ 40px -10px 0 var(--bad,#e0445a),-45px 0 0 var(--accent),
116
+ 10px 40px 0 var(--accent-2,var(--accent)),-15px -40px 0 var(--accent-3,var(--accent));
117
+ opacity:0;animation:kf-confetti 1.2s var(--anim-ease) forwards}
118
+ .anim-confetti-burst::after{animation-delay:.15s;transform:rotate(45deg)}
119
+ @keyframes kf-confetti{0%{opacity:0;transform:scale(.2)}30%{opacity:1}100%{opacity:0;transform:scale(2.2)}}
120
+
121
+ /* ---------- SPOTLIGHT ---------- */
122
+ @keyframes kf-spot{0%{clip-path:circle(0% at 50% 50%)}100%{clip-path:circle(140% at 50% 50%)}}
123
+ .anim-spotlight{animation:kf-spot 1.1s var(--anim-ease) both}
124
+
125
+ /* ---------- MORPH SHAPE (SVG) ---------- */
126
+ .anim-morph-shape path{animation:kf-morph 6s ease-in-out infinite alternate}
127
+ @keyframes kf-morph{0%{d:path("M60,120 Q120,20 180,120 T300,120")}
128
+ 100%{d:path("M60,120 Q120,220 180,120 T300,120")}}
129
+
130
+ /* ---------- RIPPLE REVEAL ---------- */
131
+ @keyframes kf-ripple{0%{clip-path:circle(0% at 20% 80%);opacity:.4}
132
+ 100%{clip-path:circle(160% at 20% 80%);opacity:1}}
133
+ .anim-ripple-reveal{animation:kf-ripple 1.2s var(--anim-ease) both}
134
+
135
+ /* reduced motion */
136
+ @media (prefers-reduced-motion: reduce){
137
+ [class*="anim-"]{animation:none!important;transition:none!important}
138
+ }