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,141 @@
1
+ /**
2
+ * Qwen Code(`qwen`,0.25 起)的适配器。输出读法在 stream-json.ts,运行约定:
3
+ * - **隔离的家**:不用 `--bare`(它不读任何配置、不认 `--core-tools`、自带 read_file / edit / run_shell_command 一套)。
4
+ * `QWEN_HOME` 指 workspace 的 `.cotutor/qwen/home/`(不改 HOME),里面的 settings.json 由这里生成:模型供应商(key 只写环境变量名)、
5
+ * 关掉它自己的记忆整理(不然一轮跑完在后台用 write_file 写文件)、使用统计、遥测、防休眠。会话落在 `.cotutor/qwen/runtime/`。
6
+ * - **工具**:`{toolArgs}` 展开成 `--core-tools` + `--exclude-tools`;不带 = 工具表为空,只读 = read_file / glob / grep_search。
7
+ * 模板带 `--approval-mode default`:shell、写、读 workspace 外都被拒(`--yolo` 会放行 workspace 外的读)。
8
+ * - **思考量**:没有旗标;按 effort 指一份系统配置(`QWEN_CODE_SYSTEM_SETTINGS_PATH`,`model.reasoningEffort`)。
9
+ * - **key 与端点**:settings.json 只写 `${COTUTOR_QWEN_BASE_URL}` 与环境变量名 `COTUTOR_QWEN_API_KEY`(qwen 读配置时展开);起进程时按 `src/shared/qianwen.ts`
10
+ * 定走 Token Plan 还是百炼按量,把这两个填进子进程的环境,不落盘。出厂的几个模型 Token Plan 都有,有它的 key 就走它。
11
+ * - 没有钱数,只报 token;超时(退出码 55)不吐 result;每轮一条 goal_state 事件(读法里不出事件)。
12
+ */
13
+ import { mkdir, readFile, writeFile } from 'node:fs/promises';
14
+ import { dirname, join } from 'node:path';
15
+ import { compatibleBase, qianwenKeys, qianwenLine } from "../../shared/qianwen.js";
16
+ import { parseStreamJson, streamJsonUserMessage } from "./stream-json.js";
17
+ const KINDS = {
18
+ read_file: 'read',
19
+ read_many_files: 'read',
20
+ zoom_image: 'read',
21
+ list_directory: 'read',
22
+ run_shell_command: 'shell',
23
+ glob: 'search',
24
+ grep_search: 'search',
25
+ edit: 'edit',
26
+ write_file: 'edit',
27
+ notebook_edit: 'edit',
28
+ skill: 'skill',
29
+ };
30
+ /** 只读那轮给的核心工具(读文件含图片、按名找、按内容找) */
31
+ const READ_TOOLS = ['read_file', 'glob', 'grep_search'];
32
+ /** `--core-tools` 管不到的非核心工具,要一个个排除(0.25 的 system/init 里出现过的;ask_user_question 与计划模式那两个是不加 --bare 时才有的,2026-10-09 真跑里核对出来) */
33
+ const NON_CORE = ['agent', 'skill', 'list_agents', 'task_stop', 'send_message', 'record_artifact', 'get_goal', 'update_goal', 'tool_call', 'tool_search', 'report_findings', 'enter_worktree', 'exit_worktree', 'ask_user_question', 'enter_plan_mode', 'exit_plan_mode'];
34
+ /** workspace 里归 qwen 的目录(机器文件,prepare 每次对一遍) */
35
+ export const QWEN_DIR = '.cotutor/qwen';
36
+ const homeOf = (root) => join(root, QWEN_DIR, 'home');
37
+ const effortFile = (root, level) => join(root, QWEN_DIR, `effort-${level}.json`);
38
+ /** 政策 effort → 模型的思考档:low 不想(孩子在等);qwen3.7 系列只有开关,none 以外都是开 */
39
+ const EFFORT = { low: 'none', medium: 'low', high: 'xhigh' };
40
+ /**
41
+ * 带工具的轮次(作业照片、记账)至少想一点:2026-10-09 真跑,同一道照片题 none 那次 read_file 都没调、请孩子说是哪页;
42
+ * low 那次读了图、认出题目(11 秒)。孩子随口的话不带工具,不想照旧(3–6 秒)
43
+ */
44
+ const levelOf = (effort, tools) => (tools !== 'off' && EFFORT[effort] === 'none' ? 'low' : EFFORT[effort]);
45
+ /** settings.json 里写的占位;qwen 读配置时拿子进程环境展开 */
46
+ const BASE_ENV = 'COTUTOR_QWEN_BASE_URL';
47
+ const KEY_ENV = 'COTUTOR_QWEN_API_KEY';
48
+ const toggle = { thinking: true, toggleOnly: true, disableField: 'enable_thinking' };
49
+ const tiers = { thinking: true, efforts: ['low', 'medium', 'xhigh'], defaultEffort: 'xhigh', disableField: 'reasoning_effort' };
50
+ /** 出厂模型(2026-10-09 五个模型 7 道真题对比:不想时 2–8 秒,讲得准也细;3.7-plus 快但浅,3.8-flash 不想时把盘算写进讲稿——
51
+ * 2026-10-13 英语老师三问没再见到,出厂 qwen-flash 运行时给英语老师) */
52
+ export const QWEN_DEFAULT_MODEL = 'qwen3.8-max';
53
+ /** 千问上能用的几个(Token Plan 与百炼按量都有);运行时模板的 -m 选其中一个 */
54
+ const MODELS = [
55
+ { id: 'qwen3.7-plus', capabilities: { reasoning: toggle }, generationConfig: { contextWindowSize: 1_000_000, modalities: { image: true } } },
56
+ { id: 'qwen3.7-max', capabilities: { reasoning: toggle }, generationConfig: { contextWindowSize: 1_000_000 } },
57
+ { id: 'qwen3.8-flash', capabilities: { reasoning: tiers }, generationConfig: { contextWindowSize: 1_000_000, modalities: { image: true, video: true } } },
58
+ { id: 'qwen3.8-max', capabilities: { reasoning: tiers }, generationConfig: { contextWindowSize: 1_000_000, modalities: { image: true, video: true } } },
59
+ ];
60
+ /** 隔离的家里那份 settings.json(没有 key,只写环境变量名) */
61
+ export function qwenHomeSettings() {
62
+ return {
63
+ $version: 4,
64
+ security: { auth: { selectedType: 'openai' } },
65
+ model: { name: QWEN_DEFAULT_MODEL },
66
+ modelProviders: { openai: MODELS.map((m) => ({ ...m, baseUrl: `\${${BASE_ENV}}`, envKey: KEY_ENV })) },
67
+ memory: { enableManagedAutoMemory: false, enableManagedAutoDream: false },
68
+ privacy: { usageStatisticsEnabled: false },
69
+ telemetry: { enabled: false },
70
+ general: { disableAutoUpdate: true, disableUpdateNag: true, preventSystemSleep: false },
71
+ };
72
+ }
73
+ /** 这几份机器文件:绝对路径 → 内容 */
74
+ export function qwenFiles(root) {
75
+ const files = {
76
+ // 整个目录不进 git:会话记录(runtime/)是对话原文,同 conversations/ 只留本机;其余都是这里每次重新生成的
77
+ [join(root, QWEN_DIR, '.gitignore')]: '# qwen 的隔离家目录与会话记录(cotutor 生成,对话原文只留本机)\n*\n',
78
+ [join(homeOf(root), 'settings.json')]: `${JSON.stringify(qwenHomeSettings(), null, 2)}\n`,
79
+ };
80
+ for (const level of new Set(Object.values(EFFORT)))
81
+ files[effortFile(root, level)] = `${JSON.stringify({ $version: 4, model: { reasoningEffort: level } }, null, 2)}\n`;
82
+ return files;
83
+ }
84
+ /** 别处的设置会盖掉家里选的模型与供应商,起进程时去掉 */
85
+ const FOREIGN = ['OPENAI_API_KEY', 'OPENAI_BASE_URL', 'OPENAI_MODEL', 'QWEN_MODEL'];
86
+ export const qwen = {
87
+ name: 'qwen',
88
+ parse: parseStreamJson,
89
+ stdinMessage: streamJsonUserMessage,
90
+ // qwen 的带工具只有只读一档(read / on 一样):shell 与写本来就不给
91
+ toolList: (set) => (set !== 'off' ? READ_TOOLS.join(',') : ''),
92
+ // --core-tools 是白名单,不带时也要给一个(给空等于不限),再把它排除掉;非核心工具不归 --core-tools 管,总要排除。
93
+ // 只读那轮把 workspace 根与 vault 加进可读范围:会话 cwd 是老师目录,作业照片(captures/)与教材在它外面,读外面要征得同意——
94
+ // 消息走 stdin 时它就停在那儿等,一直等到 --max-wall-time(2026-10-09 真跑,开了思考的那次读照片挂住)
95
+ toolArgs: (set, { readDirs }) => set !== 'off'
96
+ ? ['--core-tools', READ_TOOLS.join(','), '--exclude-tools', NON_CORE.join(','), ...readDirs.flatMap((d) => ['--include-directories', d])]
97
+ : ['--core-tools', 'read_file', '--exclude-tools', ['read_file', ...NON_CORE].join(',')],
98
+ toolKind: (name) => KINDS[name] ?? 'other',
99
+ expectedTools: (set) => (set !== 'off' ? READ_TOOLS : []),
100
+ planEnv: ({ root, effort, tools }) => root ? { QWEN_HOME: homeOf(root), QWEN_RUNTIME_DIR: join(root, QWEN_DIR, 'runtime'), QWEN_CODE_SYSTEM_SETTINGS_PATH: effortFile(root, levelOf(effort, tools)) } : {},
101
+ async prepare(root) {
102
+ for (const [file, text] of Object.entries(qwenFiles(root))) {
103
+ if ((await readFile(file, 'utf8').catch(() => null)) === text)
104
+ continue;
105
+ await mkdir(dirname(file), { recursive: true });
106
+ await writeFile(file, text);
107
+ }
108
+ },
109
+ env: (env) => {
110
+ const out = { ...env, QWEN_USAGE_STATISTICS_ENABLED: 'false', QWEN_CODE_MODELS_DEV: 'off', QWEN_CODE_SUPPRESS_YOLO_WARNING: '1' };
111
+ for (const k of FOREIGN)
112
+ delete out[k];
113
+ const line = qianwenLine(QWEN_DEFAULT_MODEL, qianwenKeys(out));
114
+ if (line) {
115
+ out[BASE_ENV] = compatibleBase(line.host);
116
+ out[KEY_ENV] = line.key;
117
+ }
118
+ return out;
119
+ },
120
+ check: ({ version, env }) => {
121
+ const v = /(\d+)\.(\d+)\.(\d+)/.exec(version);
122
+ const old = !v || Number(v[1]) === 0 && Number(v[2]) < 25;
123
+ const line = qianwenLine(QWEN_DEFAULT_MODEL, qianwenKeys(env));
124
+ return [
125
+ { name: 'version', ok: !old, detail: old ? `qwen ${version || '?'}:要 0.25 起(关工具的旗标、隔离的家、思考量配置都按 0.25 定的)` : `qwen ${version}`, fix: old ? 'qwen update(或 brew upgrade qwen-code)' : undefined },
126
+ line
127
+ ? { name: 'key', ok: true, detail: line.plan ? '走千问 Token Plan(QWENCLOUD_TOKEN_PLAN_API_KEY)' : '走百炼按量(DASHSCOPE_API_KEY,或本机 qwen / voxtell 的配置)' }
128
+ : { name: 'key', ok: false, detail: '千问的 key 一把都拿不到:老师进程起来就会 401', fix: '在起 serve 的 shell 里 export QWENCLOUD_TOKEN_PLAN_API_KEY(Token Plan,sk-sp-)或 DASHSCOPE_API_KEY(百炼按量)' },
129
+ ];
130
+ },
131
+ runtimes: () => {
132
+ // 消息走 stdin(预热能用;数组旗标 --core-tools 之类会吞掉跟在后面的消息,不进 argv 正好避开);-m 选模型(家里那份 settings.json 列着的);
133
+ // {systemBody} = 老师正文 + 板书写法,整份换掉 qwen 自己的系统提示;{toolArgs} 由适配器展开;--approval-mode default:shell、写、读 workspace 外都拒
134
+ // qwen-flash 只差模型(2026-10-13 英语老师出厂走它:Token Plan 上便宜、开口 2.5–4 秒)
135
+ const of = (model) => {
136
+ const flags = ['-m', model, '--system-prompt', '{systemBody}', '--input-format', 'stream-json', '--output-format', 'stream-json', '--include-partial-messages', '--approval-mode', 'default', '{toolArgs}', '--max-wall-time', '10m'];
137
+ return { stdin: 'stream-json', run: ['qwen', ...flags], resume: ['qwen', '--resume', '{session}', ...flags] };
138
+ };
139
+ return { qwen: of(QWEN_DEFAULT_MODEL), 'qwen-flash': of('qwen3.8-flash') };
140
+ },
141
+ };
@@ -0,0 +1,59 @@
1
+ import { streamJsonUserMessage } from './stream-json.ts';
2
+ import type { ToolSet } from './types.ts';
3
+ import { type ConversationIndex, type CotutorConfig, type Policy, type Runtime } from '../../schema/index.ts';
4
+ export interface RunPlan {
5
+ /** 运行时名(runtimes 里的键) */
6
+ runtime: string;
7
+ /** 适配器名(src/brain/cli/;认不出的是 stream-json) */
8
+ cli: string;
9
+ /** 这轮带不带工具(模板管不了工具的运行时也照记,只是没用上) */
10
+ tools: ToolSet;
11
+ /** 完整命令行,argv[0] 是可执行文件 */
12
+ argv: string[];
13
+ /** 这次是 resume 还是新开 */
14
+ resume: boolean;
15
+ /** resume 的会话 id */
16
+ session: string | null;
17
+ /** 运行时 stdin: "stream-json":要写进 stdin 的那一行(用户消息,带换行);消息不在 argv 里 */
18
+ stdin?: string;
19
+ /** 适配器按这轮的计划定的环境变量(qwen 的思考量配置之类);和 argv 一起进预热的比对 */
20
+ env: Record<string, string>;
21
+ }
22
+ export declare class RuntimeError extends Error {
23
+ }
24
+ export declare function getRuntime(config: CotutorConfig, name?: string): {
25
+ name: string;
26
+ runtime: Runtime;
27
+ };
28
+ /** 模板里有没有用到某个占位符(决定要不要去读老师正文)。API 运行时没有模板:系统提示由应用给,算用了 {systemBody} */
29
+ export declare function runtimeUses(runtime: Runtime, placeholder: string): boolean;
30
+ /**
31
+ * 这个运行时把板书写法预载进系统提示了吗:模板用了 {boardFile} / {systemBody},或者(2026-09-19 头一版)写死了 cotutor-board/SKILL.md 的路径。
32
+ * 没有 → 应用在话题第一条注入 <cotutor-board>。
33
+ */
34
+ export declare function boardPreloaded(runtime: Runtime): boolean;
35
+ export declare function planRun(config: CotutorConfig, index: Pick<ConversationIndex, 'session'>, vars: {
36
+ agent: string;
37
+ prompt: string;
38
+ agentBody?: string;
39
+ systemBody?: string;
40
+ boardFile?: string;
41
+ runtime?: string;
42
+ effort?: Policy['effort'];
43
+ tools?: ToolSet;
44
+ root?: string;
45
+ readDirs?: readonly string[];
46
+ }): RunPlan;
47
+ /** stream-json 输入的一条用户消息(Qwen 的 `--input-format stream-json` 一行一条;别的 CLI 看它的适配器) */
48
+ export declare const stdinMessage: typeof streamJsonUserMessage;
49
+ /**
50
+ * 断流后接着跑的那条消息(policy.stall):resume 同一个会话发给老师。被杀的那段回复只流到了 stdout,没进会话,
51
+ * 所以断在半截的正文(open)原样递回去,让它从断处接着写;应用把 open 拼在这次的收尾正文前面。
52
+ * open 为空 = 这一段一个字没出来,已经做完的工具调用与整段都在会话里,接着把这一轮做完。
53
+ */
54
+ export declare function stallPrompt(open: string): string;
55
+ /**
56
+ * 老师把工具调用写成了正文、停在那里等结果(这轮没给它那个工具,qwen 照自己的格式写出来;板书解析器把那块剥掉了):
57
+ * resume 同一个会话,告诉它不会有结果,接着直接回孩子。那块前面写的话已经进了会话,应用拼在这次的前面
58
+ */
59
+ export declare function toolLeakPrompt(): string;
@@ -0,0 +1,71 @@
1
+ /**
2
+ * 一次运行的命令规划(纯函数):按运行时选 run 还是 resume、填占位符、定 cwd 相对路径。
3
+ * 规则:当天索引里已有会话**且**是同一运行时跑出来的 → resume;否则新开(跨天索引本来就是新的,零点后第一条自然不带 --resume;
4
+ * 换了运行时也新开——不同运行时的会话不混用)。{agentBody} 只给模板里真用到它的运行时读老师正文。
5
+ */
6
+ import { adapterFor, fillArgs } from "./adapters.js";
7
+ import { streamJsonUserMessage } from "./stream-json.js";
8
+ import { POLICY_DEFAULTS, isApiRuntime } from "../../schema/index.js";
9
+ export class RuntimeError extends Error {
10
+ }
11
+ export function getRuntime(config, name) {
12
+ const n = name ?? config.runtimes.default;
13
+ const p = config.runtimes[n];
14
+ if (n === 'default' || !p || typeof p === 'string') {
15
+ const known = Object.keys(config.runtimes).filter((k) => k !== 'default');
16
+ throw new RuntimeError(`运行时 "${n}" 不存在;cotutor.json 的 runtimes 里有:${known.join('、')}`);
17
+ }
18
+ return { name: n, runtime: p };
19
+ }
20
+ /** 模板里有没有用到某个占位符(决定要不要去读老师正文)。API 运行时没有模板:系统提示由应用给,算用了 {systemBody} */
21
+ export function runtimeUses(runtime, placeholder) {
22
+ if (isApiRuntime(runtime))
23
+ return placeholder === '{systemBody}';
24
+ return [...runtime.run, ...runtime.resume].some((a) => a.includes(placeholder));
25
+ }
26
+ /**
27
+ * 这个运行时把板书写法预载进系统提示了吗:模板用了 {boardFile} / {systemBody},或者(2026-09-19 头一版)写死了 cotutor-board/SKILL.md 的路径。
28
+ * 没有 → 应用在话题第一条注入 <cotutor-board>。
29
+ */
30
+ export function boardPreloaded(runtime) {
31
+ return runtimeUses(runtime, '{boardFile}') || runtimeUses(runtime, '{systemBody}') || runtimeUses(runtime, 'cotutor-board/SKILL.md');
32
+ }
33
+ export function planRun(config, index, vars) {
34
+ const { name, runtime } = getRuntime(config, vars.runtime);
35
+ if (isApiRuntime(runtime))
36
+ throw new RuntimeError(`运行时 "${name}" 是 API 运行时,不起命令行(src/brain/api.ts)`);
37
+ const adapter = adapterFor(runtime);
38
+ const session = index.session && index.session.runtime === name ? index.session.id : null;
39
+ const template = session ? runtime.resume : runtime.run;
40
+ const effort = vars.effort ?? POLICY_DEFAULTS.effort;
41
+ return {
42
+ runtime: name,
43
+ cli: adapter.name,
44
+ tools: vars.tools ?? 'on',
45
+ argv: fillArgs(adapter, template, { agent: vars.agent, prompt: vars.prompt, session: session ?? undefined, agentBody: vars.agentBody, systemBody: vars.systemBody, boardFile: vars.boardFile, effort: vars.effort, tools: vars.tools, readDirs: vars.readDirs }),
46
+ resume: session !== null,
47
+ session,
48
+ ...(runtime.stdin ? { stdin: adapter.stdinMessage(vars.prompt) } : {}),
49
+ env: adapter.planEnv?.({ root: vars.root, effort, tools: vars.tools ?? 'on' }) ?? {},
50
+ };
51
+ }
52
+ /** stream-json 输入的一条用户消息(Qwen 的 `--input-format stream-json` 一行一条;别的 CLI 看它的适配器) */
53
+ export const stdinMessage = streamJsonUserMessage;
54
+ /**
55
+ * 断流后接着跑的那条消息(policy.stall):resume 同一个会话发给老师。被杀的那段回复只流到了 stdout,没进会话,
56
+ * 所以断在半截的正文(open)原样递回去,让它从断处接着写;应用把 open 拼在这次的收尾正文前面。
57
+ * open 为空 = 这一段一个字没出来,已经做完的工具调用与整段都在会话里,接着把这一轮做完。
58
+ */
59
+ export function stallPrompt(open) {
60
+ const rule = '不道歉,不提断了,不重复前面的。';
61
+ return open
62
+ ? `(应用注)你刚才那段回复传到一半网络断了。孩子那边已经看到、听到的就是下面 <<< 与 >>> 之间这些:\n<<<\n${open}\n>>>\n从断的地方直接接着写,字要接得上;${rule}`
63
+ : `(应用注)你刚才那段回复网络断了,一个字没传出来。已经做完的工具调用和写完的段都还在,接着把这一轮做完;${rule}`;
64
+ }
65
+ /**
66
+ * 老师把工具调用写成了正文、停在那里等结果(这轮没给它那个工具,qwen 照自己的格式写出来;板书解析器把那块剥掉了):
67
+ * resume 同一个会话,告诉它不会有结果,接着直接回孩子。那块前面写的话已经进了会话,应用拼在这次的前面
68
+ */
69
+ export function toolLeakPrompt() {
70
+ return '(应用注)你刚才写的工具调用没有执行,孩子也看不到。这一轮不用工具,接着直接回孩子;不提工具,不道歉,不重复前面的。';
71
+ }
@@ -0,0 +1,35 @@
1
+ import { type RunPlan } from './run-plan.ts';
2
+ import type { CliRuntime, CotutorConfig, Policy } from '../../schema/index.ts';
3
+ import type { BrainExecutor, BrainHooks, BrainRequest, BrainRun, WarmKey } from '../index.ts';
4
+ import { type Slot } from './warm.ts';
5
+ export declare class CliBrain implements BrainExecutor {
6
+ private readonly spares;
7
+ private readonly workspace;
8
+ /** 起子进程用的环境(测试注入);缺省 process.env */
9
+ private readonly env;
10
+ constructor(opts: {
11
+ workspace: () => {
12
+ config: CotutorConfig;
13
+ root: string;
14
+ };
15
+ env?: NodeJS.ProcessEnv;
16
+ warmIdleMs?: number;
17
+ });
18
+ plan(req: BrainRequest): RunPlan;
19
+ prepare(plan: RunPlan): Promise<void>;
20
+ canWarm(runtime: CliRuntime): boolean;
21
+ warm(tutor: string, slot: Slot, plan: RunPlan, key: WarmKey): void;
22
+ warmed(tutor: string, slot?: Slot): boolean;
23
+ dropWarm(tutor: string, slot?: Slot): void;
24
+ close(): void;
25
+ private processEnv;
26
+ start(req: BrainRequest, plan: RunPlan, ctx: {
27
+ tutor: string;
28
+ key: WarmKey;
29
+ files: {
30
+ log: string;
31
+ err: string;
32
+ };
33
+ stall: Policy['stall'];
34
+ }, hooks: BrainHooks): BrainRun;
35
+ }
@@ -0,0 +1,256 @@
1
+ /**
2
+ * 脑执行的 CLI 实现:按 cotutor.json 的运行时起老师进程(qwen 之类,读输出、关工具、环境都在同目录的适配器 adapters.ts 与各家的文件),
3
+ * stream-json 落 <日期>.<job>.log、stderr 落 .err.log;每行读成统一事件,一行只解析一次,同一批事件给拼正文、工具、会话 id 用。
4
+ * - 预热(./warm.ts):消息走 stdin 的运行时,下一轮的进程提前起好,对得上就接过来
5
+ * - 断流看门狗:stall.ms 没吐一个字节、也没有工具在跑 → 杀掉,resume 同一个会话接着写(最多 stall.retries 次)。
6
+ * CLI 自己的断流重试可能要等很久(2026-09-21 真跑一轮连断两次,等了 6 分钟)
7
+ * - 回复停在写成正文的工具调用上(这轮没给它那个工具,qwen 照自己的格式写出来):resume 同一个会话告诉它不会有结果、接着回孩子,只一次
8
+ * - 收尾:从 .log 读整轮转录;断流接着跑的,断在半截的那段拼回最后一段前面
9
+ */
10
+ import { spawn } from 'node:child_process';
11
+ import { closeSync, createWriteStream, openSync, writeSync } from 'node:fs';
12
+ import { appendFile, mkdir, readFile } from 'node:fs/promises';
13
+ import { basename } from 'node:path';
14
+ import { parserOf, prepareCli, processEnv, toolsOf, unexpectedTools } from "./adapters.js";
15
+ import { planRun, stallPrompt, toolLeakPrompt } from "./run-plan.js";
16
+ import { createPartialReader } from "../stream.js";
17
+ import { parseTranscript, toolCalls, toolSummary } from "../transcript.js";
18
+ import { WarmPool } from "./warm.js";
19
+ const cliName = (p) => p.argv[0].slice(p.argv[0].lastIndexOf('/') + 1);
20
+ export class CliBrain {
21
+ spares;
22
+ workspace;
23
+ /** 起子进程用的环境(测试注入);缺省 process.env */
24
+ env;
25
+ constructor(opts) {
26
+ this.workspace = opts.workspace;
27
+ this.env = opts.env;
28
+ this.spares = new WarmPool({ idleMs: opts.warmIdleMs });
29
+ }
30
+ plan(req) {
31
+ const { config, root } = this.workspace();
32
+ return planRun(config, { session: req.session }, { agent: req.agent, prompt: req.prompt, agentBody: req.agentBody, systemBody: req.systemBody, boardFile: req.boardFile, runtime: req.runtime, effort: req.effort, tools: req.tools, root, readDirs: req.readDirs });
33
+ }
34
+ prepare(plan) {
35
+ return prepareCli(plan.cli, this.workspace().root).catch(() => { });
36
+ }
37
+ canWarm(runtime) {
38
+ return Boolean(runtime.stdin);
39
+ }
40
+ warm(tutor, slot, plan, key) {
41
+ this.spares.warm(tutor, slot, { argv: plan.argv, env: plan.env, ...key }, this.processEnv(plan));
42
+ }
43
+ warmed(tutor, slot) {
44
+ return this.spares.has(tutor, slot);
45
+ }
46
+ dropWarm(tutor, slot) {
47
+ this.spares.drop(tutor, slot);
48
+ }
49
+ close() {
50
+ this.spares.dropAll();
51
+ }
52
+ processEnv(p) {
53
+ return processEnv(p, { ...(this.env ?? process.env), COTUTOR_WORKSPACE: this.workspace().root });
54
+ }
55
+ start(req, plan, ctx, hooks) {
56
+ // 预热的进程:resume 的接那个位置(对得上 = 这个话题从它起来之后没人写过),新开的接 fresh;对不上(或这轮不走 stdin)就杀掉
57
+ const spare = this.spares.claim(ctx.tutor, plan.resume ? 'resume' : 'fresh', { argv: plan.argv, env: plan.env, ...ctx.key });
58
+ // 断流接着跑:carried = 被杀那次已经拼出的正文(接着跑的那次换新读取器,正文 = carried + 新的);
59
+ // open = 断在半截、没进会话的那段(递回给老师,收尾时拼在最后一段前面)
60
+ let reader = createPartialReader();
61
+ let carried = '';
62
+ let open = '';
63
+ const liveText = () => { const t = reader.text(); return !carried ? t : !t ? carried : open ? carried + t : `${carried}\n\n${t}`; };
64
+ const resumePlan = (id, prompt) => this.plan({ ...req, runtime: plan.runtime, session: { id, runtime: plan.runtime }, prompt });
65
+ const stall = ctx.stall;
66
+ const files = ctx.files;
67
+ const cwd = ctx.key.cwd;
68
+ const go = async () => {
69
+ await mkdir(cwd, { recursive: true });
70
+ const out = createWriteStream(files.log);
71
+ const err = openSync(files.err, 'w');
72
+ hooks.onStart({ cli: cliName(plan), runtime: plan.runtime, resume: plan.resume, ...(spare ? { warmBornAt: spare.bornAt } : {}) });
73
+ // 工具调用回报一条(子代理的标 sub);顺手记哪些顶层工具还没回结果:工具在跑时进程不吐字是正常的,断流看门狗不算这段
74
+ const parse = parserOf(plan.cli);
75
+ let lineBuf = '';
76
+ const toolsRunning = new Set();
77
+ // 消息走 stdin 的运行时:看到收尾就关 stdin,进程自己退(每次 runOnce 换一个)
78
+ let onResult = null;
79
+ // 进程起来报的工具表里不该有的(适配器核对;不带工具那轮却有工具 = 关工具的旗标失效了,CLI 升版本最先坏的地方)
80
+ let unexpected = [];
81
+ let session = plan.session;
82
+ // 新会话要等模型开始回了(开始回复、吐字、在想、整条回复)才在盘上、才 resume 得了
83
+ // (2026-09-22 真跑:init 吐了会话 id 就被杀,resume 报 No conversation found;吐过三个字再杀,盘上有这条用户消息)
84
+ let persisted = plan.resume;
85
+ let stalls = 0;
86
+ // warm:预热好的进程(只给第一次;断流接着跑的那次照旧冷起)
87
+ const runOnce = (p, warm = null) => new Promise((resolveExit) => {
88
+ // 被杀的那次没收完的半行不要了
89
+ lineBuf = '';
90
+ const child = warm?.child ?? spawn(p.argv[0], p.argv.slice(1), {
91
+ cwd,
92
+ env: this.processEnv(p),
93
+ stdio: [p.stdin ? 'pipe' : 'ignore', 'pipe', err],
94
+ });
95
+ if (warm) {
96
+ // 预热的进程 stderr 是管道(起它时还没有这轮的 err.log):攒下的和之后的都写进来(池子交出来时暂停着,这里 resume)
97
+ const toErr = (c) => { try {
98
+ writeSync(err, c);
99
+ }
100
+ catch { /* err.log 已关 */ } };
101
+ warm.stderr.forEach(toErr);
102
+ child.stderr?.on('data', toErr);
103
+ child.stderr?.resume();
104
+ }
105
+ if (p.stdin) {
106
+ child.stdin?.on('error', () => { });
107
+ child.stdin?.write(p.stdin);
108
+ onResult = () => { onResult = null; child.stdin?.end(); };
109
+ }
110
+ else
111
+ onResult = null;
112
+ let stalled = false;
113
+ let idle = null;
114
+ let lastByte = Date.now();
115
+ const arm = () => {
116
+ if (idle)
117
+ clearTimeout(idle);
118
+ if (!stall.ms)
119
+ return;
120
+ idle = setTimeout(() => {
121
+ idle = null;
122
+ if (toolsRunning.size)
123
+ return arm();
124
+ stalled = true;
125
+ child.kill('SIGTERM');
126
+ setTimeout(() => { if (child.exitCode === null && child.signalCode === null)
127
+ child.kill('SIGKILL'); }, 2000).unref();
128
+ }, stall.ms);
129
+ };
130
+ arm();
131
+ child.stdout?.on('data', (chunk) => {
132
+ lastByte = Date.now();
133
+ arm();
134
+ out.write(chunk);
135
+ lineBuf += chunk.toString('utf8');
136
+ const lines = lineBuf.split('\n');
137
+ lineBuf = lines.pop() ?? '';
138
+ let changed = false;
139
+ for (const line of lines) {
140
+ const events = parse(line);
141
+ for (const e of events) {
142
+ if (e.kind === 'session') {
143
+ if (!session)
144
+ session = e.id;
145
+ }
146
+ else if (e.kind === 'init')
147
+ unexpected = unexpectedTools(plan.cli, plan.tools, e.tools);
148
+ else if (e.kind === 'result')
149
+ onResult?.();
150
+ else if (e.kind === 'results') {
151
+ if (!e.sub)
152
+ for (const r of e.results)
153
+ toolsRunning.delete(r.id);
154
+ }
155
+ else {
156
+ if (e.kind === 'start' || e.kind === 'delta' || e.kind === 'thinking' || e.kind === 'assistant')
157
+ persisted = true;
158
+ if (e.kind === 'assistant')
159
+ for (const tool of toolsOf(e.parts)) {
160
+ if (!e.sub && tool.id)
161
+ toolsRunning.add(tool.id);
162
+ hooks.onTool({ name: toolSummary(tool.name, tool.input), sub: e.sub });
163
+ }
164
+ }
165
+ }
166
+ if (reader.apply(events))
167
+ changed = true;
168
+ }
169
+ if (changed)
170
+ hooks.onText();
171
+ });
172
+ const done = (r) => {
173
+ if (idle)
174
+ clearTimeout(idle);
175
+ resolveExit({ ...r, ...(stalled ? { stalled: true } : {}) });
176
+ };
177
+ child.once('error', (e) => done({ code: null, spawnError: e }));
178
+ child.once('close', (code) => { if (stalled)
179
+ void appendFile(files.err, `cotutor: ${Date.now() - lastByte}ms 没有输出,当断流杀掉\n`).catch(() => { }); done({ code }); });
180
+ if (warm) {
181
+ // 开口前吐的按顺序补喂,再放开暂停;接手之前就退了的,close 已经错过,直接收尾
182
+ for (const c of warm.stdout)
183
+ child.stdout?.emit('data', c);
184
+ child.stdout?.resume();
185
+ if (warm.closed())
186
+ done({ code: child.exitCode });
187
+ }
188
+ });
189
+ let exit = await runOnce(plan, spare);
190
+ while (exit.stalled) {
191
+ stalls++;
192
+ if (persisted)
193
+ open += reader.current();
194
+ else {
195
+ session = plan.session;
196
+ open = '';
197
+ }
198
+ const retry = stalls <= stall.retries ? stalls : 0;
199
+ hooks.onStall({ idleMs: stall.ms, retry, kept: Array.from(open).length });
200
+ if (!retry)
201
+ break;
202
+ carried = persisted ? liveText() : '';
203
+ reader = createPartialReader();
204
+ toolsRunning.clear();
205
+ // 会话还没落盘(进程起来就卡住、一条整的回复都没有):原样从头再起一次;落了盘就 resume 接着写
206
+ const next = persisted && session ? resumePlan(session, stallPrompt(open)) : plan;
207
+ hooks.onStart({ cli: cliName(next), runtime: next.runtime, resume: next.resume });
208
+ exit = await runOnce(next);
209
+ }
210
+ // 回复停在写成正文的工具调用上(板书解析器已剥掉,孩子没看到):老师在等结果,resume 同一个会话告诉它不会有结果、接着回孩子,只一次。
211
+ // 这次的正文接在前面那段后面
212
+ let leaked = '';
213
+ if (!exit.stalled && exit.code === 0 && session && req.stuckOnTool?.(liveText())) {
214
+ leaked = liveText();
215
+ carried = leaked;
216
+ open = '';
217
+ reader = createPartialReader();
218
+ toolsRunning.clear();
219
+ const next = resumePlan(session, toolLeakPrompt());
220
+ hooks.onStart({ cli: cliName(next), runtime: next.runtime, resume: next.resume });
221
+ exit = await runOnce(next);
222
+ }
223
+ hooks.onExit(Date.now());
224
+ await new Promise((r) => out.end(r));
225
+ closeSync(err);
226
+ if (exit.spawnError)
227
+ await appendFile(files.err, `cotutor: 起不来 ${plan.argv[0]}:${exit.spawnError.message}\n`);
228
+ const logText = await readFile(files.log, 'utf8').catch(() => '');
229
+ const transcript = parseTranscript(logText, parse);
230
+ // 断流接着跑的:断在半截的那段没进会话、也不在最后的 result 里,拼回最后一段前面(老师是从断处接着写的)
231
+ // (result 的正文被 trim 过,断在句末 / 围栏上的补回换行,免得两句粘成一行)
232
+ if (open && transcript.final?.text)
233
+ transcript.final.text = open + (/[。!!??;;`\n]\s*$/.test(open) ? '\n' : '') + transcript.final.text;
234
+ if (leaked && transcript.final?.text)
235
+ transcript.final.text = `${leaked}\n\n${transcript.final.text}`;
236
+ if (exit.stalled && !transcript.final)
237
+ transcript.final = { text: null, ok: false, reason: `stalled:${stalls} 次断流(每次 ${stall.ms}ms 没输出),接着跑的次数用完了` };
238
+ // 这轮用了哪些工具、读了什么:从 .log 抽出来物化(家长端「看原文」一站、cotutor show)
239
+ const tools = toolCalls(logText, parse).slice(0, 200);
240
+ if (!transcript.final) {
241
+ // 进程退了但没有 result 事件:起不来、被杀、或 CLI 崩了;标 error,原因指向 err.log
242
+ transcript.final = { text: null, ok: false, reason: exit.spawnError ? `spawn:${exit.spawnError.message}` : `exit:${exit.code ?? 'signal'}` };
243
+ transcript.items.push({ kind: 'done', text: `本轮没有收尾(${transcript.final.reason}),看 ${basename(files.err)}` });
244
+ }
245
+ const warnings = [];
246
+ if (unexpected.length)
247
+ warnings.push(`${plan.cli} 起来时带着这轮不该有的工具:${unexpected.join('、')}(${plan.tools === 'off' ? '这轮应该一个工具都不带' : '这轮只该带只读的几样'});关工具的旗标可能随 CLI 升级失效了,看 src/brain/cli/${plan.cli}.ts`);
248
+ if (leaked)
249
+ warnings.push('老师把工具调用写成了正文、停在那里等结果(板上没出、嘴没念),应用 resume 同一个会话叫它直接回孩子');
250
+ if (stalls)
251
+ warnings.push(`API 流断了 ${stalls} 次(每次 ${stall.ms / 1000} 秒没动静),应用杀掉进程、resume 会话接着写的${exit.stalled ? ';次数用完还断,这轮没收尾' : ''}`);
252
+ return { transcript: { ...transcript, final: transcript.final }, tools, warnings };
253
+ };
254
+ return { warm: Boolean(spare), text: liveText, done: go() };
255
+ }
256
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Qwen Code 的 stream-json(`--output-format stream-json`,一行一个 JSON)读成统一事件。
3
+ * 同时保留历史日志的费用字段解析,让已有对话仍能查看。Qwen Code 0.25 的输出:
4
+ * - `{"type":"system","subtype":"init","session_id","tools":[…]}`(qwen 的 json 模式叫 session_start)
5
+ * - `{"type":"stream_event","event":{…}}`:`--include-partial-messages` 才有;message_start 开新的一条,content_block_delta 的 text_delta 是正文、thinking_delta 是在想
6
+ * - `{"type":"assistant","message":{"id","content":[text / tool_use 块],"usage"}}`:一条整的回复;usage 是这一次请求自己的
7
+ * - `{"type":"user","message":{"content":[tool_result 块]}}`:工具结果
8
+ * - `{"type":"result","subtype","is_error","result","num_turns","usage"}`:收尾;记账只认 usage 的 token(total_cost_usd 有也不读)。
9
+ * qwen 续会话时这里的 usage 是整个会话的累计(2026-10-30 在 ray 上量出来的:续了 28 轮的话题,索引里加起来 15.6M,实际约 1.2M),
10
+ * 所以 assistant 那几行的 usage 也读出来,parseTranscript 按它们加总
11
+ * parent_tool_use_id 非空的是子代理的。
12
+ */
13
+ import type { CliEvent } from './types.ts';
14
+ /** 结果块的文字:字符串原样,块数组拼各块的 text */
15
+ export declare const blockText: (c: unknown) => string;
16
+ export declare function parseStreamJson(line: string): CliEvent[];
17
+ /** stream-json 输入的一条用户消息(`--input-format stream-json` 一行一条) */
18
+ export declare function streamJsonUserMessage(prompt: string): string;