cotutor 0.1.0 → 0.3.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 (845) hide show
  1. package/LICENSE +247 -21
  2. package/NOTICE +42 -0
  3. package/README.md +107 -24
  4. package/bin/cotutor.js +4 -4
  5. package/cards/canvas/card.css +8 -0
  6. package/cards/canvas/card.md +68 -0
  7. package/cards/choice/card.css +18 -0
  8. package/cards/choice/card.md +55 -0
  9. package/cards/code/card.css +5 -0
  10. package/cards/code/card.md +46 -0
  11. package/cards/dictation/card.css +10 -0
  12. package/cards/dictation/card.md +97 -0
  13. package/cards/image/card.css +10 -0
  14. package/cards/image/card.md +52 -0
  15. package/cards/lecture/card.css +9 -0
  16. package/cards/lecture/card.md +69 -0
  17. package/cards/paint/card.css +20 -0
  18. package/cards/paint/card.md +77 -0
  19. package/cards/photo/card.css +15 -0
  20. package/cards/photo/card.md +61 -0
  21. package/cards/read/card.css +6 -0
  22. package/cards/read/card.md +51 -0
  23. package/cards/text/card.css +3 -0
  24. package/cards/text/card.md +69 -0
  25. package/cards/tianzige/card.css +17 -0
  26. package/cards/tianzige/card.md +78 -0
  27. package/cards/tutor/card.css +66 -0
  28. package/cards/tutor/card.md +148 -0
  29. package/cards/word/card.css +24 -0
  30. package/cards/word/card.md +91 -0
  31. package/cards//346/235/277/344/271/246/346/200/216/344/271/210/345/206/231.md +159 -0
  32. package/dist/app/activity-eval-rules.d.ts +62 -0
  33. package/dist/app/activity-eval-rules.js +276 -0
  34. package/dist/app/activity-eval.d.ts +65 -0
  35. package/dist/app/activity-eval.js +158 -0
  36. package/dist/app/build.d.ts +11 -0
  37. package/dist/app/build.js +45 -0
  38. package/dist/app/cli/activities.d.ts +63 -0
  39. package/dist/app/cli/activities.js +158 -0
  40. package/dist/app/cli/cert.d.ts +7 -0
  41. package/dist/app/cli/cert.js +36 -0
  42. package/dist/app/cli/chalk/bake.d.ts +10 -0
  43. package/dist/app/cli/chalk/bake.js +58 -0
  44. package/dist/app/cli/chalk/browser.d.ts +16 -0
  45. package/dist/app/cli/chalk/browser.js +142 -0
  46. package/dist/app/cli/chalk/build.d.ts +14 -0
  47. package/dist/app/cli/chalk/build.js +100 -0
  48. package/dist/app/cli/chalk/dub.d.ts +51 -0
  49. package/dist/app/cli/chalk/dub.js +106 -0
  50. package/dist/app/cli/chalk/load-scene.d.ts +34 -0
  51. package/dist/app/cli/chalk/load-scene.js +117 -0
  52. package/dist/app/cli/chalk/main.d.ts +7 -0
  53. package/dist/app/cli/chalk/main.js +198 -0
  54. package/dist/app/cli/chalk/serve.d.ts +4 -0
  55. package/dist/app/cli/chalk/serve.js +28 -0
  56. package/dist/app/cli/chalk/snap.d.ts +65 -0
  57. package/dist/app/cli/chalk/snap.js +103 -0
  58. package/dist/app/cli/chalk/typecheck.d.ts +7 -0
  59. package/dist/app/cli/chalk/typecheck.js +51 -0
  60. package/dist/app/cli/doctor.d.ts +23 -0
  61. package/dist/app/cli/doctor.js +617 -0
  62. package/dist/app/cli/grades.d.ts +14 -0
  63. package/dist/app/cli/grades.js +44 -0
  64. package/dist/{cli → app/cli}/init.d.ts +3 -1
  65. package/dist/app/cli/init.js +155 -0
  66. package/dist/app/cli/main.js +715 -0
  67. package/dist/app/cli/migrate.d.ts +58 -0
  68. package/dist/app/cli/migrate.js +253 -0
  69. package/dist/app/cli/serve.d.ts +37 -0
  70. package/dist/app/cli/serve.js +98 -0
  71. package/dist/app/cli/shipped.d.ts +30 -0
  72. package/dist/app/cli/shipped.js +47 -0
  73. package/dist/app/cli/skeleton.d.ts +38 -0
  74. package/dist/app/cli/skeleton.js +161 -0
  75. package/dist/app/cli/skills.d.ts +55 -0
  76. package/dist/app/cli/skills.js +189 -0
  77. package/dist/app/cli/themes.d.ts +52 -0
  78. package/dist/app/cli/themes.js +148 -0
  79. package/dist/app/cli/tutors.d.ts +73 -0
  80. package/dist/app/cli/tutors.js +250 -0
  81. package/dist/app/cli/usage.d.ts +2 -0
  82. package/dist/app/cli/usage.js +30 -0
  83. package/dist/app/dictation/recognize.d.ts +18 -0
  84. package/dist/app/dictation/recognize.js +6 -0
  85. package/dist/app/dictation/route.d.ts +52 -0
  86. package/dist/app/dictation/route.js +510 -0
  87. package/dist/app/diff.d.ts +11 -0
  88. package/dist/app/diff.js +71 -0
  89. package/dist/app/http/access.d.ts +62 -0
  90. package/dist/app/http/access.js +180 -0
  91. package/dist/app/http/app.d.ts +246 -0
  92. package/dist/app/http/app.js +1212 -0
  93. package/dist/app/http/dev-activities.d.ts +115 -0
  94. package/dist/app/http/dev-activities.js +193 -0
  95. package/dist/app/http/dev-overview.d.ts +108 -0
  96. package/dist/app/http/dev-overview.js +209 -0
  97. package/dist/app/http/dev-tutor-files.d.ts +80 -0
  98. package/dist/app/http/dev-tutor-files.js +151 -0
  99. package/dist/app/http/parent-home.d.ts +37 -0
  100. package/dist/app/http/parent-home.js +203 -0
  101. package/dist/app/http/range.d.ts +9 -0
  102. package/dist/app/http/range.js +19 -0
  103. package/dist/app/http/raw-view.d.ts +117 -0
  104. package/dist/app/http/raw-view.js +149 -0
  105. package/dist/app/http/send-file.d.ts +7 -0
  106. package/dist/app/http/send-file.js +29 -0
  107. package/dist/app/http/stage.d.ts +24 -0
  108. package/dist/app/http/stage.js +97 -0
  109. package/dist/app/http/theme.d.ts +13 -0
  110. package/dist/app/http/theme.js +41 -0
  111. package/dist/app/machine/bailian.d.ts +28 -0
  112. package/dist/app/machine/bailian.js +88 -0
  113. package/dist/app/mock/mock-live.d.ts +16 -0
  114. package/dist/app/mock/mock-live.js +140 -0
  115. package/dist/app/mock/mock.d.ts +89 -0
  116. package/dist/app/mock/mock.js +1117 -0
  117. package/dist/app/replay.d.ts +94 -0
  118. package/dist/app/replay.js +170 -0
  119. package/dist/app/skills/analyze-doc.d.ts +3 -0
  120. package/dist/app/skills/analyze-doc.js +47 -0
  121. package/dist/app/skills/home-doc.d.ts +5 -0
  122. package/dist/app/skills/home-doc.js +112 -0
  123. package/dist/app/skills/tune-doc.d.ts +3 -0
  124. package/dist/app/skills/tune-doc.js +80 -0
  125. package/dist/app/talk/list.d.ts +11 -0
  126. package/dist/app/talk/list.js +9 -0
  127. package/dist/app/talk/route.d.ts +16 -0
  128. package/dist/app/talk/route.js +142 -0
  129. package/dist/app/workspace.d.ts +58 -0
  130. package/dist/{cli → app}/workspace.js +82 -36
  131. package/dist/app/ws/route.d.ts +25 -0
  132. package/dist/app/ws/route.js +29 -0
  133. package/dist/app/ws/ws.d.ts +31 -0
  134. package/dist/app/ws/ws.js +169 -0
  135. package/dist/board/canvas-chat.d.ts +97 -0
  136. package/dist/board/canvas-chat.js +175 -0
  137. package/dist/board/card-guards.d.ts +15 -0
  138. package/dist/board/card-guards.js +38 -0
  139. package/dist/board/cards/canvas.d.ts +41 -0
  140. package/dist/board/cards/canvas.js +83 -0
  141. package/dist/board/cards/choice.d.ts +20 -0
  142. package/dist/board/cards/choice.js +64 -0
  143. package/dist/board/cards/code.d.ts +9 -0
  144. package/dist/board/cards/code.js +10 -0
  145. package/dist/board/cards/dictation.d.ts +42 -0
  146. package/dist/board/cards/dictation.js +105 -0
  147. package/dist/board/cards/docs.d.ts +47 -0
  148. package/dist/board/cards/docs.js +152 -0
  149. package/dist/board/cards/image.d.ts +13 -0
  150. package/dist/board/cards/image.js +26 -0
  151. package/dist/board/cards/index.d.ts +62 -0
  152. package/dist/board/cards/index.js +144 -0
  153. package/dist/board/cards/kind.d.ts +33 -0
  154. package/dist/board/cards/kind.js +9 -0
  155. package/dist/board/cards/lecture.d.ts +26 -0
  156. package/dist/board/cards/lecture.js +62 -0
  157. package/dist/board/cards/paint.d.ts +38 -0
  158. package/dist/board/cards/paint.js +85 -0
  159. package/dist/board/cards/photo.d.ts +15 -0
  160. package/dist/board/cards/photo.js +29 -0
  161. package/dist/board/cards/read.d.ts +8 -0
  162. package/dist/board/cards/read.js +18 -0
  163. package/dist/board/cards/text.d.ts +20 -0
  164. package/dist/board/cards/text.js +59 -0
  165. package/dist/board/cards/tianzige.d.ts +16 -0
  166. package/dist/board/cards/tianzige.js +64 -0
  167. package/dist/board/cards/tutor.d.ts +72 -0
  168. package/dist/board/cards/tutor.js +134 -0
  169. package/dist/board/cards/word.d.ts +20 -0
  170. package/dist/board/cards/word.js +76 -0
  171. package/dist/board/lecture.d.ts +100 -0
  172. package/dist/board/lecture.js +204 -0
  173. package/dist/board/paper.d.ts +20 -0
  174. package/dist/board/paper.js +76 -0
  175. package/dist/board/parse.d.ts +120 -0
  176. package/dist/board/parse.js +330 -0
  177. package/dist/board/presentation.d.ts +295 -0
  178. package/dist/board/presentation.js +615 -0
  179. package/dist/board/sections.d.ts +16 -0
  180. package/dist/board/sections.js +130 -0
  181. package/dist/brain/api-tools.d.ts +8 -0
  182. package/dist/brain/api-tools.js +190 -0
  183. package/dist/brain/api.d.ts +62 -0
  184. package/dist/brain/api.js +411 -0
  185. package/dist/brain/cli/adapters.d.ts +60 -0
  186. package/dist/brain/cli/adapters.js +91 -0
  187. package/dist/brain/cli/qwen.d.ts +11 -0
  188. package/dist/brain/cli/qwen.js +141 -0
  189. package/dist/brain/cli/run-plan.d.ts +59 -0
  190. package/dist/brain/cli/run-plan.js +71 -0
  191. package/dist/brain/cli/run.d.ts +35 -0
  192. package/dist/brain/cli/run.js +256 -0
  193. package/dist/brain/cli/stream-json.d.ts +18 -0
  194. package/dist/brain/cli/stream-json.js +86 -0
  195. package/dist/brain/cli/types.d.ts +144 -0
  196. package/dist/brain/cli/types.js +3 -0
  197. package/dist/brain/cli/warm.d.ts +53 -0
  198. package/dist/brain/cli/warm.js +103 -0
  199. package/dist/brain/index.d.ts +145 -0
  200. package/dist/brain/index.js +74 -0
  201. package/dist/brain/stream.d.ts +20 -0
  202. package/dist/brain/stream.js +70 -0
  203. package/dist/brain/transcript.d.ts +45 -0
  204. package/dist/brain/transcript.js +132 -0
  205. package/dist/chalk/actions.d.ts +37 -0
  206. package/dist/chalk/actions.js +69 -0
  207. package/dist/chalk/bundle.d.ts +26 -0
  208. package/dist/chalk/bundle.js +69 -0
  209. package/dist/chalk/check.d.ts +28 -0
  210. package/dist/chalk/check.js +291 -0
  211. package/dist/chalk/circle.d.ts +64 -0
  212. package/dist/chalk/circle.js +193 -0
  213. package/dist/chalk/clock.d.ts +84 -0
  214. package/dist/chalk/clock.js +84 -0
  215. package/dist/chalk/geometry.d.ts +44 -0
  216. package/dist/chalk/geometry.js +139 -0
  217. package/dist/chalk/glyphs/capitals.d.ts +12 -0
  218. package/dist/chalk/glyphs/capitals.js +264 -0
  219. package/dist/chalk/glyphs/index.d.ts +21 -0
  220. package/dist/chalk/glyphs/index.js +18 -0
  221. package/dist/chalk/glyphs/letters.d.ts +13 -0
  222. package/dist/chalk/glyphs/letters.js +280 -0
  223. package/dist/chalk/glyphs/metrics.d.ts +33 -0
  224. package/dist/chalk/glyphs/metrics.js +28 -0
  225. package/dist/chalk/glyphs/registry.d.ts +7 -0
  226. package/dist/chalk/glyphs/registry.js +8 -0
  227. package/dist/chalk/glyphs/sample.d.ts +32 -0
  228. package/dist/chalk/glyphs/sample.js +102 -0
  229. package/dist/chalk/glyphs/skeleton.d.ts +64 -0
  230. package/dist/chalk/glyphs/skeleton.js +126 -0
  231. package/dist/chalk/glyphs/types.d.ts +58 -0
  232. package/dist/chalk/glyphs/types.js +17 -0
  233. package/dist/chalk/index.d.ts +23 -0
  234. package/dist/chalk/index.js +15 -0
  235. package/dist/chalk/manifest.d.ts +41 -0
  236. package/dist/chalk/manifest.js +6 -0
  237. package/dist/chalk/paint.d.ts +180 -0
  238. package/dist/chalk/paint.js +210 -0
  239. package/dist/chalk/pointer.d.ts +8 -0
  240. package/dist/chalk/pointer.js +21 -0
  241. package/dist/chalk/prepare.d.ts +11 -0
  242. package/dist/chalk/prepare.js +15 -0
  243. package/dist/chalk/scene-schema.d.ts +199 -0
  244. package/dist/chalk/scene-schema.js +91 -0
  245. package/dist/chalk/seed.d.ts +3 -0
  246. package/dist/chalk/seed.js +10 -0
  247. package/dist/chalk/text-metrics.d.ts +8 -0
  248. package/dist/chalk/text-metrics.js +156 -0
  249. package/dist/chalk/timeline.d.ts +47 -0
  250. package/dist/chalk/timeline.js +84 -0
  251. package/dist/chalk/types.d.ts +150 -0
  252. package/dist/chalk/types.js +8 -0
  253. package/dist/lib/index.d.ts +14 -8
  254. package/dist/lib/index.js +14 -8
  255. package/dist/media/draw.d.ts +23 -0
  256. package/dist/media/draw.js +44 -0
  257. package/dist/media/mp3.d.ts +6 -0
  258. package/dist/media/mp3.js +58 -0
  259. package/dist/media/mp4.d.ts +1 -0
  260. package/dist/media/mp4.js +58 -0
  261. package/dist/media/tts-voices.d.ts +18 -0
  262. package/dist/media/tts-voices.js +606 -0
  263. package/dist/media/tts.d.ts +56 -0
  264. package/dist/media/tts.js +174 -0
  265. package/dist/media/vision.d.ts +25 -0
  266. package/dist/media/vision.js +71 -0
  267. package/dist/memory/commit.d.ts +67 -0
  268. package/dist/memory/commit.js +130 -0
  269. package/dist/memory/context.d.ts +86 -0
  270. package/dist/memory/context.js +97 -0
  271. package/dist/memory/diary.d.ts +84 -0
  272. package/dist/memory/diary.js +183 -0
  273. package/dist/memory/grade.d.ts +2 -0
  274. package/dist/memory/grade.js +7 -0
  275. package/dist/{lib → memory}/plan.d.ts +3 -1
  276. package/dist/{lib → memory}/plan.js +10 -1
  277. package/dist/memory/proposals.d.ts +11 -0
  278. package/dist/memory/proposals.js +43 -0
  279. package/dist/memory/retrieval.d.ts +44 -0
  280. package/dist/memory/retrieval.js +157 -0
  281. package/dist/memory/timetable.d.ts +19 -0
  282. package/dist/memory/timetable.js +95 -0
  283. package/dist/memory/vault-notes.d.ts +165 -0
  284. package/dist/memory/vault-notes.js +359 -0
  285. package/dist/memory/vault.d.ts +70 -0
  286. package/dist/memory/vault.js +169 -0
  287. package/dist/realtime/bailian.d.ts +120 -0
  288. package/dist/realtime/bailian.js +288 -0
  289. package/dist/realtime/cues.d.ts +51 -0
  290. package/dist/realtime/cues.js +94 -0
  291. package/dist/realtime/listen.d.ts +32 -0
  292. package/dist/realtime/listen.js +53 -0
  293. package/dist/realtime/preview.d.ts +23 -0
  294. package/dist/realtime/preview.js +38 -0
  295. package/dist/realtime/prompt.d.ts +8 -0
  296. package/dist/realtime/prompt.js +13 -0
  297. package/dist/realtime/voices.d.ts +19 -0
  298. package/dist/realtime/voices.js +71 -0
  299. package/dist/runtime/activities.d.ts +17 -0
  300. package/dist/runtime/activities.js +46 -0
  301. package/dist/runtime/activity-state.d.ts +22 -0
  302. package/dist/runtime/activity-state.js +83 -0
  303. package/dist/runtime/activity.d.ts +63 -0
  304. package/dist/runtime/activity.js +428 -0
  305. package/dist/runtime/agent-file.d.ts +24 -0
  306. package/dist/runtime/agent-file.js +59 -0
  307. package/dist/runtime/auto-bookkeep.d.ts +30 -0
  308. package/dist/runtime/auto-bookkeep.js +84 -0
  309. package/dist/{lib → runtime/context}/context-pack.d.ts +3 -3
  310. package/dist/runtime/context/context-pack.js +182 -0
  311. package/dist/runtime/context/thread-digest.d.ts +4 -0
  312. package/dist/runtime/context/thread-digest.js +35 -0
  313. package/dist/runtime/context/tutor-rules.d.ts +25 -0
  314. package/dist/runtime/context/tutor-rules.js +47 -0
  315. package/dist/runtime/delivery/delivery.d.ts +94 -0
  316. package/dist/runtime/delivery/delivery.js +145 -0
  317. package/dist/runtime/delivery/playback.d.ts +25 -0
  318. package/dist/runtime/delivery/playback.js +29 -0
  319. package/dist/runtime/delivery/player.d.ts +145 -0
  320. package/dist/runtime/delivery/player.js +221 -0
  321. package/dist/runtime/delivery/queue.d.ts +89 -0
  322. package/dist/runtime/delivery/queue.js +59 -0
  323. package/dist/runtime/home/edit.d.ts +39 -0
  324. package/dist/runtime/home/edit.js +132 -0
  325. package/dist/runtime/home/home.d.ts +180 -0
  326. package/dist/runtime/home/home.js +311 -0
  327. package/dist/runtime/home/store.d.ts +142 -0
  328. package/dist/runtime/home/store.js +440 -0
  329. package/dist/runtime/journal/conversation.d.ts +46 -0
  330. package/dist/runtime/journal/conversation.js +89 -0
  331. package/dist/runtime/journal/events.d.ts +27 -0
  332. package/dist/runtime/journal/events.js +136 -0
  333. package/dist/runtime/journal/kid-log.d.ts +105 -0
  334. package/dist/runtime/journal/kid-log.js +133 -0
  335. package/dist/runtime/journal/ledger.d.ts +17 -0
  336. package/dist/{lib → runtime/journal}/ledger.js +7 -32
  337. package/dist/runtime/journal/mix.d.ts +33 -0
  338. package/dist/runtime/journal/mix.js +88 -0
  339. package/dist/runtime/journal/mouth-index.d.ts +26 -0
  340. package/dist/runtime/journal/mouth-index.js +34 -0
  341. package/dist/runtime/journal/mouth.d.ts +54 -0
  342. package/dist/runtime/journal/mouth.js +102 -0
  343. package/dist/runtime/journal/recorder.d.ts +46 -0
  344. package/dist/runtime/journal/recorder.js +58 -0
  345. package/dist/runtime/journal/store.d.ts +123 -0
  346. package/dist/runtime/journal/store.js +316 -0
  347. package/dist/runtime/kid-input.d.ts +16 -0
  348. package/dist/runtime/kid-input.js +195 -0
  349. package/dist/runtime/kid-view.d.ts +124 -0
  350. package/dist/runtime/kid-view.js +157 -0
  351. package/dist/runtime/lecture.d.ts +86 -0
  352. package/dist/runtime/lecture.js +237 -0
  353. package/dist/runtime/live/call.d.ts +219 -0
  354. package/dist/runtime/live/call.js +1211 -0
  355. package/dist/runtime/live/turns.d.ts +48 -0
  356. package/dist/runtime/live/turns.js +102 -0
  357. package/dist/runtime/runner.d.ts +289 -0
  358. package/dist/runtime/runner.js +898 -0
  359. package/dist/runtime/talk-run.d.ts +21 -0
  360. package/dist/runtime/talk-run.js +34 -0
  361. package/dist/scenes/dictation/match.d.ts +57 -0
  362. package/dist/scenes/dictation/match.js +255 -0
  363. package/dist/scenes/dictation/recognize.d.ts +86 -0
  364. package/dist/scenes/dictation/recognize.js +163 -0
  365. package/dist/scenes/dictation/store.d.ts +112 -0
  366. package/dist/scenes/dictation/store.js +99 -0
  367. package/dist/scenes/look.d.ts +26 -0
  368. package/dist/scenes/look.js +1 -0
  369. package/dist/scenes/paint/painter.d.ts +84 -0
  370. package/dist/scenes/paint/painter.js +170 -0
  371. package/dist/scenes/paint/prompt.d.ts +23 -0
  372. package/dist/scenes/paint/prompt.js +36 -0
  373. package/dist/scenes/talk/en-words.d.ts +8 -0
  374. package/dist/scenes/talk/en-words.js +44 -0
  375. package/dist/scenes/talk/list.d.ts +44 -0
  376. package/dist/scenes/talk/list.js +88 -0
  377. package/dist/scenes/talk/store.d.ts +27 -0
  378. package/dist/scenes/talk/store.js +61 -0
  379. package/dist/scenes/talk/warmup.d.ts +16 -0
  380. package/dist/scenes/talk/warmup.js +39 -0
  381. package/dist/schema/activity.d.ts +149 -0
  382. package/dist/schema/activity.js +113 -0
  383. package/dist/schema/board.d.ts +200 -0
  384. package/dist/schema/board.js +42 -0
  385. package/dist/schema/config.d.ts +353 -80
  386. package/dist/schema/config.js +293 -76
  387. package/dist/schema/context-pack.d.ts +82 -13
  388. package/dist/schema/context-pack.js +97 -10
  389. package/dist/schema/conversation-files.d.ts +43 -0
  390. package/dist/schema/conversation-files.js +26 -0
  391. package/dist/schema/conversation.d.ts +459 -13
  392. package/dist/schema/conversation.js +148 -8
  393. package/dist/schema/events.d.ts +138 -0
  394. package/dist/schema/events.js +1 -0
  395. package/dist/schema/home.d.ts +46 -0
  396. package/dist/schema/home.js +30 -0
  397. package/dist/schema/index.d.ts +19 -4
  398. package/dist/schema/index.js +19 -4
  399. package/dist/schema/json-schema.d.ts +2 -0
  400. package/dist/schema/json-schema.js +23 -0
  401. package/dist/schema/kid-device.d.ts +20 -0
  402. package/dist/schema/kid-device.js +32 -0
  403. package/dist/schema/ledger.d.ts +9 -64
  404. package/dist/schema/ledger.js +7 -31
  405. package/dist/schema/memory.d.ts +73 -0
  406. package/dist/schema/memory.js +47 -0
  407. package/dist/schema/plan.d.ts +2 -2
  408. package/dist/schema/plan.js +2 -2
  409. package/dist/schema/sections.d.ts +32 -25
  410. package/dist/schema/sections.js +21 -22
  411. package/dist/schema/theme.d.ts +25 -0
  412. package/dist/schema/theme.js +26 -0
  413. package/dist/schema/timetable.d.ts +26 -0
  414. package/dist/schema/timetable.js +18 -0
  415. package/dist/schema/workspace.d.ts +41 -0
  416. package/dist/schema/workspace.js +9 -0
  417. package/dist/shared/errors.d.ts +8 -0
  418. package/dist/shared/errors.js +13 -0
  419. package/dist/shared/home.d.ts +2 -0
  420. package/dist/shared/home.js +16 -0
  421. package/dist/shared/human-notes.d.ts +5 -0
  422. package/dist/shared/human-notes.js +7 -0
  423. package/dist/shared/qianwen.d.ts +50 -0
  424. package/dist/shared/qianwen.js +109 -0
  425. package/dist/shared/time.d.ts +9 -0
  426. package/dist/shared/time.js +22 -0
  427. package/dist/shared/tokens.d.ts +18 -0
  428. package/dist/shared/tokens.js +11 -0
  429. package/dist/shared/wav.d.ts +10 -0
  430. package/dist/shared/wav.js +50 -0
  431. package/dist/stage/Assistant-Bold-ZDZZ6JHA.woff2 +0 -0
  432. package/dist/stage/Assistant-Medium-DZ25RZU3.woff2 +0 -0
  433. package/dist/stage/Assistant-Regular-PLF2XOGW.woff2 +0 -0
  434. package/dist/stage/Assistant-SemiBold-CZ5MX6FK.woff2 +0 -0
  435. package/dist/stage/chunk-226TNLQA.js +129 -0
  436. package/dist/stage/chunk-24LGQEKE.js +1 -0
  437. package/dist/stage/chunk-25XV6UY3.js +10 -0
  438. package/dist/stage/chunk-2AZI3NHJ.js +1 -0
  439. package/dist/stage/chunk-2BQZTTBE.js +1 -0
  440. package/dist/stage/chunk-2M7CGY3Y.js +11 -0
  441. package/dist/stage/chunk-2VR4WFQ7.js +10 -0
  442. package/dist/stage/chunk-2ZYXBUWG.js +9 -0
  443. package/dist/stage/chunk-32LAWMGY.js +1 -0
  444. package/dist/stage/chunk-3LEMTSOO.js +11 -0
  445. package/dist/stage/chunk-3QCKGZYE.js +32 -0
  446. package/dist/stage/chunk-44P66WFA.js +1 -0
  447. package/dist/stage/chunk-4AM6FRR6.js +7 -0
  448. package/dist/stage/chunk-4QDE4SUK.js +1 -0
  449. package/dist/stage/chunk-4QESHV3U.js +1 -0
  450. package/dist/stage/chunk-4SG5QPHB.js +2 -0
  451. package/dist/stage/chunk-4T4UVCOC.js +1 -0
  452. package/dist/stage/chunk-4WUEPPG3.js +34 -0
  453. package/dist/stage/chunk-4YCN6UZ5.js +99 -0
  454. package/dist/stage/chunk-5V7ZY2AP.js +1 -0
  455. package/dist/stage/chunk-5VS5Y2VJ.js +6 -0
  456. package/dist/stage/chunk-5W4NO2ZD.js +62 -0
  457. package/dist/stage/chunk-65CRNICM.js +1 -0
  458. package/dist/stage/chunk-66MULO7F.js +5 -0
  459. package/dist/stage/chunk-6COFQTBS.js +162 -0
  460. package/dist/stage/chunk-6VZG3M3I.js +8 -0
  461. package/dist/stage/chunk-7HVDH43T.js +1 -0
  462. package/dist/stage/chunk-7JLJN4EZ.js +8 -0
  463. package/dist/stage/chunk-7QDSP4LN.js +1 -0
  464. package/dist/stage/chunk-7R6OQAO3.js +1 -0
  465. package/dist/stage/chunk-7VTTHZKW.js +7 -0
  466. package/dist/stage/chunk-ATHR5KEN.js +10 -0
  467. package/dist/stage/chunk-B6R5LTP2.js +36 -0
  468. package/dist/stage/chunk-BD4WE264.js +1 -0
  469. package/dist/stage/chunk-BONANU47.js +206 -0
  470. package/dist/stage/chunk-BTVW7OFK.js +89 -0
  471. package/dist/stage/chunk-BUTJIDHG.js +8 -0
  472. package/dist/stage/chunk-C2IPYMML.js +84 -0
  473. package/dist/stage/chunk-C54FTPPV.js +9 -0
  474. package/dist/stage/chunk-C6LOUF2Z.js +90 -0
  475. package/dist/stage/chunk-CFF3PILO.js +339 -0
  476. package/dist/stage/chunk-CI2FQ2JY.js +9 -0
  477. package/dist/stage/chunk-CW5O4RV7.js +12 -0
  478. package/dist/stage/chunk-CYABNQYD.js +1 -0
  479. package/dist/stage/chunk-D7FFA4NS.js +15 -0
  480. package/dist/stage/chunk-DUNNXU6Z.js +8 -0
  481. package/dist/stage/chunk-E3E4Q6JF.js +6 -0
  482. package/dist/stage/chunk-EB3U3LH7.js +9 -0
  483. package/dist/stage/chunk-EGSZ736B.js +8 -0
  484. package/dist/stage/chunk-EOBXW5VQ.js +2 -0
  485. package/dist/stage/chunk-ERZC3B7Y.js +11 -0
  486. package/dist/stage/chunk-ESDOOBIH.js +11 -0
  487. package/dist/stage/chunk-EVU4QAL4.js +178 -0
  488. package/dist/stage/chunk-EVVZI2NY.js +39 -0
  489. package/dist/stage/chunk-FBKAZUKD.js +39 -0
  490. package/dist/stage/chunk-FDVKYQJN.js +1 -0
  491. package/dist/stage/chunk-FGPVYHVR.js +5 -0
  492. package/dist/stage/chunk-FHUD4AZC.js +1 -0
  493. package/dist/stage/chunk-FKUJ2DMY.js +96 -0
  494. package/dist/stage/chunk-FNZGVIJV.js +1 -0
  495. package/dist/stage/chunk-GBYSEGYM.js +78 -0
  496. package/dist/stage/chunk-GCO4TDHX.js +1 -0
  497. package/dist/stage/chunk-GKTML2LG.js +10 -0
  498. package/dist/stage/chunk-GMDIHHXQ.js +11 -0
  499. package/dist/stage/chunk-GOUNACI3.js +10 -0
  500. package/dist/stage/chunk-GXAYATPF.js +3 -0
  501. package/dist/stage/chunk-H2K2DDXV.js +8 -0
  502. package/dist/stage/chunk-H3UJI6ZY.js +13 -0
  503. package/dist/stage/chunk-H6PUGCME.js +7 -0
  504. package/dist/stage/chunk-HNBUIMIG.js +1 -0
  505. package/dist/stage/chunk-HRZY2BJQ.js +10 -0
  506. package/dist/stage/chunk-HSPJGALW.js +30 -0
  507. package/dist/stage/chunk-IBYORHIP.js +25 -0
  508. package/dist/stage/chunk-IHF4EWTY.js +1 -0
  509. package/dist/stage/chunk-ISBRPNKI.js +1 -0
  510. package/dist/stage/chunk-IZ3OI3C2.js +2 -0
  511. package/dist/stage/chunk-JEFZAC2R.js +1 -0
  512. package/dist/stage/chunk-JFIGRDPO.js +1 -0
  513. package/dist/stage/chunk-JFVYBOOC.js +9 -0
  514. package/dist/stage/chunk-JGD4TUTQ.js +1 -0
  515. package/dist/stage/chunk-JO4BEHDH.js +4 -0
  516. package/dist/stage/chunk-JOWBS42C.js +1 -0
  517. package/dist/stage/chunk-JP3TM2TG.js +1 -0
  518. package/dist/stage/chunk-JVK2C52O.js +1 -0
  519. package/dist/stage/chunk-K4I76XBX.js +14 -0
  520. package/dist/stage/chunk-KA6CZZ4M.js +1 -0
  521. package/dist/stage/chunk-KESSJ36M.js +1 -0
  522. package/dist/stage/chunk-LKATEVRU.js +1 -0
  523. package/dist/stage/chunk-LS4EJ2EI.js +1 -0
  524. package/dist/stage/chunk-LUKJQC2X.js +70 -0
  525. package/dist/stage/chunk-LWULR3SM.js +1 -0
  526. package/dist/stage/chunk-LWVRFMKX.js +2 -0
  527. package/dist/stage/chunk-LXC4ZBPZ.js +1 -0
  528. package/dist/stage/chunk-M2UP255H.js +1 -0
  529. package/dist/stage/chunk-MAPPXUZQ.js +231 -0
  530. package/dist/stage/chunk-MBMPW7Z5.js +1 -0
  531. package/dist/stage/chunk-MD3HMMTK.js +1 -0
  532. package/dist/stage/chunk-MLPCUIKR.js +17 -0
  533. package/dist/stage/chunk-MNQIRPDQ.js +8 -0
  534. package/dist/stage/chunk-MRG7MJVS.js +1 -0
  535. package/dist/stage/chunk-MU6EXW72.js +10 -0
  536. package/dist/stage/chunk-MVU2X6LU.js +4 -0
  537. package/dist/stage/chunk-N6UA5CZV.js +36 -0
  538. package/dist/stage/chunk-NLZIT2TJ.js +7 -0
  539. package/dist/stage/chunk-NOJR3J7M.js +1 -0
  540. package/dist/stage/chunk-NT7ARDOL.js +1 -0
  541. package/dist/stage/chunk-NWOGMPZH.js +1 -0
  542. package/dist/stage/chunk-NXE4KMG3.js +40 -0
  543. package/dist/stage/chunk-O4YCZXD2.js +257 -0
  544. package/dist/stage/chunk-OAJZ7HLK.js +1 -0
  545. package/dist/stage/chunk-OCFCFASO.js +1 -0
  546. package/dist/stage/chunk-ODGPG5RY.js +7 -0
  547. package/dist/stage/chunk-ODUEA52Q.js +3 -0
  548. package/dist/stage/chunk-OGDJ3FCI.js +1 -0
  549. package/dist/stage/chunk-OLDJ55TT.js +1 -0
  550. package/dist/stage/chunk-OOCL4ATI.js +2 -0
  551. package/dist/stage/chunk-OQEFDUDV.js +1 -0
  552. package/dist/stage/chunk-OQWVEWG7.js +4 -0
  553. package/dist/stage/chunk-OUIX6BGK.js +1 -0
  554. package/dist/stage/chunk-OV7OZYUO.js +7 -0
  555. package/dist/stage/chunk-PFGDY33O.js +1 -0
  556. package/dist/stage/chunk-PFJDUJB3.js +139 -0
  557. package/dist/stage/chunk-PGEW76ER.js +1 -0
  558. package/dist/stage/chunk-PP76TAQX.js +32 -0
  559. package/dist/stage/chunk-PTBOP4OT.js +2 -0
  560. package/dist/stage/chunk-PX2RVHCK.js +1 -0
  561. package/dist/stage/chunk-Q7K3PNAD.js +1 -0
  562. package/dist/stage/chunk-QDDPLZDB.js +1 -0
  563. package/dist/stage/chunk-QLGLZ77F.js +1 -0
  564. package/dist/stage/chunk-QOPFDFHI.js +1 -0
  565. package/dist/stage/chunk-QXT4KAEJ.js +1 -0
  566. package/dist/stage/chunk-R4YVZCIT.js +1 -0
  567. package/dist/stage/chunk-R6P6EHWA.js +62 -0
  568. package/dist/stage/chunk-RCH3OXBI.js +9 -0
  569. package/dist/stage/chunk-RHPE44I2.js +1 -0
  570. package/dist/stage/chunk-RJ2R4FVC.js +1 -0
  571. package/dist/stage/chunk-RJH2YVTD.js +1 -0
  572. package/dist/stage/chunk-RLWWW5OB.js +6 -0
  573. package/dist/stage/chunk-S3WO35Z7.js +120 -0
  574. package/dist/stage/chunk-S7ZGX6MW.js +1 -0
  575. package/dist/stage/chunk-SIAWX27B.js +1 -0
  576. package/dist/stage/chunk-SLG4X622.js +1 -0
  577. package/dist/stage/chunk-SLJRBC77.js +168 -0
  578. package/dist/stage/chunk-SRORWQJZ.js +1 -0
  579. package/dist/stage/chunk-STZTUIIF.js +2 -0
  580. package/dist/stage/chunk-SVQ6MWNV.js +9 -0
  581. package/dist/stage/chunk-TL3HLL2S.js +132 -0
  582. package/dist/stage/chunk-U3DOE6SF.js +24 -0
  583. package/dist/stage/chunk-UABQIZKW.js +6 -0
  584. package/dist/stage/chunk-UDK3R764.js +1 -0
  585. package/dist/stage/chunk-UFF4E54B.js +41 -0
  586. package/dist/stage/chunk-UFP5Q4AY.js +1 -0
  587. package/dist/stage/chunk-UMH2TSW2.js +72 -0
  588. package/dist/stage/chunk-UTASVNF5.js +10 -0
  589. package/dist/stage/chunk-UW7ML5ML.js +88 -0
  590. package/dist/stage/chunk-V3J7F6OP.js +1 -0
  591. package/dist/stage/chunk-VEHP5B5Q.js +5 -0
  592. package/dist/stage/chunk-VRXWB733.js +9 -0
  593. package/dist/stage/chunk-VVDHBBS5.js +5 -0
  594. package/dist/stage/chunk-VYFOH6FU.js +106 -0
  595. package/dist/stage/chunk-W3VZTLQS.js +3 -0
  596. package/dist/stage/chunk-W7WNRWTZ.js +8 -0
  597. package/dist/stage/chunk-WHUCV53C.js +1 -0
  598. package/dist/stage/chunk-WULMYHIF.js +1 -0
  599. package/dist/stage/chunk-X54EX7AW.js +9 -0
  600. package/dist/stage/chunk-X565ISZM.js +1 -0
  601. package/dist/stage/chunk-XGZMDECB.js +1 -0
  602. package/dist/stage/chunk-XHONC4RF.js +172 -0
  603. package/dist/stage/chunk-XIK4XQ6E.js +24 -0
  604. package/dist/stage/chunk-XJQQWFTE.js +1 -0
  605. package/dist/stage/chunk-XM4WOU3I.js +13 -0
  606. package/dist/stage/chunk-XM7Y5HP5.js +38 -0
  607. package/dist/stage/chunk-XNYYRGD5.js +292 -0
  608. package/dist/stage/chunk-XOYVR3SV.js +1 -0
  609. package/dist/stage/chunk-XQIW5HCE.js +1 -0
  610. package/dist/stage/chunk-YEWL7FUW.js +8 -0
  611. package/dist/stage/chunk-YI55PY3V.js +1 -0
  612. package/dist/stage/chunk-YM63HI6W.js +1 -0
  613. package/dist/stage/chunk-YNLGLU4P.js +9 -0
  614. package/dist/stage/chunk-YTNMNOWP.js +1 -0
  615. package/dist/stage/chunk-YV62XKTC.js +1 -0
  616. package/dist/stage/chunk-YVBA3QW6.js +1 -0
  617. package/dist/stage/chunk-Z2SY2HOC.js +1 -0
  618. package/dist/stage/chunk-ZBTCQEBK.js +10 -0
  619. package/dist/stage/chunk-ZCUFN74D.js +1 -0
  620. package/dist/stage/chunk-ZHOULXEJ.js +11 -0
  621. package/dist/stage/chunk-ZTRZIET2.js +1 -0
  622. package/dist/stage/index.html +11 -0
  623. package/dist/stage/stage.css +1 -0
  624. package/dist/stage/stage.js +1 -0
  625. package/dist/ui/dev/dev-page.d.ts +1 -0
  626. package/dist/ui/dev/dev-page.js +2248 -0
  627. package/dist/ui/dev/dev-theme.d.ts +6 -0
  628. package/dist/ui/dev/dev-theme.js +67 -0
  629. package/dist/ui/dev/qr-page.d.ts +8 -0
  630. package/dist/ui/dev/qr-page.js +61 -0
  631. package/dist/ui/dev/voice-gallery-page.d.ts +1 -0
  632. package/dist/ui/dev/voice-gallery-page.js +121 -0
  633. package/dist/ui/dev/voice-scenes.d.ts +21 -0
  634. package/dist/ui/dev/voice-scenes.js +30 -0
  635. package/dist/ui/dictation/en-box.d.ts +2 -0
  636. package/dist/ui/dictation/en-box.js +86 -0
  637. package/dist/ui/dictation/en-page.d.ts +1 -0
  638. package/dist/ui/dictation/en-page.js +484 -0
  639. package/dist/ui/dictation/page.d.ts +1 -0
  640. package/dist/ui/dictation/page.js +1084 -0
  641. package/dist/ui/dictation/parent-page.d.ts +1 -0
  642. package/dist/ui/dictation/parent-page.js +234 -0
  643. package/dist/ui/dictation/reel-mode.d.ts +1 -0
  644. package/dist/ui/dictation/reel-mode.js +87 -0
  645. package/dist/ui/dictation/reel-page.d.ts +1 -0
  646. package/dist/ui/dictation/reel-page.js +62 -0
  647. package/dist/ui/dictation/reel.d.ts +163 -0
  648. package/dist/ui/dictation/reel.js +436 -0
  649. package/dist/ui/dictation/ui.d.ts +44 -0
  650. package/dist/ui/dictation/ui.js +80 -0
  651. package/dist/ui/dictation/unlock.d.ts +7 -0
  652. package/dist/ui/dictation/unlock.js +16 -0
  653. package/dist/ui/kid/audio-client.d.ts +11 -0
  654. package/dist/ui/kid/audio-client.js +74 -0
  655. package/dist/ui/kid/board-mark-art.d.ts +37 -0
  656. package/dist/ui/kid/board-mark-art.js +5 -0
  657. package/dist/ui/kid/board-mark.d.ts +24 -0
  658. package/dist/ui/kid/board-mark.js +58 -0
  659. package/dist/ui/kid/kid-log.d.ts +15 -0
  660. package/dist/ui/kid/kid-log.js +87 -0
  661. package/dist/ui/kid/kid-nav.d.ts +11 -0
  662. package/dist/ui/kid/kid-nav.js +22 -0
  663. package/dist/ui/kid/kid-page.d.ts +9 -0
  664. package/dist/ui/kid/kid-page.js +3719 -0
  665. package/dist/ui/kid/letters.d.ts +26 -0
  666. package/dist/ui/kid/letters.js +51 -0
  667. package/dist/ui/kid/photo-edit.d.ts +83 -0
  668. package/dist/ui/kid/photo-edit.js +106 -0
  669. package/dist/ui/kid/photo-ui.d.ts +23 -0
  670. package/dist/ui/kid/photo-ui.js +60 -0
  671. package/dist/ui/kid/reel.d.ts +419 -0
  672. package/dist/ui/kid/reel.js +648 -0
  673. package/dist/ui/kid/tianzige.d.ts +8 -0
  674. package/dist/ui/kid/tianzige.js +45 -0
  675. package/dist/ui/kid/tutor-face.d.ts +35 -0
  676. package/dist/ui/kid/tutor-face.js +84 -0
  677. package/dist/ui/kid/voice-ui.d.ts +70 -0
  678. package/dist/ui/kid/voice-ui.js +316 -0
  679. package/dist/ui/kid/voice-view.d.ts +71 -0
  680. package/dist/ui/kid/voice-view.js +75 -0
  681. package/dist/ui/kid/word-draw.d.ts +2 -0
  682. package/dist/ui/kid/word-draw.js +107 -0
  683. package/dist/ui/kid/word-emoji.d.ts +10 -0
  684. package/dist/ui/kid/word-emoji.js +66 -0
  685. package/dist/ui/kid/word-layout.d.ts +25 -0
  686. package/dist/ui/kid/word-layout.js +29 -0
  687. package/dist/ui/parent/parent-home-page.d.ts +1 -0
  688. package/dist/ui/parent/parent-home-page.js +414 -0
  689. package/dist/ui/parent/parent-page.d.ts +2 -0
  690. package/dist/ui/parent/parent-page.js +507 -0
  691. package/dist/ui/shared/brand.d.ts +36 -0
  692. package/dist/ui/shared/brand.js +51 -0
  693. package/dist/ui/shared/favicon.d.ts +12 -0
  694. package/dist/ui/shared/favicon.js +96 -0
  695. package/dist/ui/shared/icon.d.ts +9 -0
  696. package/dist/ui/shared/icon.js +35 -0
  697. package/dist/ui/shared/inline-lib.d.ts +1 -0
  698. package/dist/ui/shared/inline-lib.js +28 -0
  699. package/dist/ui/shared/logo.d.ts +31 -0
  700. package/dist/ui/shared/logo.js +43 -0
  701. package/dist/ui/shared/page-dom.d.ts +12 -0
  702. package/dist/ui/shared/page-dom.js +36 -0
  703. package/dist/ui/shared/png.d.ts +1 -0
  704. package/dist/ui/shared/png.js +45 -0
  705. package/dist/ui/shared/qr-svg.d.ts +3 -0
  706. package/dist/ui/shared/qr-svg.js +32 -0
  707. package/dist/ui/shared/qr.d.ts +14 -0
  708. package/dist/ui/shared/qr.js +281 -0
  709. package/dist/ui/shared/reel-dock.d.ts +22 -0
  710. package/dist/ui/shared/reel-dock.js +365 -0
  711. package/dist/ui/shared/tutor-color.d.ts +15 -0
  712. package/dist/ui/shared/tutor-color.js +47 -0
  713. package/dist/ui/talk/page.d.ts +6 -0
  714. package/dist/ui/talk/page.js +294 -0
  715. package/grades/grade-2/README.md +11 -0
  716. package/grades/grade-2/VALIDATION.md +41 -0
  717. package/grades/grade-2/agents/chinese-tutor/activities//344/275/240/350/257/264/346/210/221/347/224/273.md +157 -0
  718. package/grades/grade-2/agents/chinese-tutor/activities//344/275/240/350/257/264/346/210/221/347/224/273./344/276/213/345/255/220.md +78 -0
  719. package/grades/grade-2/agents/chinese-tutor/activities//344/276/213/345/255/220/345/233/276//345/200/237/344/274/236.jpg +0 -0
  720. package/grades/grade-2/agents/chinese-tutor/activities//344/276/213/345/255/220/345/233/276//345/260/217/347/214/264/346/221/230/346/241/203.jpg +0 -0
  721. package/grades/grade-2/agents/chinese-tutor/activities//345/206/231/350/257/235.md +64 -0
  722. package/grades/grade-2/agents/chinese-tutor/activities//345/206/231/350/257/235./344/276/213/345/255/220.md +31 -0
  723. package/grades/grade-2/agents/chinese-tutor/activities//345/220/254/345/206/231.md +48 -0
  724. package/grades/grade-2/agents/chinese-tutor/activities//345/244/215/344/271/240.md +79 -0
  725. package/grades/grade-2/agents/chinese-tutor/activities//345/244/215/344/271/240./344/276/213/345/255/220.md +35 -0
  726. package/grades/grade-2/agents/chinese-tutor/activities//345/260/217/350/257/276/345/240/202.md +53 -0
  727. package/grades/grade-2/agents/chinese-tutor/activities//346/211/271/346/224/271.md +81 -0
  728. package/grades/grade-2/agents/chinese-tutor/activities//346/211/271/346/224/271./344/276/213/345/255/220.md +35 -0
  729. package/grades/grade-2/agents/chinese-tutor/activities//347/234/213/345/233/276/350/257/264/350/257/235.md +94 -0
  730. package/grades/grade-2/agents/chinese-tutor/activities//347/234/213/345/233/276/350/257/264/350/257/235./344/276/213/345/255/220.md +63 -0
  731. package/grades/grade-2/agents/chinese-tutor/activities//351/242/204/344/271/240.md +82 -0
  732. package/grades/grade-2/agents/chinese-tutor/activities//351/242/204/344/271/240./344/276/213/345/255/220.md +35 -0
  733. package/grades/grade-2/agents/chinese-tutor.md +59 -0
  734. package/grades/grade-2/agents/english-tutor/activities//345/217/243/350/257/255/350/257/276.md +149 -0
  735. package/grades/grade-2/agents/english-tutor/activities//345/217/243/350/257/255/350/257/276./344/276/213/345/255/220.md +13 -0
  736. package/grades/grade-2/agents/english-tutor/activities//345/220/254/345/206/231.md +47 -0
  737. package/grades/grade-2/agents/english-tutor/activities//345/244/215/344/271/240.md +78 -0
  738. package/grades/grade-2/agents/english-tutor/activities//345/244/215/344/271/240./344/276/213/345/255/220.md +35 -0
  739. package/grades/grade-2/agents/english-tutor/activities//345/260/217/350/257/276/345/240/202.md +53 -0
  740. package/grades/grade-2/agents/english-tutor/activities//346/211/271/346/224/271.md +80 -0
  741. package/grades/grade-2/agents/english-tutor/activities//346/211/271/346/224/271./344/276/213/345/255/220.md +35 -0
  742. package/grades/grade-2/agents/english-tutor/activities//351/242/204/344/271/240.md +86 -0
  743. package/grades/grade-2/agents/english-tutor/activities//351/242/204/344/271/240./344/276/213/345/255/220.md +35 -0
  744. package/grades/grade-2/agents/english-tutor.md +57 -0
  745. package/grades/grade-2/agents/math-tutor/activities//345/244/215/344/271/240.md +78 -0
  746. package/grades/grade-2/agents/math-tutor/activities//345/244/215/344/271/240./344/276/213/345/255/220.md +35 -0
  747. package/grades/grade-2/agents/math-tutor/activities//345/260/217/350/257/276/345/240/202.md +56 -0
  748. package/grades/grade-2/agents/math-tutor/activities//345/260/217/350/257/276/345/240/202./344/276/213/345/255/220.md +52 -0
  749. package/grades/grade-2/agents/math-tutor/activities//346/211/271/346/224/271.md +80 -0
  750. package/grades/grade-2/agents/math-tutor/activities//346/211/271/346/224/271./344/276/213/345/255/220.md +35 -0
  751. package/grades/grade-2/agents/math-tutor/activities//351/242/204/344/271/240.md +81 -0
  752. package/grades/grade-2/agents/math-tutor/activities//351/242/204/344/271/240./344/276/213/345/255/220.md +35 -0
  753. package/grades/grade-2/agents/math-tutor.md +51 -0
  754. package/grades/grade-2/examples/2026-10-27-pingjunfen/audio/index.json +44 -0
  755. package/grades/grade-2/examples/2026-10-27-pingjunfen/audio/step-1.mp3 +0 -0
  756. package/grades/grade-2/examples/2026-10-27-pingjunfen/audio/step-2.mp3 +0 -0
  757. package/grades/grade-2/examples/2026-10-27-pingjunfen/audio/step-3.mp3 +0 -0
  758. package/grades/grade-2/examples/2026-10-27-pingjunfen/audio/step-4.mp3 +0 -0
  759. package/grades/grade-2/examples/2026-10-27-pingjunfen/audio/step-5.mp3 +0 -0
  760. package/grades/grade-2/examples/2026-10-27-pingjunfen/bake.json +1 -0
  761. package/grades/grade-2/examples/2026-10-27-pingjunfen/manifest.json +63 -0
  762. package/grades/grade-2/examples/2026-10-27-pingjunfen/scene.json +247 -0
  763. package/grades/grade-2/examples/2026-10-27-pingjunfen.md +40 -0
  764. package/grades/grade-2/examples/2026-10-27-pingjunfen.ts +26 -0
  765. package/grades/grade-2/examples//345/271/263/345/235/207/345/210/206./344/276/213/345/255/220.md +24 -0
  766. package/grades/grade-2/examples//346/225/260/345/255/246/345/271/263/345/235/207/345/210/206.md +42 -0
  767. package/grades/grade-2/validation/2026-10-27.json +4410 -0
  768. package/package.json +32 -12
  769. package/skills/chalk-cli/SKILL.md +62 -0
  770. package/skills/chalk-scene/SKILL.md +91 -0
  771. package/skills/chalk-teaching/SKILL.md +82 -0
  772. package/skills/chalk-teaching/models//344/272/244/351/224/231/346/225/260/345/210/227/345/210/206/350/241/214.md +8 -0
  773. package/skills/chalk-teaching/models//345/207/221/345/215/201.md +7 -0
  774. package/skills/chalk-teaching/models//345/221/250/346/234/237/350/247/204/345/276/213.md +6 -0
  775. package/skills/chalk-teaching/models//345/256/236/347/211/251/345/233/276-/345/242/236/345/207/217.md +6 -0
  776. package/skills/chalk-teaching/models//345/256/236/347/211/251/345/233/276-/346/257/224/345/244/232/345/260/221-/346/261/202/345/244/247/346/225/260/346/261/202/345/260/217/346/225/260.md +7 -0
  777. package/skills/chalk-teaching/models//345/256/236/347/211/251/345/233/276-/346/257/224/345/244/232/345/260/221-/346/261/202/345/267/256.md +6 -0
  778. package/skills/chalk-teaching/models//345/260/217/346/243/222/350/277/233/344/275/215/345/212/240.md +7 -0
  779. package/skills/chalk-teaching/models//345/260/217/346/243/222/351/200/200/344/275/215/345/207/217.md +6 -0
  780. package/skills/chalk-teaching/models//346/216/222/351/230/237/347/202/271/351/230/265.md +7 -0
  781. package/skills/chalk-teaching/models//346/227/266/351/227/264/346/225/260/350/275/264.md +6 -0
  782. package/skills/chalk-teaching/models//346/245/274/345/261/202/351/227/264/351/232/224/345/233/276.md +7 -0
  783. package/skills/chalk-teaching/models//347/240/264/345/215/201.md +7 -0
  784. package/skills/chalk-teaching/models//347/253/226/345/274/217/351/200/200/344/275/215.md +6 -0
  785. package/skills/chalk-teaching/models//347/272/277/346/256/265/345/233/276.md +7 -0
  786. package/skills/chalk-teaching/models-index.md +24 -0
  787. package/skills/chalk-teaching/references//350/256/262/350/247/243/346/250/241/346/235/277/344/270/211/346/241/243.md +32 -0
  788. package/skills/chalk-teaching/references//350/257/264/346/230/216/346/226/207/344/273/266.md +102 -0
  789. package/skills/chalk-verify/SKILL.md +57 -0
  790. package/skills/chalk-verify/references//350/257/204/345/210/244/346/240/207/345/207/206.md +69 -0
  791. package/skills/cotutor-analyze/SKILL.md +106 -0
  792. package/skills/cotutor-analyze/references//345/221/275/344/273/244/344/270/216/346/226/207/344/273/266.md +31 -0
  793. package/skills/cotutor-board/SKILL.md +373 -0
  794. package/skills/cotutor-board/references/README.md +38 -0
  795. package/skills/cotutor-board/references/canvas.md +68 -0
  796. package/skills/cotutor-board/references/choice.md +55 -0
  797. package/skills/cotutor-board/references/code.md +46 -0
  798. package/skills/cotutor-board/references/image.md +52 -0
  799. package/skills/cotutor-board/references/lecture.md +69 -0
  800. package/skills/cotutor-board/references/paint.md +77 -0
  801. package/skills/cotutor-board/references/photo.md +61 -0
  802. package/skills/cotutor-board/references/read.md +51 -0
  803. package/skills/cotutor-board/references/text.md +69 -0
  804. package/skills/cotutor-board/references/tianzige.md +78 -0
  805. package/skills/cotutor-board/references/word.md +91 -0
  806. package/skills/cotutor-home/SKILL.md +169 -0
  807. package/skills/cotutor-home/references/dictation.md +97 -0
  808. package/skills/cotutor-home/references/tutor.md +148 -0
  809. package/skills/cotutor-home/references//345/221/275/344/273/244.md +21 -0
  810. package/skills/cotutor-home/references//351/246/226/351/241/265/350/257/255/346/263/225.md +142 -0
  811. package/skills/cotutor-tune/SKILL.md +147 -0
  812. package/skills/cotutor-tune/references//345/255/227/346/256/265.md +50 -0
  813. package/skills/cotutor-tutor/SKILL.md +261 -0
  814. package/skills/cotutor-tutor/references//344/270/212/344/270/213/346/226/207/345/214/205.md +78 -0
  815. package/themes/default/kid.css +86 -0
  816. package/themes/default/theme.json +26 -0
  817. package/agents/chinese-teacher.md +0 -19
  818. package/agents/homework-aide.md +0 -17
  819. package/agents/math-teacher.md +0 -19
  820. package/agents/planner.md +0 -18
  821. package/agents/reading-teacher.md +0 -19
  822. package/dist/cli/doctor.d.ts +0 -19
  823. package/dist/cli/doctor.js +0 -190
  824. package/dist/cli/init.js +0 -114
  825. package/dist/cli/main.js +0 -123
  826. package/dist/cli/serve.d.ts +0 -19
  827. package/dist/cli/serve.js +0 -22
  828. package/dist/cli/skeleton.d.ts +0 -21
  829. package/dist/cli/skeleton.js +0 -82
  830. package/dist/cli/workspace.d.ts +0 -61
  831. package/dist/lib/agent-file.d.ts +0 -10
  832. package/dist/lib/agent-file.js +0 -16
  833. package/dist/lib/context-pack.js +0 -46
  834. package/dist/lib/conversation.d.ts +0 -28
  835. package/dist/lib/conversation.js +0 -44
  836. package/dist/lib/kid-view.d.ts +0 -26
  837. package/dist/lib/kid-view.js +0 -38
  838. package/dist/lib/ledger.d.ts +0 -21
  839. package/dist/lib/sections.d.ts +0 -12
  840. package/dist/lib/sections.js +0 -151
  841. package/dist/lib/transcript.d.ts +0 -36
  842. package/dist/lib/transcript.js +0 -95
  843. package/dist/server/app.d.ts +0 -13
  844. package/dist/server/app.js +0 -45
  845. /package/dist/{cli → app/cli}/main.d.ts +0 -0
@@ -0,0 +1,62 @@
1
+ /**
2
+ * 小课堂卡:老师答孩子时放课里的一段,不另讲一遍。正文第一行「<课包或视频的 id> 0:19-0:30」,第二行可以写一句给孩子的话。
3
+ * 拿现成的课包或视频(家长做的);时间照上下文包 lecture.lines 抄。
4
+ * 课名、真放的起止(对齐到段界,board/lecture.ts lectureRange)、能不能放(ready)、末帧停在 SVG 的哪一刻,都是服务端下发时从课包现算的快照(src/runtime/lecture.ts 的 enrichLectures)。
5
+ * 状态 = 那一段看完没;讲稿 [[play]] 锚到它:念到那句,铺满放那一段(课里原来的声音),放完停在末帧接着念。
6
+ */
7
+ import { z } from 'zod';
8
+ import { BUNDLE_ID_RE, bodyLines } from "./kind.js";
9
+ import { clockLabel, parseClock } from "../lecture.js";
10
+ export const LecturePropsSchema = z.object({
11
+ /** 课包 id(bundles/<id>/) */
12
+ bundle: z.string().regex(BUNDLE_ID_RE),
13
+ /** 老师写的起止(毫秒);不写止 = 起点那一段放完;都不写 = 整堂课 */
14
+ from: z.number().int().nonnegative().optional(),
15
+ to: z.number().int().nonnegative().optional(),
16
+ /** 老师在第二行写的一句(卡上标题下面一行) */
17
+ text: z.string().optional(),
18
+ /** 以下是下发时从课包算的快照 */
19
+ title: z.string().optional(),
20
+ /** 真放的起止(毫秒,对齐到段界) */
21
+ start: z.number().nonnegative().optional(),
22
+ end: z.number().nonnegative().optional(),
23
+ /** 末帧停在 SVG 的哪一刻(紧凑态缩略图) */
24
+ still: z.number().nonnegative().optional(),
25
+ /** 课包读得出来、起止对得上 */
26
+ ready: z.boolean().optional(),
27
+ /** 这一课是视频(lectures/<id>/video.mp4),不是课包 */
28
+ video: z.boolean().optional(),
29
+ });
30
+ export const LectureStateSchema = z.object({ done: z.boolean() });
31
+ export const lecture = {
32
+ name: 'lecture',
33
+ props: LecturePropsSchema,
34
+ parse(body) {
35
+ const [first, ...rest] = bodyLines(body);
36
+ const [bundle, range, ...more] = (first ?? '').split(/\s+/).filter(Boolean);
37
+ if (!bundle)
38
+ throw new Error('第一行要是课包 id 和一段时间,照上下文包 lecture.source 与 lines 抄,如 2026-09-18-po13-jian-8 0:19-0:30');
39
+ if (!BUNDLE_ID_RE.test(bundle))
40
+ throw new Error(`课包 id 只能是小写字母、数字、连字符:${bundle}`);
41
+ if (more.length)
42
+ throw new Error(`第一行只写课包 id 和一段时间:${first}`);
43
+ let from;
44
+ let to;
45
+ if (range) {
46
+ const [a, b, ...c] = range.split(/[-–~]/);
47
+ from = parseClock(a) ?? undefined;
48
+ to = b === undefined ? undefined : (parseClock(b) ?? undefined);
49
+ if (from === undefined || (b !== undefined && to === undefined) || c.length)
50
+ throw new Error(`时间写成「分:秒-分:秒」,如 0:19-0:30:${range}`);
51
+ if (to !== undefined && to <= from)
52
+ throw new Error(`止要在起之后:${range}`);
53
+ }
54
+ const text = rest.join(' ').trim();
55
+ return { bundle, ...(from !== undefined ? { from } : {}), ...(to !== undefined ? { to } : {}), ...(text ? { text } : {}) };
56
+ },
57
+ state: LectureStateSchema,
58
+ describe(p, s) {
59
+ const at = p.from !== undefined ? `(${clockLabel(p.from)}${p.to !== undefined ? `–${clockLabel(p.to)}` : ''})` : '';
60
+ return s.done ? `看完了这一段${at}` : `还没看完这一段${at}`;
61
+ },
62
+ };
@@ -0,0 +1,38 @@
1
+ /**
2
+ * 画图卡(kind 名 paint):老师把孩子说清楚的故事分好幅,应用交给百炼画成一张连环画(四格时 2×2,同练习册)。
3
+ * 正文:`题:` 题干、`词:` 词语宝库(出题版才有)、`角色:` 一行一个(每幅都画同一个样子靠它)、`1.` 起一幅一行。
4
+ * 画是这张卡的资产:一轮跑完后台画(src/scenes/paint/),图落在 .cards/<n>/paint.png;下发时由 enrichPaints 补上画好没有。孩子端没有错误:没画成就停在分幅那几句。
5
+ */
6
+ import { z } from 'zod';
7
+ import { type CardKind } from './kind.ts';
8
+ /** 最多几幅:四格(2×2)是练习册的样子 */
9
+ export declare const PAINT_PANELS_MAX = 4;
10
+ /** 一幅最多几个字 */
11
+ export declare const PAINT_PANEL_MAX = 80;
12
+ /** 最多几个角色(一幅最多画三个,整个故事给四个) */
13
+ export declare const PAINT_CAST_MAX = 4;
14
+ /** 词语宝库最多几个词 */
15
+ export declare const PAINT_WORDS_MAX = 8;
16
+ export declare const PaintCastSchema: z.ZodObject<{
17
+ name: z.ZodString;
18
+ look: z.ZodOptional<z.ZodString>;
19
+ }, z.core.$strip>;
20
+ export type PaintCast = z.infer<typeof PaintCastSchema>;
21
+ export declare const PaintPropsSchema: z.ZodObject<{
22
+ panels: z.ZodArray<z.ZodString>;
23
+ cast: z.ZodOptional<z.ZodArray<z.ZodObject<{
24
+ name: z.ZodString;
25
+ look: z.ZodOptional<z.ZodString>;
26
+ }, z.core.$strip>>>;
27
+ ask: z.ZodOptional<z.ZodString>;
28
+ words: z.ZodOptional<z.ZodArray<z.ZodString>>;
29
+ pic: z.ZodOptional<z.ZodString>;
30
+ drawn: z.ZodOptional<z.ZodEnum<{
31
+ done: "done";
32
+ drawing: "drawing";
33
+ none: "none";
34
+ }>>;
35
+ note: z.ZodOptional<z.ZodString>;
36
+ }, z.core.$strip>;
37
+ export type PaintProps = z.infer<typeof PaintPropsSchema>;
38
+ export declare const paint: CardKind<PaintProps>;
@@ -0,0 +1,85 @@
1
+ /**
2
+ * 画图卡(kind 名 paint):老师把孩子说清楚的故事分好幅,应用交给百炼画成一张连环画(四格时 2×2,同练习册)。
3
+ * 正文:`题:` 题干、`词:` 词语宝库(出题版才有)、`角色:` 一行一个(每幅都画同一个样子靠它)、`1.` 起一幅一行。
4
+ * 画是这张卡的资产:一轮跑完后台画(src/scenes/paint/),图落在 .cards/<n>/paint.png;下发时由 enrichPaints 补上画好没有。孩子端没有错误:没画成就停在分幅那几句。
5
+ */
6
+ import { z } from 'zod';
7
+ import { bodyLines } from "./kind.js";
8
+ /** 最多几幅:四格(2×2)是练习册的样子 */
9
+ export const PAINT_PANELS_MAX = 4;
10
+ /** 一幅最多几个字 */
11
+ export const PAINT_PANEL_MAX = 80;
12
+ /** 最多几个角色(一幅最多画三个,整个故事给四个) */
13
+ export const PAINT_CAST_MAX = 4;
14
+ /** 词语宝库最多几个词 */
15
+ export const PAINT_WORDS_MAX = 8;
16
+ export const PaintCastSchema = z.object({
17
+ name: z.string().min(1),
18
+ /** 样子、颜色、衣服;孩子没说就不写(只有名字,画家照名字画,每幅一样就行) */
19
+ look: z.string().min(1).optional(),
20
+ });
21
+ export const PaintPropsSchema = z.object({
22
+ /** 一幅一句,只写看得见的;一到四幅 */
23
+ panels: z.array(z.string().min(1)).min(1).max(PAINT_PANELS_MAX),
24
+ cast: z.array(PaintCastSchema).max(PAINT_CAST_MAX).optional(),
25
+ /** 题干(出题版) */
26
+ ask: z.string().min(1).optional(),
27
+ /** 词语宝库(出题版) */
28
+ words: z.array(z.string().min(1)).max(PAINT_WORDS_MAX).optional(),
29
+ /** 下发时补的(enrichPaints):画好了是图的路径(相对 workspace 根),还在画 drawing,没画成 none;老师写不出来 */
30
+ pic: z.string().optional(),
31
+ drawn: z.enum(['drawing', 'done', 'none']).optional(),
32
+ /** 家长端才补的:用的模型、画了几秒、没画成的原因 */
33
+ note: z.string().optional(),
34
+ });
35
+ /** 「题:」「词:」「角色:」;中英文冒号都认(全角写成 \uFF1A,一眼看得出两种都在;原来少了全角那个,2026-10-12 qwen 写「题:」整张卡退成文字) */
36
+ const FIELD = /^(题干?|词语?宝库|词|角色)\s*[:\uFF1A]\s*(.*)$/;
37
+ /** 「1.」「1、」「1)」「第1幅:」「第 1 格:」 */
38
+ const PANEL = /^(?:第\s*)?([1-9])\s*(?:[.、)\uFF0E\uFF09]|幅\s*[:\uFF1A]?|格\s*[:\uFF1A]?)\s*(.+)$/;
39
+ const WORD_SEP = /[、,\uFF0C;\uFF1B\s]+/;
40
+ export const paint = {
41
+ name: 'paint',
42
+ props: PaintPropsSchema,
43
+ parse(body) {
44
+ const panels = [];
45
+ const cast = [];
46
+ let ask;
47
+ let words = [];
48
+ for (const line of bodyLines(body)) {
49
+ const f = FIELD.exec(line);
50
+ if (f) {
51
+ const v = f[2].trim();
52
+ if (!v)
53
+ continue;
54
+ if (f[1].startsWith('题'))
55
+ ask = v;
56
+ else if (f[1] === '角色') {
57
+ // 「名字:样子」;孩子没说样子就只写名字(2026-10-12 qwen 照「只写孩子说过的」写了「角色: 小熊」,整张卡退成文字)
58
+ const m = /^([^:\uFF1A]+)[:\uFF1A]\s*(.+)$/.exec(v);
59
+ cast.push(m ? { name: m[1].trim(), look: m[2].trim() } : { name: v });
60
+ }
61
+ else
62
+ words = v.split(WORD_SEP).map((w) => w.trim()).filter(Boolean);
63
+ continue;
64
+ }
65
+ const p = PANEL.exec(line);
66
+ if (p) {
67
+ const text = p[2].trim();
68
+ if (Array.from(text).length > PAINT_PANEL_MAX)
69
+ throw new Error(`第 ${p[1]} 幅超过 ${PAINT_PANEL_MAX} 个字;一幅只画一件事`);
70
+ panels.push(text);
71
+ continue;
72
+ }
73
+ throw new Error(`认不出这一行(要是「题:」「词:」「角色:」或「1.」开头的一幅):${line}`);
74
+ }
75
+ if (!panels.length)
76
+ throw new Error('一幅都没有:一幅一行,「1.」开头');
77
+ if (panels.length > PAINT_PANELS_MAX)
78
+ throw new Error(`${panels.length} 幅,最多 ${PAINT_PANELS_MAX} 幅`);
79
+ if (cast.length > PAINT_CAST_MAX)
80
+ throw new Error(`${cast.length} 个角色,最多 ${PAINT_CAST_MAX} 个`);
81
+ if (words.length > PAINT_WORDS_MAX)
82
+ throw new Error(`${words.length} 个词,最多 ${PAINT_WORDS_MAX} 个`);
83
+ return { panels, ...(cast.length ? { cast } : {}), ...(ask ? { ask } : {}), ...(words.length ? { words } : {}) };
84
+ },
85
+ };
@@ -0,0 +1,15 @@
1
+ /**
2
+ * 拍给我看卡(《卡片协议.md》「拍给我看卡」):老师要孩子拍一张照片发来——看图说话的那幅图、写好的那一页。
3
+ * 卡上是相机与要拍什么;它在最后一节时下沿是答案栏「等你拍…」带「拍照」「相册」,点了走老师页那套发照片屏(裁、圈、配一句话),
4
+ * 发出去那条消息的照片(与配的话)落回这张卡的答案栏(board/presentation.ts 的 askCard / kidSaid)。照片随消息交给老师,卡自己不存状态。
5
+ * 起因:看图说话老师说「把那幅图拍下来,好吗?」,末句是问句,解析器补了提问卡,孩子端写的是「等你说…」。
6
+ */
7
+ import { z } from 'zod';
8
+ import { type CardKind } from './kind.ts';
9
+ /** 要拍什么,最多几个字:一行说清,卡上一眼读完 */
10
+ export declare const PHOTO_TEXT_MAX = 30;
11
+ export declare const PhotoPropsSchema: z.ZodObject<{
12
+ text: z.ZodString;
13
+ }, z.core.$strip>;
14
+ export type PhotoProps = z.infer<typeof PhotoPropsSchema>;
15
+ export declare const photo: CardKind<PhotoProps>;
@@ -0,0 +1,29 @@
1
+ /**
2
+ * 拍给我看卡(《卡片协议.md》「拍给我看卡」):老师要孩子拍一张照片发来——看图说话的那幅图、写好的那一页。
3
+ * 卡上是相机与要拍什么;它在最后一节时下沿是答案栏「等你拍…」带「拍照」「相册」,点了走老师页那套发照片屏(裁、圈、配一句话),
4
+ * 发出去那条消息的照片(与配的话)落回这张卡的答案栏(board/presentation.ts 的 askCard / kidSaid)。照片随消息交给老师,卡自己不存状态。
5
+ * 起因:看图说话老师说「把那幅图拍下来,好吗?」,末句是问句,解析器补了提问卡,孩子端写的是「等你说…」。
6
+ */
7
+ import { z } from 'zod';
8
+ import { bodyLines } from "./kind.js";
9
+ /** 要拍什么,最多几个字:一行说清,卡上一眼读完 */
10
+ export const PHOTO_TEXT_MAX = 30;
11
+ export const PhotoPropsSchema = z.object({
12
+ /** 要拍什么(「看图说话的那幅图」「写好的那一页」) */
13
+ text: z.string().min(1),
14
+ });
15
+ export const photo = {
16
+ name: 'photo',
17
+ props: PhotoPropsSchema,
18
+ parse(body) {
19
+ const lines = bodyLines(body);
20
+ if (!lines.length)
21
+ throw new Error('写一行:要孩子拍什么');
22
+ if (lines.length > 1)
23
+ throw new Error('一张卡一行:要拍什么');
24
+ const n = Array.from(lines[0]).length;
25
+ if (n > PHOTO_TEXT_MAX)
26
+ throw new Error(`${n} 个字,最多 ${PHOTO_TEXT_MAX} 个;说清要拍什么就够`);
27
+ return { text: lines[0] };
28
+ },
29
+ };
@@ -0,0 +1,8 @@
1
+ /** 点读卡:一行一段,孩子点哪段听哪段;配音在一轮跑完后后台按段合成到 .cards/<n>/<段>.mp3,还没好的段退浏览器合成声。 */
2
+ import { z } from 'zod';
3
+ import { type CardKind } from './kind.ts';
4
+ export declare const ReadPropsSchema: z.ZodObject<{
5
+ segments: z.ZodArray<z.ZodString>;
6
+ }, z.core.$strip>;
7
+ export type ReadProps = z.infer<typeof ReadPropsSchema>;
8
+ export declare const read: CardKind<ReadProps>;
@@ -0,0 +1,18 @@
1
+ /** 点读卡:一行一段,孩子点哪段听哪段;配音在一轮跑完后后台按段合成到 .cards/<n>/<段>.mp3,还没好的段退浏览器合成声。 */
2
+ import { z } from 'zod';
3
+ import { bodyLines } from "./kind.js";
4
+ export const ReadPropsSchema = z.object({ segments: z.array(z.string().min(1)).min(1) });
5
+ export const read = {
6
+ name: 'read',
7
+ where: ['board', 'home'],
8
+ props: ReadPropsSchema,
9
+ parse(body) {
10
+ const segments = bodyLines(body);
11
+ if (!segments.length)
12
+ throw new Error('一行都没有(一行一段)');
13
+ return { segments };
14
+ },
15
+ assets(p) {
16
+ return p.segments.map((text, k) => ({ file: `${k + 1}.mp3`, text }));
17
+ },
18
+ };
@@ -0,0 +1,20 @@
1
+ /**
2
+ * 文字卡:一段字。正文第一行以 `#` 开头就是标题(2026-09-12:样子归主题,老师只写 ```text);
3
+ * 只有一行 `# 标题` 没正文 = 小节标题(heading:渲染成无底加粗一行,不算一张卡)。
4
+ * 修饰词只有 formula(算式,衬线居中);别的修饰词不认,整段当正文。
5
+ */
6
+ import { z } from 'zod';
7
+ import type { CardKind } from './kind.ts';
8
+ export declare const TEXT_STYLES: readonly ["formula"];
9
+ export type TextStyle = (typeof TEXT_STYLES)[number];
10
+ export declare const TextPropsSchema: z.ZodObject<{
11
+ style: z.ZodOptional<z.ZodEnum<{
12
+ formula: "formula";
13
+ }>>;
14
+ title: z.ZodOptional<z.ZodString>;
15
+ text: z.ZodString;
16
+ heading: z.ZodOptional<z.ZodBoolean>;
17
+ ask: z.ZodOptional<z.ZodBoolean>;
18
+ }, z.core.$strip>;
19
+ export type TextProps = z.infer<typeof TextPropsSchema>;
20
+ export declare const text: CardKind<TextProps>;
@@ -0,0 +1,59 @@
1
+ /**
2
+ * 文字卡:一段字。正文第一行以 `#` 开头就是标题(2026-09-12:样子归主题,老师只写 ```text);
3
+ * 只有一行 `# 标题` 没正文 = 小节标题(heading:渲染成无底加粗一行,不算一张卡)。
4
+ * 修饰词只有 formula(算式,衬线居中);别的修饰词不认,整段当正文。
5
+ */
6
+ import { z } from 'zod';
7
+ export const TEXT_STYLES = ['formula'];
8
+ export const TextPropsSchema = z.object({
9
+ style: z.enum(TEXT_STYLES).optional(),
10
+ /** 第一行 `# 标题` */
11
+ title: z.string().optional(),
12
+ /** 正文 */
13
+ text: z.string(),
14
+ /** 小节标题行(只有 `# 标题`):不算卡 */
15
+ heading: z.boolean().optional(),
16
+ /** 提问卡:解析器在末句问句没配能答的卡时补的(老师写不出来),text 就是那句问话 */
17
+ ask: z.boolean().optional(),
18
+ });
19
+ /**
20
+ * 文字卡里的答案行:老师把填空卡的「= 答案」写进了文字卡(10-20 21:24「( )穷( )尽,填两个字。= 山 = 水」),
21
+ * 文字卡原来不剥,答案上了孩子的板。正文里有空(___、( ))时,「= 」开头的行算答案:下发前剥掉,家长视图报一句。
22
+ * 没有空的照旧(算式一步一步往下写「= 24 ÷ 2」是正文)
23
+ */
24
+ const ANSWER_LINE = /^\s*=\s/;
25
+ const BLANK = /_{2,}|[((][\s ]*[))]/;
26
+ function answerLines(text) {
27
+ const lines = text.split('\n');
28
+ const kept = lines.filter((l) => !ANSWER_LINE.test(l));
29
+ if (kept.length === lines.length || !BLANK.test(kept.join('\n')))
30
+ return { kept: text, dropped: 0 };
31
+ return { kept: kept.join('\n').trim(), dropped: lines.length - kept.length };
32
+ }
33
+ export const text = {
34
+ name: 'text',
35
+ where: ['board', 'home'],
36
+ props: TextPropsSchema,
37
+ parse(body, mods) {
38
+ const style = mods.map((m) => m.toLowerCase()).find((m) => TEXT_STYLES.includes(m));
39
+ const trimmed = body.replace(/^\s*\n/, '').trimEnd();
40
+ if (!trimmed.trim())
41
+ throw new Error('正文是空的');
42
+ const hd = /^#{1,3}\s+(\S.*)$/.exec(trimmed.split('\n')[0] ?? '');
43
+ if (hd && !style) {
44
+ const nl = trimmed.indexOf('\n');
45
+ const rest = nl < 0 ? '' : trimmed.slice(nl + 1).trim();
46
+ const title = hd[1].trim();
47
+ return rest ? { title, text: rest } : { title, text: '', heading: true };
48
+ }
49
+ return { ...(style ? { style } : {}), text: trimmed.trim() };
50
+ },
51
+ note(_body, p) {
52
+ const { dropped } = answerLines(p.text);
53
+ return dropped ? `文字卡里 ${dropped} 行「= …」像答案,孩子端不显示(要孩子做的出 choice 卡,或请他开口说)` : null;
54
+ },
55
+ strip(p) {
56
+ const { kept, dropped } = answerLines(p.text);
57
+ return dropped ? { ...p, text: kept } : p;
58
+ },
59
+ };
@@ -0,0 +1,16 @@
1
+ /**
2
+ * 田字格卡(kind 名 tianzige):一到四个汉字,孩子端每个字一个田字格,讲到这张卡时逐笔写一遍,之后点哪个字哪个字再写一遍。
3
+ * 笔顺数据是确定性资源(hanzi-writer-data,服务 /api/kid/tianzige/<字> 现读),老师只写字,不写笔画、不数笔画。没有状态。
4
+ * 第二行可以写拼音(一字一个音节,声调符号或数字调),孩子端标在格子上方;多音字按这句话里的读法,老师写(《卡片协议.md》)。
5
+ * 拼音对不上字数、不像拼音:卡照常只写字,家长视图报一句(note)。
6
+ */
7
+ import { z } from 'zod';
8
+ import type { CardKind } from './kind.ts';
9
+ export declare const TianzigePropsSchema: z.ZodObject<{
10
+ chars: z.ZodString;
11
+ pinyin: z.ZodOptional<z.ZodArray<z.ZodString>>;
12
+ }, z.core.$strip>;
13
+ export type TianzigeProps = z.infer<typeof TianzigePropsSchema>;
14
+ export declare const HAN: RegExp;
15
+ export declare const TIANZIGE_MAX = 4;
16
+ export declare const tianzige: CardKind<TianzigeProps>;
@@ -0,0 +1,64 @@
1
+ /**
2
+ * 田字格卡(kind 名 tianzige):一到四个汉字,孩子端每个字一个田字格,讲到这张卡时逐笔写一遍,之后点哪个字哪个字再写一遍。
3
+ * 笔顺数据是确定性资源(hanzi-writer-data,服务 /api/kid/tianzige/<字> 现读),老师只写字,不写笔画、不数笔画。没有状态。
4
+ * 第二行可以写拼音(一字一个音节,声调符号或数字调),孩子端标在格子上方;多音字按这句话里的读法,老师写(《卡片协议.md》)。
5
+ * 拼音对不上字数、不像拼音:卡照常只写字,家长视图报一句(note)。
6
+ */
7
+ import { z } from 'zod';
8
+ import { toneMark } from "../presentation.js";
9
+ export const TianzigePropsSchema = z.object({
10
+ /** 要写的字,1–4 个汉字,连着写 */
11
+ chars: z.string().min(1),
12
+ /** 每个字的拼音(带调号,一字一个);没写或对不上 = 没有 */
13
+ pinyin: z.array(z.string().min(1)).optional(),
14
+ });
15
+ export const HAN = /^\p{Script=Han}$/u;
16
+ export const TIANZIGE_MAX = 4;
17
+ /** 一个音节:数字调(gu3,轻声可不写数字)或一个调号(gǔ),不混写 */
18
+ const SYLLABLE = /^(?:[a-zü]+[1-5]?|[a-zü]*[āáǎàēéěèīíǐìōóǒòūúǔùǖǘǚǜ][a-zü]*)$/;
19
+ const VOWEL = /[aeiouüāáǎàēéěèīíǐìōóǒòūúǔùǖǘǚǜ]/;
20
+ const HAS_HAN = /\p{Script=Han}/u;
21
+ /** 正文 → 字那几行(连起来)与拼音那几行(没有汉字的行) */
22
+ function split(body) {
23
+ const lines = body.split('\n').map((l) => l.trim()).filter(Boolean);
24
+ const han = lines.filter((l) => HAS_HAN.test(l));
25
+ const py = lines.filter((l) => !HAS_HAN.test(l));
26
+ // 一行汉字都没有:当它是要写的字(报「不是汉字」),不当拼音
27
+ if (!han.length)
28
+ return { chars: Array.from(body.replace(/\s+/g, '')), pinyin: null };
29
+ return { chars: Array.from(han.join('').replace(/\s+/g, '')), pinyin: py.length ? py.join(' ') : null };
30
+ }
31
+ /** 拼音那行 → 每字一个带调号的音节;对不上 → why */
32
+ function readPinyin(line, n) {
33
+ const syl = line.toLowerCase().replace(/v/g, 'ü').split(/\s+/).filter(Boolean);
34
+ const bad = syl.find((s) => !SYLLABLE.test(s) || !VOWEL.test(s));
35
+ if (bad)
36
+ return { why: `「${bad}」不像拼音` };
37
+ if (syl.length !== n)
38
+ return { why: `拼音 ${syl.length} 个音节,字 ${n} 个,要一字一个` };
39
+ return { pinyin: syl.map(toneMark) };
40
+ }
41
+ export const tianzige = {
42
+ name: 'tianzige',
43
+ where: ['board', 'home'],
44
+ props: TianzigePropsSchema,
45
+ parse(body) {
46
+ const { chars, pinyin } = split(body);
47
+ if (!chars.length)
48
+ throw new Error('要写的字呢(一到四个汉字)');
49
+ const bad = chars.find((c) => !HAN.test(c));
50
+ if (bad)
51
+ throw new Error(`「${bad}」不是汉字;拼音写在第二行,标点写在讲稿里`);
52
+ if (chars.length > TIANZIGE_MAX)
53
+ throw new Error(`一张卡最多 ${TIANZIGE_MAX} 个字(给了 ${chars.length} 个),拆成两张`);
54
+ const py = pinyin ? readPinyin(pinyin, chars.length) : null;
55
+ return { chars: chars.join(''), ...(py && 'pinyin' in py ? { pinyin: py.pinyin } : {}) };
56
+ },
57
+ note(body, props) {
58
+ const { pinyin } = split(body);
59
+ if (!pinyin || props.pinyin)
60
+ return null;
61
+ const py = readPinyin(pinyin, Array.from(props.chars).length);
62
+ return 'why' in py ? `田字格的拼音没用上(${py.why}),只写了字` : null;
63
+ },
64
+ };
@@ -0,0 +1,72 @@
1
+ /**
2
+ * 老师卡(kind 名 tutor,只用在首页):一位老师 + 几个按钮,孩子点了进这位老师。
3
+ * 标签修饰 = 老师的键;正文一行一个按钮:`接着 <日期> <话题> <字>` 接着那天的那个话题,`小课堂 <课包 id> <字>` 先看那份课包再聊,其余行是开场按钮;
4
+ * `讲法:` 行挂在上一个按钮下面,是家长和 LLM 写给老师的,strip 剥掉,孩子端 JSON 里没有;`留到: <日期>` 也挂在上一个按钮下面,过了那天孩子端不再出现(家长端表单的「只今天 / 到周日」)。
5
+ * 小课堂按钮下面 `activity: <名>` 挂一个 activity,看完开口那条起照它带。
6
+ * `activity <名> [孩子看到的字]` 进那个 activity(agents/<老师>/activities/<名>.md);它下面 `名: 值` 的行是这个 activity 的参数,和讲法一样 strip 剥掉。
7
+ * 「新话题」应用永远放第一个,不进 props。老师在不在、话题在不在,由首页检查(src/runtime/home/store.ts)查。
8
+ */
9
+ import { z } from 'zod';
10
+ import { type CardKind } from './kind.ts';
11
+ export declare const TUTOR_BUTTONS_MAX = 4;
12
+ export declare const BUTTON_LABEL_MAX = 16;
13
+ export declare const TutorButtonSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
14
+ kind: z.ZodLiteral<"start">;
15
+ label: z.ZodString;
16
+ brief: z.ZodOptional<z.ZodString>;
17
+ until: z.ZodOptional<z.ZodString>;
18
+ }, z.core.$strip>, z.ZodObject<{
19
+ kind: z.ZodLiteral<"continue">;
20
+ label: z.ZodString;
21
+ date: z.ZodString;
22
+ thread: z.ZodString;
23
+ brief: z.ZodOptional<z.ZodString>;
24
+ until: z.ZodOptional<z.ZodString>;
25
+ }, z.core.$strip>, z.ZodObject<{
26
+ kind: z.ZodLiteral<"lecture">;
27
+ label: z.ZodString;
28
+ bundle: z.ZodString;
29
+ brief: z.ZodOptional<z.ZodString>;
30
+ until: z.ZodOptional<z.ZodString>;
31
+ activity: z.ZodOptional<z.ZodString>;
32
+ }, z.core.$strip>, z.ZodObject<{
33
+ kind: z.ZodLiteral<"activity">;
34
+ label: z.ZodString;
35
+ activity: z.ZodString;
36
+ params: z.ZodRecord<z.ZodString, z.ZodString>;
37
+ brief: z.ZodOptional<z.ZodString>;
38
+ until: z.ZodOptional<z.ZodString>;
39
+ }, z.core.$strip>], "kind">;
40
+ export type TutorButton = z.infer<typeof TutorButtonSchema>;
41
+ export declare const TutorPropsSchema: z.ZodObject<{
42
+ tutor: z.ZodString;
43
+ buttons: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
44
+ kind: z.ZodLiteral<"start">;
45
+ label: z.ZodString;
46
+ brief: z.ZodOptional<z.ZodString>;
47
+ until: z.ZodOptional<z.ZodString>;
48
+ }, z.core.$strip>, z.ZodObject<{
49
+ kind: z.ZodLiteral<"continue">;
50
+ label: z.ZodString;
51
+ date: z.ZodString;
52
+ thread: z.ZodString;
53
+ brief: z.ZodOptional<z.ZodString>;
54
+ until: z.ZodOptional<z.ZodString>;
55
+ }, z.core.$strip>, z.ZodObject<{
56
+ kind: z.ZodLiteral<"lecture">;
57
+ label: z.ZodString;
58
+ bundle: z.ZodString;
59
+ brief: z.ZodOptional<z.ZodString>;
60
+ until: z.ZodOptional<z.ZodString>;
61
+ activity: z.ZodOptional<z.ZodString>;
62
+ }, z.core.$strip>, z.ZodObject<{
63
+ kind: z.ZodLiteral<"activity">;
64
+ label: z.ZodString;
65
+ activity: z.ZodString;
66
+ params: z.ZodRecord<z.ZodString, z.ZodString>;
67
+ brief: z.ZodOptional<z.ZodString>;
68
+ until: z.ZodOptional<z.ZodString>;
69
+ }, z.core.$strip>], "kind">>;
70
+ }, z.core.$strip>;
71
+ export type TutorProps = z.infer<typeof TutorPropsSchema>;
72
+ export declare const tutor: CardKind<TutorProps>;
@@ -0,0 +1,134 @@
1
+ /**
2
+ * 老师卡(kind 名 tutor,只用在首页):一位老师 + 几个按钮,孩子点了进这位老师。
3
+ * 标签修饰 = 老师的键;正文一行一个按钮:`接着 <日期> <话题> <字>` 接着那天的那个话题,`小课堂 <课包 id> <字>` 先看那份课包再聊,其余行是开场按钮;
4
+ * `讲法:` 行挂在上一个按钮下面,是家长和 LLM 写给老师的,strip 剥掉,孩子端 JSON 里没有;`留到: <日期>` 也挂在上一个按钮下面,过了那天孩子端不再出现(家长端表单的「只今天 / 到周日」)。
5
+ * 小课堂按钮下面 `activity: <名>` 挂一个 activity,看完开口那条起照它带。
6
+ * `activity <名> [孩子看到的字]` 进那个 activity(agents/<老师>/activities/<名>.md);它下面 `名: 值` 的行是这个 activity 的参数,和讲法一样 strip 剥掉。
7
+ * 「新话题」应用永远放第一个,不进 props。老师在不在、话题在不在,由首页检查(src/runtime/home/store.ts)查。
8
+ */
9
+ import { z } from 'zod';
10
+ import { BUNDLE_ID_RE } from "./kind.js";
11
+ export const TUTOR_BUTTONS_MAX = 4;
12
+ export const BUTTON_LABEL_MAX = 16;
13
+ const NAME_RE = /^[a-z0-9][a-z0-9-]*$/;
14
+ const DAY_RE = /^\d{4}-\d{2}-\d{2}$/;
15
+ const THREAD_RE = /^\d{4}-\d+$/;
16
+ const LIST_PREFIX = /^(?:[-*+]|\d+[.)])\s+/;
17
+ const BRIEF_LINE = /^讲法\s*[::]\s*(.*)$/;
18
+ const UNTIL_LINE = /^留到\s*[::]\s*(.*)$/;
19
+ const CONTINUE_LINE = /^接着\s+/;
20
+ const LECTURE_LINE = /^小课堂\s+/;
21
+ const ACTIVITY_LINE = /^activity(?:\s|$)/;
22
+ /** activity 按钮下面的参数行:名: 值 */
23
+ const PARAM_LINE = /^([^\s::]+)\s*[::]\s*(.*)$/;
24
+ /** 小课堂按钮下面挂一个 activity:看完开口那条起照那个 activity 带(参数用缺省) */
25
+ const LECTURE_ACTIVITY = /^activity\s*[::]\s*(.*)$/;
26
+ const label = z.string().min(1).refine((s) => Array.from(s).length <= BUTTON_LABEL_MAX, `按钮的字最多 ${BUTTON_LABEL_MAX} 个`);
27
+ /** 留到哪天(含那天);过了孩子端不再出现 */
28
+ const until = z.string().regex(DAY_RE).optional();
29
+ export const TutorButtonSchema = z.discriminatedUnion('kind', [
30
+ /** 开场:孩子点了就把 label 发给老师(新话题),老师照 brief 开讲 */
31
+ z.object({ kind: z.literal('start'), label, brief: z.string().min(1).optional(), until }),
32
+ /** 接着:那天的那个话题;今天的 resume,以前的新开会话、上下文包带那个话题的尾巴 */
33
+ z.object({ kind: z.literal('continue'), label, date: z.string().regex(DAY_RE), thread: z.string().regex(THREAD_RE), brief: z.string().min(1).optional(), until }),
34
+ /** 小课堂:孩子点了先看这份课包(铺满、一口气放完),看完才能开口;开口那条新开话题,老师拿到课的每句与孩子画的地方 */
35
+ z.object({ kind: z.literal('lecture'), label, bundle: z.string().regex(BUNDLE_ID_RE), brief: z.string().min(1).optional(), until, activity: z.string().min(1).optional() }),
36
+ /** activity:孩子点了新开话题、把 label 发给老师;老师照那个 activity 文件带,params 是家长填的(原文,对不对由首页检查读 activity 文件查) */
37
+ z.object({ kind: z.literal('activity'), label, activity: z.string().min(1), params: z.record(z.string(), z.string()), brief: z.string().min(1).optional(), until }),
38
+ ]);
39
+ export const TutorPropsSchema = z.object({
40
+ /** 老师的键(cotutor.json tutors 里的,-tutor 结尾) */
41
+ tutor: z.string().regex(NAME_RE),
42
+ buttons: z.array(TutorButtonSchema).max(TUTOR_BUTTONS_MAX),
43
+ });
44
+ export const tutor = {
45
+ name: 'tutor',
46
+ where: ['home'],
47
+ props: TutorPropsSchema,
48
+ parse(body, mods) {
49
+ const name = mods[0]?.toLowerCase();
50
+ if (!name)
51
+ throw new Error('标签后面写老师的键,如 ```tutor chinese-tutor');
52
+ if (!NAME_RE.test(name))
53
+ throw new Error(`「${mods[0]}」不是老师的键(cotutor.json tutors 里的英文名,如 chinese-tutor)`);
54
+ if (mods.length > 1)
55
+ throw new Error(`一张老师卡只写一位老师(多了 ${mods.slice(1).join(' ')})`);
56
+ const buttons = [];
57
+ for (const raw of body.split('\n')) {
58
+ const line = raw.trim().replace(LIST_PREFIX, '');
59
+ if (!line)
60
+ continue;
61
+ const brief = BRIEF_LINE.exec(line);
62
+ if (brief) {
63
+ const last = buttons[buttons.length - 1];
64
+ if (!last)
65
+ throw new Error('「讲法:」前面要有一个按钮(讲法挂在上一个按钮下面)');
66
+ const text = brief[1].trim();
67
+ if (text)
68
+ last.brief = last.brief ? `${last.brief}\n${text}` : text;
69
+ continue;
70
+ }
71
+ const keep = UNTIL_LINE.exec(line);
72
+ if (keep) {
73
+ const last = buttons[buttons.length - 1];
74
+ if (!last)
75
+ throw new Error('「留到:」前面要有一个按钮(留到挂在上一个按钮下面)');
76
+ const day = keep[1].trim();
77
+ if (!DAY_RE.test(day))
78
+ throw new Error(`「${line}」:留到要写日期,如「留到: 2026-10-12」(那天过完孩子就看不到这个按钮)`);
79
+ last.until = day;
80
+ continue;
81
+ }
82
+ if (line === '新话题')
83
+ continue;
84
+ const last = buttons[buttons.length - 1];
85
+ const hang = LECTURE_ACTIVITY.exec(line);
86
+ if (hang) {
87
+ if (last?.kind !== 'lecture')
88
+ throw new Error(`「${line}」:activity: 只挂在小课堂按钮下面;要一个 activity 按钮,写「activity <名>」`);
89
+ const name = hang[1].trim();
90
+ if (!/^\S+$/.test(name))
91
+ throw new Error(`「${line}」:activity: 后面写一个 activity 的名字,如「activity: 看图说话」`);
92
+ last.activity = name;
93
+ continue;
94
+ }
95
+ const param = last?.kind === 'activity' ? PARAM_LINE.exec(line) : null;
96
+ if (last?.kind === 'activity' && param) {
97
+ if (param[1] in last.params)
98
+ throw new Error(`「${line}」:参数 ${param[1]} 写了两次`);
99
+ last.params[param[1]] = param[2].trim();
100
+ continue;
101
+ }
102
+ if (CONTINUE_LINE.test(line)) {
103
+ const m = /^接着\s+(\S+)\s+(\S+)\s+(.+)$/.exec(line);
104
+ if (!m || !DAY_RE.test(m[1]) || !THREAD_RE.test(m[2]))
105
+ throw new Error(`「${line}」:接着要写成「接着 <日期> <话题> <孩子看到的字>」,如「接着 2026-09-16 1930-1 接着写看图写话」`);
106
+ buttons.push({ kind: 'continue', date: m[1], thread: m[2], label: m[3].trim() });
107
+ }
108
+ else if (LECTURE_LINE.test(line)) {
109
+ const m = /^小课堂\s+(\S+)\s+(.+)$/.exec(line);
110
+ if (!m || !BUNDLE_ID_RE.test(m[1]))
111
+ throw new Error(`「${line}」:小课堂要写成「小课堂 <课包 id> <孩子看到的字>」,如「小课堂 2026-09-18-po13-jian-8 13 减 8 怎么拆」`);
112
+ buttons.push({ kind: 'lecture', bundle: m[1], label: m[2].trim() });
113
+ }
114
+ else if (ACTIVITY_LINE.test(line)) {
115
+ const m = /^activity\s+(\S+)(?:\s+(.+))?$/.exec(line);
116
+ if (!m)
117
+ throw new Error(`「${line}」:activity 要写成「activity <名> [孩子看到的字]」,如「activity 你说我画」`);
118
+ buttons.push({ kind: 'activity', activity: m[1], label: (m[2] ?? m[1]).trim(), params: {} });
119
+ }
120
+ else
121
+ buttons.push({ kind: 'start', label: line });
122
+ const cps = Array.from(buttons[buttons.length - 1].label).length;
123
+ if (cps > BUTTON_LABEL_MAX)
124
+ throw new Error(`按钮「${buttons[buttons.length - 1].label}」${cps} 个字,最多 ${BUTTON_LABEL_MAX} 个;要跟老师说的挪到下一行的「讲法:」里`);
125
+ }
126
+ if (buttons.length > TUTOR_BUTTONS_MAX)
127
+ throw new Error(`按钮最多 ${TUTOR_BUTTONS_MAX} 个(「新话题」不算),写了 ${buttons.length} 个`);
128
+ return { tutor: name, buttons };
129
+ },
130
+ strip(props) {
131
+ // 讲法与 activity 的参数是写给老师的,孩子端不要
132
+ return { ...props, buttons: props.buttons.map(({ brief: _brief, ...b }) => (b.kind === 'activity' ? { ...b, params: {} } : b)) };
133
+ },
134
+ };