cotutor 0.2.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.
- package/LICENSE +247 -21
- package/NOTICE +42 -0
- package/README.md +92 -20
- package/bin/cotutor.js +4 -4
- package/cards/canvas/card.css +8 -0
- package/cards/canvas/card.md +68 -0
- package/cards/choice/card.css +18 -0
- package/cards/choice/card.md +55 -0
- package/cards/code/card.css +5 -0
- package/cards/code/card.md +46 -0
- package/cards/dictation/card.css +10 -0
- package/cards/dictation/card.md +97 -0
- package/cards/image/card.css +10 -0
- package/cards/image/card.md +52 -0
- package/cards/lecture/card.css +9 -0
- package/cards/lecture/card.md +69 -0
- package/cards/paint/card.css +20 -0
- package/cards/paint/card.md +77 -0
- package/cards/photo/card.css +15 -0
- package/cards/photo/card.md +61 -0
- package/cards/read/card.css +6 -0
- package/cards/read/card.md +51 -0
- package/cards/text/card.css +3 -0
- package/cards/text/card.md +69 -0
- package/cards/tianzige/card.css +17 -0
- package/cards/tianzige/card.md +78 -0
- package/cards/tutor/card.css +66 -0
- package/cards/tutor/card.md +148 -0
- package/cards/word/card.css +24 -0
- package/cards/word/card.md +91 -0
- package/cards//346/235/277/344/271/246/346/200/216/344/271/210/345/206/231.md +159 -0
- package/dist/app/activity-eval-rules.d.ts +62 -0
- package/dist/app/activity-eval-rules.js +276 -0
- package/dist/app/activity-eval.d.ts +65 -0
- package/dist/app/activity-eval.js +158 -0
- package/dist/app/build.d.ts +11 -0
- package/dist/app/build.js +45 -0
- package/dist/app/cli/activities.d.ts +63 -0
- package/dist/app/cli/activities.js +158 -0
- package/dist/{cli → app/cli}/cert.js +3 -3
- package/dist/app/cli/chalk/bake.d.ts +10 -0
- package/dist/app/cli/chalk/bake.js +58 -0
- package/dist/app/cli/chalk/browser.d.ts +16 -0
- package/dist/app/cli/chalk/browser.js +142 -0
- package/dist/app/cli/chalk/build.d.ts +14 -0
- package/dist/app/cli/chalk/build.js +100 -0
- package/dist/app/cli/chalk/dub.d.ts +51 -0
- package/dist/app/cli/chalk/dub.js +106 -0
- package/dist/app/cli/chalk/load-scene.d.ts +34 -0
- package/dist/app/cli/chalk/load-scene.js +117 -0
- package/dist/app/cli/chalk/main.d.ts +7 -0
- package/dist/app/cli/chalk/main.js +198 -0
- package/dist/app/cli/chalk/serve.d.ts +4 -0
- package/dist/app/cli/chalk/serve.js +28 -0
- package/dist/app/cli/chalk/snap.d.ts +65 -0
- package/dist/app/cli/chalk/snap.js +103 -0
- package/dist/app/cli/chalk/typecheck.d.ts +7 -0
- package/dist/app/cli/chalk/typecheck.js +51 -0
- package/dist/{cli → app/cli}/doctor.d.ts +4 -3
- package/dist/app/cli/doctor.js +617 -0
- package/dist/app/cli/grades.d.ts +14 -0
- package/dist/app/cli/grades.js +44 -0
- package/dist/{cli → app/cli}/init.d.ts +3 -1
- package/dist/app/cli/init.js +155 -0
- package/dist/app/cli/main.js +715 -0
- package/dist/app/cli/migrate.d.ts +58 -0
- package/dist/app/cli/migrate.js +253 -0
- package/dist/{cli → app/cli}/serve.d.ts +12 -5
- package/dist/app/cli/serve.js +98 -0
- package/dist/app/cli/shipped.d.ts +30 -0
- package/dist/app/cli/shipped.js +47 -0
- package/dist/app/cli/skeleton.d.ts +38 -0
- package/dist/app/cli/skeleton.js +161 -0
- package/dist/app/cli/skills.d.ts +55 -0
- package/dist/app/cli/skills.js +189 -0
- package/dist/app/cli/themes.d.ts +52 -0
- package/dist/app/cli/themes.js +148 -0
- package/dist/{cli → app/cli}/tutors.d.ts +15 -26
- package/dist/{cli → app/cli}/tutors.js +86 -110
- package/dist/app/cli/usage.d.ts +2 -0
- package/dist/app/cli/usage.js +30 -0
- package/dist/app/dictation/recognize.d.ts +18 -0
- package/dist/app/dictation/recognize.js +6 -0
- package/dist/app/dictation/route.d.ts +52 -0
- package/dist/app/dictation/route.js +510 -0
- package/dist/app/diff.d.ts +11 -0
- package/dist/app/diff.js +71 -0
- package/dist/app/http/access.d.ts +62 -0
- package/dist/app/http/access.js +180 -0
- package/dist/app/http/app.d.ts +246 -0
- package/dist/app/http/app.js +1212 -0
- package/dist/app/http/dev-activities.d.ts +115 -0
- package/dist/app/http/dev-activities.js +193 -0
- package/dist/app/http/dev-overview.d.ts +108 -0
- package/dist/app/http/dev-overview.js +209 -0
- package/dist/app/http/dev-tutor-files.d.ts +80 -0
- package/dist/app/http/dev-tutor-files.js +151 -0
- package/dist/app/http/parent-home.d.ts +37 -0
- package/dist/app/http/parent-home.js +203 -0
- package/dist/app/http/range.d.ts +9 -0
- package/dist/app/http/range.js +19 -0
- package/dist/app/http/raw-view.d.ts +117 -0
- package/dist/app/http/raw-view.js +149 -0
- package/dist/app/http/send-file.d.ts +7 -0
- package/dist/app/http/send-file.js +29 -0
- package/dist/{server → app/http}/stage.d.ts +9 -0
- package/dist/{server → app/http}/stage.js +34 -6
- package/dist/app/http/theme.d.ts +13 -0
- package/dist/app/http/theme.js +41 -0
- package/dist/app/machine/bailian.d.ts +28 -0
- package/dist/app/machine/bailian.js +88 -0
- package/dist/app/mock/mock-live.d.ts +16 -0
- package/dist/app/mock/mock-live.js +140 -0
- package/dist/{server → app/mock}/mock.d.ts +36 -5
- package/dist/app/mock/mock.js +1117 -0
- package/dist/app/replay.d.ts +94 -0
- package/dist/app/replay.js +170 -0
- package/dist/app/skills/analyze-doc.d.ts +3 -0
- package/dist/app/skills/analyze-doc.js +47 -0
- package/dist/app/skills/home-doc.d.ts +5 -0
- package/dist/app/skills/home-doc.js +112 -0
- package/dist/app/skills/tune-doc.d.ts +3 -0
- package/dist/app/skills/tune-doc.js +80 -0
- package/dist/app/talk/list.d.ts +11 -0
- package/dist/app/talk/list.js +9 -0
- package/dist/app/talk/route.d.ts +16 -0
- package/dist/app/talk/route.js +142 -0
- package/dist/app/workspace.d.ts +58 -0
- package/dist/{cli → app}/workspace.js +77 -52
- package/dist/app/ws/route.d.ts +25 -0
- package/dist/app/ws/route.js +29 -0
- package/dist/app/ws/ws.d.ts +31 -0
- package/dist/app/ws/ws.js +169 -0
- package/dist/board/canvas-chat.d.ts +97 -0
- package/dist/board/canvas-chat.js +175 -0
- package/dist/board/card-guards.d.ts +15 -0
- package/dist/board/card-guards.js +38 -0
- package/dist/board/cards/canvas.d.ts +41 -0
- package/dist/board/cards/canvas.js +83 -0
- package/dist/{cards → board/cards}/choice.js +0 -12
- package/dist/{cards → board/cards}/code.js +0 -3
- package/dist/board/cards/dictation.d.ts +42 -0
- package/dist/board/cards/dictation.js +105 -0
- package/dist/board/cards/docs.d.ts +47 -0
- package/dist/board/cards/docs.js +152 -0
- package/dist/{cards → board/cards}/image.js +1 -10
- package/dist/board/cards/index.d.ts +62 -0
- package/dist/board/cards/index.js +144 -0
- package/dist/{cards → board/cards}/kind.d.ts +10 -4
- package/dist/board/cards/kind.js +9 -0
- package/dist/board/cards/lecture.d.ts +26 -0
- package/dist/board/cards/lecture.js +62 -0
- package/dist/board/cards/paint.d.ts +38 -0
- package/dist/board/cards/paint.js +85 -0
- package/dist/board/cards/photo.d.ts +15 -0
- package/dist/board/cards/photo.js +29 -0
- package/dist/{cards → board/cards}/read.js +1 -10
- package/dist/board/cards/text.d.ts +20 -0
- package/dist/board/cards/text.js +59 -0
- package/dist/board/cards/tianzige.d.ts +16 -0
- package/dist/board/cards/tianzige.js +64 -0
- package/dist/board/cards/tutor.d.ts +72 -0
- package/dist/board/cards/tutor.js +134 -0
- package/dist/board/cards/word.d.ts +20 -0
- package/dist/board/cards/word.js +76 -0
- package/dist/board/lecture.d.ts +100 -0
- package/dist/board/lecture.js +204 -0
- package/dist/board/paper.d.ts +20 -0
- package/dist/board/paper.js +76 -0
- package/dist/board/parse.d.ts +120 -0
- package/dist/board/parse.js +330 -0
- package/dist/board/presentation.d.ts +295 -0
- package/dist/board/presentation.js +615 -0
- package/dist/board/sections.d.ts +16 -0
- package/dist/board/sections.js +130 -0
- package/dist/brain/api-tools.d.ts +8 -0
- package/dist/brain/api-tools.js +190 -0
- package/dist/brain/api.d.ts +62 -0
- package/dist/brain/api.js +411 -0
- package/dist/brain/cli/adapters.d.ts +60 -0
- package/dist/brain/cli/adapters.js +91 -0
- package/dist/brain/cli/qwen.d.ts +11 -0
- package/dist/brain/cli/qwen.js +141 -0
- package/dist/brain/cli/run-plan.d.ts +59 -0
- package/dist/brain/cli/run-plan.js +71 -0
- package/dist/brain/cli/run.d.ts +35 -0
- package/dist/brain/cli/run.js +256 -0
- package/dist/brain/cli/stream-json.d.ts +18 -0
- package/dist/brain/cli/stream-json.js +86 -0
- package/dist/brain/cli/types.d.ts +144 -0
- package/dist/brain/cli/types.js +3 -0
- package/dist/brain/cli/warm.d.ts +53 -0
- package/dist/brain/cli/warm.js +103 -0
- package/dist/brain/index.d.ts +145 -0
- package/dist/brain/index.js +74 -0
- package/dist/brain/stream.d.ts +20 -0
- package/dist/brain/stream.js +70 -0
- package/dist/brain/transcript.d.ts +45 -0
- package/dist/brain/transcript.js +132 -0
- package/dist/chalk/actions.d.ts +37 -0
- package/dist/chalk/actions.js +69 -0
- package/dist/chalk/bundle.d.ts +26 -0
- package/dist/chalk/bundle.js +69 -0
- package/dist/chalk/check.d.ts +28 -0
- package/dist/chalk/check.js +291 -0
- package/dist/chalk/circle.d.ts +64 -0
- package/dist/chalk/circle.js +193 -0
- package/dist/chalk/clock.d.ts +84 -0
- package/dist/chalk/clock.js +84 -0
- package/dist/chalk/geometry.d.ts +44 -0
- package/dist/chalk/geometry.js +139 -0
- package/dist/chalk/glyphs/capitals.d.ts +12 -0
- package/dist/chalk/glyphs/capitals.js +264 -0
- package/dist/chalk/glyphs/index.d.ts +21 -0
- package/dist/chalk/glyphs/index.js +18 -0
- package/dist/chalk/glyphs/letters.d.ts +13 -0
- package/dist/chalk/glyphs/letters.js +280 -0
- package/dist/chalk/glyphs/metrics.d.ts +33 -0
- package/dist/chalk/glyphs/metrics.js +28 -0
- package/dist/chalk/glyphs/registry.d.ts +7 -0
- package/dist/chalk/glyphs/registry.js +8 -0
- package/dist/chalk/glyphs/sample.d.ts +32 -0
- package/dist/chalk/glyphs/sample.js +102 -0
- package/dist/chalk/glyphs/skeleton.d.ts +64 -0
- package/dist/chalk/glyphs/skeleton.js +126 -0
- package/dist/chalk/glyphs/types.d.ts +58 -0
- package/dist/chalk/glyphs/types.js +17 -0
- package/dist/chalk/index.d.ts +23 -0
- package/dist/chalk/index.js +15 -0
- package/dist/chalk/manifest.d.ts +41 -0
- package/dist/chalk/manifest.js +6 -0
- package/dist/chalk/paint.d.ts +180 -0
- package/dist/chalk/paint.js +210 -0
- package/dist/chalk/pointer.d.ts +8 -0
- package/dist/chalk/pointer.js +21 -0
- package/dist/chalk/prepare.d.ts +11 -0
- package/dist/chalk/prepare.js +15 -0
- package/dist/chalk/scene-schema.d.ts +199 -0
- package/dist/chalk/scene-schema.js +91 -0
- package/dist/chalk/seed.d.ts +3 -0
- package/dist/chalk/seed.js +10 -0
- package/dist/chalk/text-metrics.d.ts +8 -0
- package/dist/chalk/text-metrics.js +156 -0
- package/dist/chalk/timeline.d.ts +47 -0
- package/dist/chalk/timeline.js +84 -0
- package/dist/chalk/types.d.ts +150 -0
- package/dist/chalk/types.js +8 -0
- package/dist/lib/index.d.ts +14 -12
- package/dist/lib/index.js +14 -12
- package/dist/media/draw.d.ts +23 -0
- package/dist/media/draw.js +44 -0
- package/dist/media/mp3.d.ts +6 -0
- package/dist/media/mp3.js +58 -0
- package/dist/media/mp4.d.ts +1 -0
- package/dist/media/mp4.js +58 -0
- package/dist/media/tts-voices.d.ts +18 -0
- package/dist/media/tts-voices.js +606 -0
- package/dist/media/tts.d.ts +56 -0
- package/dist/media/tts.js +174 -0
- package/dist/media/vision.d.ts +25 -0
- package/dist/media/vision.js +71 -0
- package/dist/memory/commit.d.ts +67 -0
- package/dist/memory/commit.js +130 -0
- package/dist/memory/context.d.ts +86 -0
- package/dist/memory/context.js +97 -0
- package/dist/memory/diary.d.ts +84 -0
- package/dist/memory/diary.js +183 -0
- package/dist/memory/grade.d.ts +2 -0
- package/dist/memory/grade.js +7 -0
- package/dist/{lib → memory}/plan.d.ts +1 -1
- package/dist/{lib → memory}/plan.js +1 -1
- package/dist/memory/proposals.d.ts +11 -0
- package/dist/memory/proposals.js +43 -0
- package/dist/memory/retrieval.d.ts +44 -0
- package/dist/memory/retrieval.js +157 -0
- package/dist/{lib → memory}/timetable.d.ts +0 -3
- package/dist/{lib → memory}/timetable.js +0 -11
- package/dist/memory/vault-notes.d.ts +165 -0
- package/dist/memory/vault-notes.js +359 -0
- package/dist/memory/vault.d.ts +70 -0
- package/dist/memory/vault.js +169 -0
- package/dist/realtime/bailian.d.ts +120 -0
- package/dist/realtime/bailian.js +288 -0
- package/dist/realtime/cues.d.ts +51 -0
- package/dist/realtime/cues.js +94 -0
- package/dist/realtime/listen.d.ts +32 -0
- package/dist/realtime/listen.js +53 -0
- package/dist/realtime/preview.d.ts +23 -0
- package/dist/realtime/preview.js +38 -0
- package/dist/realtime/prompt.d.ts +8 -0
- package/dist/realtime/prompt.js +13 -0
- package/dist/realtime/voices.d.ts +19 -0
- package/dist/realtime/voices.js +71 -0
- package/dist/runtime/activities.d.ts +17 -0
- package/dist/runtime/activities.js +46 -0
- package/dist/runtime/activity-state.d.ts +22 -0
- package/dist/runtime/activity-state.js +83 -0
- package/dist/runtime/activity.d.ts +63 -0
- package/dist/runtime/activity.js +428 -0
- package/dist/runtime/agent-file.d.ts +24 -0
- package/dist/runtime/agent-file.js +59 -0
- package/dist/runtime/auto-bookkeep.d.ts +30 -0
- package/dist/runtime/auto-bookkeep.js +84 -0
- package/dist/{lib → runtime/context}/context-pack.d.ts +3 -3
- package/dist/runtime/context/context-pack.js +182 -0
- package/dist/runtime/context/thread-digest.d.ts +4 -0
- package/dist/runtime/context/thread-digest.js +35 -0
- package/dist/runtime/context/tutor-rules.d.ts +25 -0
- package/dist/runtime/context/tutor-rules.js +47 -0
- package/dist/runtime/delivery/delivery.d.ts +94 -0
- package/dist/runtime/delivery/delivery.js +145 -0
- package/dist/runtime/delivery/playback.d.ts +25 -0
- package/dist/runtime/delivery/playback.js +29 -0
- package/dist/runtime/delivery/player.d.ts +145 -0
- package/dist/runtime/delivery/player.js +221 -0
- package/dist/runtime/delivery/queue.d.ts +89 -0
- package/dist/runtime/delivery/queue.js +59 -0
- package/dist/runtime/home/edit.d.ts +39 -0
- package/dist/runtime/home/edit.js +132 -0
- package/dist/runtime/home/home.d.ts +180 -0
- package/dist/runtime/home/home.js +311 -0
- package/dist/runtime/home/store.d.ts +142 -0
- package/dist/runtime/home/store.js +440 -0
- package/dist/runtime/journal/conversation.d.ts +46 -0
- package/dist/runtime/journal/conversation.js +89 -0
- package/dist/runtime/journal/events.d.ts +27 -0
- package/dist/runtime/journal/events.js +136 -0
- package/dist/runtime/journal/kid-log.d.ts +105 -0
- package/dist/runtime/journal/kid-log.js +133 -0
- package/dist/runtime/journal/ledger.d.ts +17 -0
- package/dist/{lib → runtime/journal}/ledger.js +7 -40
- package/dist/runtime/journal/mix.d.ts +33 -0
- package/dist/runtime/journal/mix.js +88 -0
- package/dist/runtime/journal/mouth-index.d.ts +26 -0
- package/dist/runtime/journal/mouth-index.js +34 -0
- package/dist/runtime/journal/mouth.d.ts +54 -0
- package/dist/runtime/journal/mouth.js +102 -0
- package/dist/runtime/journal/recorder.d.ts +46 -0
- package/dist/runtime/journal/recorder.js +58 -0
- package/dist/runtime/journal/store.d.ts +123 -0
- package/dist/runtime/journal/store.js +316 -0
- package/dist/runtime/kid-input.d.ts +16 -0
- package/dist/runtime/kid-input.js +195 -0
- package/dist/runtime/kid-view.d.ts +124 -0
- package/dist/runtime/kid-view.js +157 -0
- package/dist/runtime/lecture.d.ts +86 -0
- package/dist/runtime/lecture.js +237 -0
- package/dist/runtime/live/call.d.ts +219 -0
- package/dist/runtime/live/call.js +1211 -0
- package/dist/runtime/live/turns.d.ts +48 -0
- package/dist/runtime/live/turns.js +102 -0
- package/dist/runtime/runner.d.ts +289 -0
- package/dist/runtime/runner.js +898 -0
- package/dist/runtime/talk-run.d.ts +21 -0
- package/dist/runtime/talk-run.js +34 -0
- package/dist/scenes/dictation/match.d.ts +57 -0
- package/dist/scenes/dictation/match.js +255 -0
- package/dist/scenes/dictation/recognize.d.ts +86 -0
- package/dist/scenes/dictation/recognize.js +163 -0
- package/dist/scenes/dictation/store.d.ts +112 -0
- package/dist/scenes/dictation/store.js +99 -0
- package/dist/scenes/look.d.ts +26 -0
- package/dist/scenes/look.js +1 -0
- package/dist/scenes/paint/painter.d.ts +84 -0
- package/dist/scenes/paint/painter.js +170 -0
- package/dist/scenes/paint/prompt.d.ts +23 -0
- package/dist/scenes/paint/prompt.js +36 -0
- package/dist/scenes/talk/en-words.d.ts +8 -0
- package/dist/scenes/talk/en-words.js +44 -0
- package/dist/scenes/talk/list.d.ts +44 -0
- package/dist/scenes/talk/list.js +88 -0
- package/dist/scenes/talk/store.d.ts +27 -0
- package/dist/scenes/talk/store.js +61 -0
- package/dist/scenes/talk/warmup.d.ts +16 -0
- package/dist/scenes/talk/warmup.js +39 -0
- package/dist/schema/activity.d.ts +149 -0
- package/dist/schema/activity.js +113 -0
- package/dist/schema/board.d.ts +143 -2
- package/dist/schema/board.js +15 -3
- package/dist/schema/config.d.ts +309 -94
- package/dist/schema/config.js +259 -72
- package/dist/schema/context-pack.d.ts +76 -14
- package/dist/schema/context-pack.js +91 -10
- package/dist/{lib/conversation.d.ts → schema/conversation-files.d.ts} +11 -33
- package/dist/schema/conversation-files.js +26 -0
- package/dist/schema/conversation.d.ts +385 -49
- package/dist/schema/conversation.js +135 -19
- package/dist/schema/events.d.ts +138 -0
- package/dist/schema/events.js +1 -0
- package/dist/schema/home.d.ts +46 -0
- package/dist/schema/home.js +30 -0
- package/dist/schema/index.d.ts +14 -3
- package/dist/schema/index.js +14 -3
- package/dist/schema/kid-device.d.ts +20 -0
- package/dist/schema/kid-device.js +32 -0
- package/dist/schema/ledger.d.ts +8 -63
- package/dist/schema/ledger.js +7 -31
- package/dist/schema/memory.d.ts +73 -0
- package/dist/schema/memory.js +47 -0
- package/dist/schema/plan.d.ts +2 -2
- package/dist/schema/plan.js +2 -2
- package/dist/schema/sections.d.ts +32 -25
- package/dist/schema/sections.js +21 -22
- package/dist/schema/theme.d.ts +25 -0
- package/dist/schema/theme.js +26 -0
- package/dist/schema/timetable.d.ts +2 -2
- package/dist/schema/timetable.js +2 -2
- package/dist/schema/workspace.d.ts +41 -0
- package/dist/schema/workspace.js +9 -0
- package/dist/shared/errors.d.ts +8 -0
- package/dist/shared/errors.js +13 -0
- package/dist/shared/home.d.ts +2 -0
- package/dist/shared/home.js +16 -0
- package/dist/shared/human-notes.d.ts +5 -0
- package/dist/shared/human-notes.js +7 -0
- package/dist/shared/qianwen.d.ts +50 -0
- package/dist/shared/qianwen.js +109 -0
- package/dist/shared/time.d.ts +9 -0
- package/dist/shared/time.js +22 -0
- package/dist/shared/tokens.d.ts +18 -0
- package/dist/shared/tokens.js +11 -0
- package/dist/shared/wav.d.ts +10 -0
- package/dist/shared/wav.js +50 -0
- package/dist/stage/chunk-226TNLQA.js +129 -0
- package/dist/stage/chunk-24LGQEKE.js +1 -0
- package/dist/stage/chunk-25XV6UY3.js +10 -0
- package/dist/stage/chunk-2AZI3NHJ.js +1 -0
- package/dist/stage/chunk-2BQZTTBE.js +1 -0
- package/dist/stage/chunk-2M7CGY3Y.js +11 -0
- package/dist/stage/chunk-2VR4WFQ7.js +10 -0
- package/dist/stage/chunk-2ZYXBUWG.js +9 -0
- package/dist/stage/chunk-32LAWMGY.js +1 -0
- package/dist/stage/chunk-3LEMTSOO.js +11 -0
- package/dist/stage/chunk-3QCKGZYE.js +32 -0
- package/dist/stage/chunk-44P66WFA.js +1 -0
- package/dist/stage/chunk-4AM6FRR6.js +7 -0
- package/dist/stage/chunk-4QDE4SUK.js +1 -0
- package/dist/stage/chunk-4QESHV3U.js +1 -0
- package/dist/stage/chunk-4SG5QPHB.js +2 -0
- package/dist/stage/chunk-4T4UVCOC.js +1 -0
- package/dist/stage/chunk-4WUEPPG3.js +34 -0
- package/dist/stage/chunk-4YCN6UZ5.js +99 -0
- package/dist/stage/chunk-5V7ZY2AP.js +1 -0
- package/dist/stage/chunk-5VS5Y2VJ.js +6 -0
- package/dist/stage/chunk-5W4NO2ZD.js +62 -0
- package/dist/stage/chunk-65CRNICM.js +1 -0
- package/dist/stage/chunk-66MULO7F.js +5 -0
- package/dist/stage/chunk-6COFQTBS.js +162 -0
- package/dist/stage/chunk-6VZG3M3I.js +8 -0
- package/dist/stage/chunk-7HVDH43T.js +1 -0
- package/dist/stage/chunk-7JLJN4EZ.js +8 -0
- package/dist/stage/chunk-7QDSP4LN.js +1 -0
- package/dist/stage/chunk-7R6OQAO3.js +1 -0
- package/dist/stage/chunk-7VTTHZKW.js +7 -0
- package/dist/stage/chunk-ATHR5KEN.js +10 -0
- package/dist/stage/chunk-B6R5LTP2.js +36 -0
- package/dist/stage/chunk-BD4WE264.js +1 -0
- package/dist/stage/chunk-BONANU47.js +206 -0
- package/dist/stage/chunk-BTVW7OFK.js +89 -0
- package/dist/stage/chunk-BUTJIDHG.js +8 -0
- package/dist/stage/chunk-C2IPYMML.js +84 -0
- package/dist/stage/chunk-C54FTPPV.js +9 -0
- package/dist/stage/chunk-C6LOUF2Z.js +90 -0
- package/dist/stage/chunk-CFF3PILO.js +339 -0
- package/dist/stage/chunk-CI2FQ2JY.js +9 -0
- package/dist/stage/chunk-CW5O4RV7.js +12 -0
- package/dist/stage/chunk-CYABNQYD.js +1 -0
- package/dist/stage/chunk-D7FFA4NS.js +15 -0
- package/dist/stage/chunk-DUNNXU6Z.js +8 -0
- package/dist/stage/chunk-E3E4Q6JF.js +6 -0
- package/dist/stage/chunk-EB3U3LH7.js +9 -0
- package/dist/stage/chunk-EGSZ736B.js +8 -0
- package/dist/stage/chunk-EOBXW5VQ.js +2 -0
- package/dist/stage/chunk-ERZC3B7Y.js +11 -0
- package/dist/stage/chunk-ESDOOBIH.js +11 -0
- package/dist/stage/chunk-EVU4QAL4.js +178 -0
- package/dist/stage/chunk-EVVZI2NY.js +39 -0
- package/dist/stage/chunk-FBKAZUKD.js +39 -0
- package/dist/stage/chunk-FDVKYQJN.js +1 -0
- package/dist/stage/chunk-FGPVYHVR.js +5 -0
- package/dist/stage/chunk-FHUD4AZC.js +1 -0
- package/dist/stage/chunk-FKUJ2DMY.js +96 -0
- package/dist/stage/chunk-FNZGVIJV.js +1 -0
- package/dist/stage/chunk-GBYSEGYM.js +78 -0
- package/dist/stage/chunk-GCO4TDHX.js +1 -0
- package/dist/stage/chunk-GKTML2LG.js +10 -0
- package/dist/stage/chunk-GMDIHHXQ.js +11 -0
- package/dist/stage/chunk-GOUNACI3.js +10 -0
- package/dist/stage/chunk-GXAYATPF.js +3 -0
- package/dist/stage/chunk-H2K2DDXV.js +8 -0
- package/dist/stage/chunk-H3UJI6ZY.js +13 -0
- package/dist/stage/chunk-H6PUGCME.js +7 -0
- package/dist/stage/chunk-HNBUIMIG.js +1 -0
- package/dist/stage/chunk-HRZY2BJQ.js +10 -0
- package/dist/stage/chunk-HSPJGALW.js +30 -0
- package/dist/stage/chunk-IBYORHIP.js +25 -0
- package/dist/stage/chunk-IHF4EWTY.js +1 -0
- package/dist/stage/chunk-ISBRPNKI.js +1 -0
- package/dist/stage/chunk-IZ3OI3C2.js +2 -0
- package/dist/stage/chunk-JEFZAC2R.js +1 -0
- package/dist/stage/chunk-JFIGRDPO.js +1 -0
- package/dist/stage/chunk-JFVYBOOC.js +9 -0
- package/dist/stage/chunk-JGD4TUTQ.js +1 -0
- package/dist/stage/chunk-JO4BEHDH.js +4 -0
- package/dist/stage/chunk-JOWBS42C.js +1 -0
- package/dist/stage/chunk-JP3TM2TG.js +1 -0
- package/dist/stage/chunk-JVK2C52O.js +1 -0
- package/dist/stage/chunk-K4I76XBX.js +14 -0
- package/dist/stage/chunk-KA6CZZ4M.js +1 -0
- package/dist/stage/chunk-KESSJ36M.js +1 -0
- package/dist/stage/chunk-LKATEVRU.js +1 -0
- package/dist/stage/chunk-LS4EJ2EI.js +1 -0
- package/dist/stage/chunk-LUKJQC2X.js +70 -0
- package/dist/stage/chunk-LWULR3SM.js +1 -0
- package/dist/stage/chunk-LWVRFMKX.js +2 -0
- package/dist/stage/chunk-LXC4ZBPZ.js +1 -0
- package/dist/stage/chunk-M2UP255H.js +1 -0
- package/dist/stage/chunk-MAPPXUZQ.js +231 -0
- package/dist/stage/chunk-MBMPW7Z5.js +1 -0
- package/dist/stage/chunk-MD3HMMTK.js +1 -0
- package/dist/stage/chunk-MLPCUIKR.js +17 -0
- package/dist/stage/chunk-MNQIRPDQ.js +8 -0
- package/dist/stage/chunk-MRG7MJVS.js +1 -0
- package/dist/stage/chunk-MU6EXW72.js +10 -0
- package/dist/stage/chunk-MVU2X6LU.js +4 -0
- package/dist/stage/chunk-N6UA5CZV.js +36 -0
- package/dist/stage/chunk-NLZIT2TJ.js +7 -0
- package/dist/stage/chunk-NOJR3J7M.js +1 -0
- package/dist/stage/chunk-NT7ARDOL.js +1 -0
- package/dist/stage/chunk-NWOGMPZH.js +1 -0
- package/dist/stage/chunk-NXE4KMG3.js +40 -0
- package/dist/stage/chunk-O4YCZXD2.js +257 -0
- package/dist/stage/chunk-OAJZ7HLK.js +1 -0
- package/dist/stage/chunk-OCFCFASO.js +1 -0
- package/dist/stage/chunk-ODGPG5RY.js +7 -0
- package/dist/stage/chunk-ODUEA52Q.js +3 -0
- package/dist/stage/chunk-OGDJ3FCI.js +1 -0
- package/dist/stage/chunk-OLDJ55TT.js +1 -0
- package/dist/stage/chunk-OOCL4ATI.js +2 -0
- package/dist/stage/chunk-OQEFDUDV.js +1 -0
- package/dist/stage/chunk-OQWVEWG7.js +4 -0
- package/dist/stage/chunk-OUIX6BGK.js +1 -0
- package/dist/stage/chunk-OV7OZYUO.js +7 -0
- package/dist/stage/chunk-PFGDY33O.js +1 -0
- package/dist/stage/chunk-PFJDUJB3.js +139 -0
- package/dist/stage/chunk-PGEW76ER.js +1 -0
- package/dist/stage/chunk-PP76TAQX.js +32 -0
- package/dist/stage/chunk-PTBOP4OT.js +2 -0
- package/dist/stage/chunk-PX2RVHCK.js +1 -0
- package/dist/stage/chunk-Q7K3PNAD.js +1 -0
- package/dist/stage/chunk-QDDPLZDB.js +1 -0
- package/dist/stage/chunk-QLGLZ77F.js +1 -0
- package/dist/stage/chunk-QOPFDFHI.js +1 -0
- package/dist/stage/chunk-QXT4KAEJ.js +1 -0
- package/dist/stage/chunk-R4YVZCIT.js +1 -0
- package/dist/stage/chunk-R6P6EHWA.js +62 -0
- package/dist/stage/chunk-RCH3OXBI.js +9 -0
- package/dist/stage/chunk-RHPE44I2.js +1 -0
- package/dist/stage/chunk-RJ2R4FVC.js +1 -0
- package/dist/stage/chunk-RJH2YVTD.js +1 -0
- package/dist/stage/chunk-RLWWW5OB.js +6 -0
- package/dist/stage/chunk-S3WO35Z7.js +120 -0
- package/dist/stage/chunk-S7ZGX6MW.js +1 -0
- package/dist/stage/chunk-SIAWX27B.js +1 -0
- package/dist/stage/chunk-SLG4X622.js +1 -0
- package/dist/stage/chunk-SLJRBC77.js +168 -0
- package/dist/stage/chunk-SRORWQJZ.js +1 -0
- package/dist/stage/chunk-STZTUIIF.js +2 -0
- package/dist/stage/chunk-SVQ6MWNV.js +9 -0
- package/dist/stage/chunk-TL3HLL2S.js +132 -0
- package/dist/stage/chunk-U3DOE6SF.js +24 -0
- package/dist/stage/chunk-UABQIZKW.js +6 -0
- package/dist/stage/chunk-UDK3R764.js +1 -0
- package/dist/stage/chunk-UFF4E54B.js +41 -0
- package/dist/stage/chunk-UFP5Q4AY.js +1 -0
- package/dist/stage/chunk-UMH2TSW2.js +72 -0
- package/dist/stage/chunk-UTASVNF5.js +10 -0
- package/dist/stage/chunk-UW7ML5ML.js +88 -0
- package/dist/stage/chunk-V3J7F6OP.js +1 -0
- package/dist/stage/chunk-VEHP5B5Q.js +5 -0
- package/dist/stage/chunk-VRXWB733.js +9 -0
- package/dist/stage/chunk-VVDHBBS5.js +5 -0
- package/dist/stage/chunk-VYFOH6FU.js +106 -0
- package/dist/stage/chunk-W3VZTLQS.js +3 -0
- package/dist/stage/chunk-W7WNRWTZ.js +8 -0
- package/dist/stage/chunk-WHUCV53C.js +1 -0
- package/dist/stage/chunk-WULMYHIF.js +1 -0
- package/dist/stage/chunk-X54EX7AW.js +9 -0
- package/dist/stage/chunk-X565ISZM.js +1 -0
- package/dist/stage/chunk-XGZMDECB.js +1 -0
- package/dist/stage/chunk-XHONC4RF.js +172 -0
- package/dist/stage/chunk-XIK4XQ6E.js +24 -0
- package/dist/stage/chunk-XJQQWFTE.js +1 -0
- package/dist/stage/chunk-XM4WOU3I.js +13 -0
- package/dist/stage/chunk-XM7Y5HP5.js +38 -0
- package/dist/stage/chunk-XNYYRGD5.js +292 -0
- package/dist/stage/chunk-XOYVR3SV.js +1 -0
- package/dist/stage/chunk-XQIW5HCE.js +1 -0
- package/dist/stage/chunk-YEWL7FUW.js +8 -0
- package/dist/stage/chunk-YI55PY3V.js +1 -0
- package/dist/stage/chunk-YM63HI6W.js +1 -0
- package/dist/stage/chunk-YNLGLU4P.js +9 -0
- package/dist/stage/chunk-YTNMNOWP.js +1 -0
- package/dist/stage/chunk-YV62XKTC.js +1 -0
- package/dist/stage/chunk-YVBA3QW6.js +1 -0
- package/dist/stage/chunk-Z2SY2HOC.js +1 -0
- package/dist/stage/chunk-ZBTCQEBK.js +10 -0
- package/dist/stage/chunk-ZCUFN74D.js +1 -0
- package/dist/stage/chunk-ZHOULXEJ.js +11 -0
- package/dist/stage/chunk-ZTRZIET2.js +1 -0
- package/dist/stage/index.html +1 -0
- package/dist/stage/stage.css +1 -1
- package/dist/stage/stage.js +1 -4383
- package/dist/ui/dev/dev-page.d.ts +1 -0
- package/dist/ui/dev/dev-page.js +2248 -0
- package/dist/ui/dev/dev-theme.d.ts +6 -0
- package/dist/ui/dev/dev-theme.js +67 -0
- package/dist/ui/dev/qr-page.d.ts +8 -0
- package/dist/ui/dev/qr-page.js +61 -0
- package/dist/ui/dev/voice-gallery-page.d.ts +1 -0
- package/dist/ui/dev/voice-gallery-page.js +121 -0
- package/dist/ui/dev/voice-scenes.d.ts +21 -0
- package/dist/ui/dev/voice-scenes.js +30 -0
- package/dist/ui/dictation/en-box.d.ts +2 -0
- package/dist/ui/dictation/en-box.js +86 -0
- package/dist/ui/dictation/en-page.d.ts +1 -0
- package/dist/ui/dictation/en-page.js +484 -0
- package/dist/ui/dictation/page.d.ts +1 -0
- package/dist/ui/dictation/page.js +1084 -0
- package/dist/ui/dictation/parent-page.d.ts +1 -0
- package/dist/ui/dictation/parent-page.js +234 -0
- package/dist/ui/dictation/reel-mode.d.ts +1 -0
- package/dist/ui/dictation/reel-mode.js +87 -0
- package/dist/ui/dictation/reel-page.d.ts +1 -0
- package/dist/ui/dictation/reel-page.js +62 -0
- package/dist/ui/dictation/reel.d.ts +163 -0
- package/dist/ui/dictation/reel.js +436 -0
- package/dist/ui/dictation/ui.d.ts +44 -0
- package/dist/ui/dictation/ui.js +80 -0
- package/dist/ui/dictation/unlock.d.ts +7 -0
- package/dist/ui/dictation/unlock.js +16 -0
- package/dist/ui/kid/audio-client.d.ts +11 -0
- package/dist/ui/kid/audio-client.js +74 -0
- package/dist/ui/kid/board-mark-art.d.ts +37 -0
- package/dist/ui/kid/board-mark-art.js +5 -0
- package/dist/ui/kid/board-mark.d.ts +24 -0
- package/dist/ui/kid/board-mark.js +58 -0
- package/dist/ui/kid/kid-log.d.ts +15 -0
- package/dist/ui/kid/kid-log.js +87 -0
- package/dist/ui/kid/kid-nav.d.ts +11 -0
- package/dist/ui/kid/kid-nav.js +22 -0
- package/dist/ui/kid/kid-page.d.ts +9 -0
- package/dist/ui/kid/kid-page.js +3719 -0
- package/dist/ui/kid/letters.d.ts +26 -0
- package/dist/ui/kid/letters.js +51 -0
- package/dist/ui/kid/photo-edit.d.ts +83 -0
- package/dist/ui/kid/photo-edit.js +106 -0
- package/dist/ui/kid/photo-ui.d.ts +23 -0
- package/dist/ui/kid/photo-ui.js +60 -0
- package/dist/ui/kid/reel.d.ts +419 -0
- package/dist/ui/kid/reel.js +648 -0
- package/dist/ui/kid/tianzige.d.ts +8 -0
- package/dist/ui/kid/tianzige.js +45 -0
- package/dist/ui/kid/tutor-face.d.ts +35 -0
- package/dist/ui/kid/tutor-face.js +84 -0
- package/dist/ui/kid/voice-ui.d.ts +70 -0
- package/dist/ui/kid/voice-ui.js +316 -0
- package/dist/ui/kid/voice-view.d.ts +71 -0
- package/dist/ui/kid/voice-view.js +75 -0
- package/dist/ui/kid/word-draw.d.ts +2 -0
- package/dist/ui/kid/word-draw.js +107 -0
- package/dist/ui/kid/word-emoji.d.ts +10 -0
- package/dist/ui/kid/word-emoji.js +66 -0
- package/dist/ui/kid/word-layout.d.ts +25 -0
- package/dist/ui/kid/word-layout.js +29 -0
- package/dist/ui/parent/parent-home-page.d.ts +1 -0
- package/dist/ui/parent/parent-home-page.js +414 -0
- package/dist/ui/parent/parent-page.d.ts +2 -0
- package/dist/ui/parent/parent-page.js +507 -0
- package/dist/ui/shared/brand.d.ts +36 -0
- package/dist/ui/shared/brand.js +51 -0
- package/dist/ui/shared/favicon.d.ts +12 -0
- package/dist/ui/shared/favicon.js +96 -0
- package/dist/ui/shared/icon.d.ts +9 -0
- package/dist/ui/shared/icon.js +35 -0
- package/dist/ui/shared/inline-lib.d.ts +1 -0
- package/dist/ui/shared/inline-lib.js +28 -0
- package/dist/ui/shared/logo.d.ts +31 -0
- package/dist/ui/shared/logo.js +43 -0
- package/dist/ui/shared/page-dom.d.ts +12 -0
- package/dist/ui/shared/page-dom.js +36 -0
- package/dist/ui/shared/png.d.ts +1 -0
- package/dist/ui/shared/png.js +45 -0
- package/dist/ui/shared/qr-svg.d.ts +3 -0
- package/dist/ui/shared/qr-svg.js +32 -0
- package/dist/ui/shared/qr.d.ts +14 -0
- package/dist/ui/shared/qr.js +281 -0
- package/dist/ui/shared/reel-dock.d.ts +22 -0
- package/dist/ui/shared/reel-dock.js +365 -0
- package/dist/ui/shared/tutor-color.d.ts +15 -0
- package/dist/ui/shared/tutor-color.js +47 -0
- package/dist/ui/talk/page.d.ts +6 -0
- package/dist/ui/talk/page.js +294 -0
- package/grades/grade-2/README.md +11 -0
- package/grades/grade-2/VALIDATION.md +41 -0
- package/grades/grade-2/agents/chinese-tutor/activities//344/275/240/350/257/264/346/210/221/347/224/273.md +157 -0
- 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
- 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
- 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
- package/grades/grade-2/agents/chinese-tutor/activities//345/206/231/350/257/235.md +64 -0
- package/grades/grade-2/agents/chinese-tutor/activities//345/206/231/350/257/235./344/276/213/345/255/220.md +31 -0
- package/grades/grade-2/agents/chinese-tutor/activities//345/220/254/345/206/231.md +48 -0
- package/grades/grade-2/agents/chinese-tutor/activities//345/244/215/344/271/240.md +79 -0
- package/grades/grade-2/agents/chinese-tutor/activities//345/244/215/344/271/240./344/276/213/345/255/220.md +35 -0
- package/grades/grade-2/agents/chinese-tutor/activities//345/260/217/350/257/276/345/240/202.md +53 -0
- package/grades/grade-2/agents/chinese-tutor/activities//346/211/271/346/224/271.md +81 -0
- package/grades/grade-2/agents/chinese-tutor/activities//346/211/271/346/224/271./344/276/213/345/255/220.md +35 -0
- package/grades/grade-2/agents/chinese-tutor/activities//347/234/213/345/233/276/350/257/264/350/257/235.md +94 -0
- 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
- package/grades/grade-2/agents/chinese-tutor/activities//351/242/204/344/271/240.md +82 -0
- package/grades/grade-2/agents/chinese-tutor/activities//351/242/204/344/271/240./344/276/213/345/255/220.md +35 -0
- package/grades/grade-2/agents/chinese-tutor.md +59 -0
- package/grades/grade-2/agents/english-tutor/activities//345/217/243/350/257/255/350/257/276.md +149 -0
- 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
- package/grades/grade-2/agents/english-tutor/activities//345/220/254/345/206/231.md +47 -0
- package/grades/grade-2/agents/english-tutor/activities//345/244/215/344/271/240.md +78 -0
- package/grades/grade-2/agents/english-tutor/activities//345/244/215/344/271/240./344/276/213/345/255/220.md +35 -0
- package/grades/grade-2/agents/english-tutor/activities//345/260/217/350/257/276/345/240/202.md +53 -0
- package/grades/grade-2/agents/english-tutor/activities//346/211/271/346/224/271.md +80 -0
- package/grades/grade-2/agents/english-tutor/activities//346/211/271/346/224/271./344/276/213/345/255/220.md +35 -0
- package/grades/grade-2/agents/english-tutor/activities//351/242/204/344/271/240.md +86 -0
- package/grades/grade-2/agents/english-tutor/activities//351/242/204/344/271/240./344/276/213/345/255/220.md +35 -0
- package/grades/grade-2/agents/english-tutor.md +57 -0
- package/grades/grade-2/agents/math-tutor/activities//345/244/215/344/271/240.md +78 -0
- package/grades/grade-2/agents/math-tutor/activities//345/244/215/344/271/240./344/276/213/345/255/220.md +35 -0
- package/grades/grade-2/agents/math-tutor/activities//345/260/217/350/257/276/345/240/202.md +56 -0
- 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
- package/grades/grade-2/agents/math-tutor/activities//346/211/271/346/224/271.md +80 -0
- package/grades/grade-2/agents/math-tutor/activities//346/211/271/346/224/271./344/276/213/345/255/220.md +35 -0
- package/grades/grade-2/agents/math-tutor/activities//351/242/204/344/271/240.md +81 -0
- package/grades/grade-2/agents/math-tutor/activities//351/242/204/344/271/240./344/276/213/345/255/220.md +35 -0
- package/grades/grade-2/agents/math-tutor.md +51 -0
- package/grades/grade-2/examples/2026-10-27-pingjunfen/audio/index.json +44 -0
- package/grades/grade-2/examples/2026-10-27-pingjunfen/audio/step-1.mp3 +0 -0
- package/grades/grade-2/examples/2026-10-27-pingjunfen/audio/step-2.mp3 +0 -0
- package/grades/grade-2/examples/2026-10-27-pingjunfen/audio/step-3.mp3 +0 -0
- package/grades/grade-2/examples/2026-10-27-pingjunfen/audio/step-4.mp3 +0 -0
- package/grades/grade-2/examples/2026-10-27-pingjunfen/audio/step-5.mp3 +0 -0
- package/grades/grade-2/examples/2026-10-27-pingjunfen/bake.json +1 -0
- package/grades/grade-2/examples/2026-10-27-pingjunfen/manifest.json +63 -0
- package/grades/grade-2/examples/2026-10-27-pingjunfen/scene.json +247 -0
- package/grades/grade-2/examples/2026-10-27-pingjunfen.md +40 -0
- package/grades/grade-2/examples/2026-10-27-pingjunfen.ts +26 -0
- package/grades/grade-2/examples//345/271/263/345/235/207/345/210/206./344/276/213/345/255/220.md +24 -0
- package/grades/grade-2/examples//346/225/260/345/255/246/345/271/263/345/235/207/345/210/206.md +42 -0
- package/grades/grade-2/validation/2026-10-27.json +4410 -0
- package/package.json +26 -15
- package/skills/chalk-cli/SKILL.md +62 -0
- package/skills/chalk-scene/SKILL.md +91 -0
- package/skills/chalk-teaching/SKILL.md +82 -0
- 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
- package/skills/chalk-teaching/models//345/207/221/345/215/201.md +7 -0
- package/skills/chalk-teaching/models//345/221/250/346/234/237/350/247/204/345/276/213.md +6 -0
- package/skills/chalk-teaching/models//345/256/236/347/211/251/345/233/276-/345/242/236/345/207/217.md +6 -0
- 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
- 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
- package/skills/chalk-teaching/models//345/260/217/346/243/222/350/277/233/344/275/215/345/212/240.md +7 -0
- package/skills/chalk-teaching/models//345/260/217/346/243/222/351/200/200/344/275/215/345/207/217.md +6 -0
- package/skills/chalk-teaching/models//346/216/222/351/230/237/347/202/271/351/230/265.md +7 -0
- package/skills/chalk-teaching/models//346/227/266/351/227/264/346/225/260/350/275/264.md +6 -0
- package/skills/chalk-teaching/models//346/245/274/345/261/202/351/227/264/351/232/224/345/233/276.md +7 -0
- package/skills/chalk-teaching/models//347/240/264/345/215/201.md +7 -0
- package/skills/chalk-teaching/models//347/253/226/345/274/217/351/200/200/344/275/215.md +6 -0
- package/skills/chalk-teaching/models//347/272/277/346/256/265/345/233/276.md +7 -0
- package/skills/chalk-teaching/models-index.md +24 -0
- 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
- package/skills/chalk-teaching/references//350/257/264/346/230/216/346/226/207/344/273/266.md +102 -0
- package/skills/chalk-verify/SKILL.md +57 -0
- package/skills/chalk-verify/references//350/257/204/345/210/244/346/240/207/345/207/206.md +69 -0
- package/skills/cotutor-analyze/SKILL.md +106 -0
- package/skills/cotutor-analyze/references//345/221/275/344/273/244/344/270/216/346/226/207/344/273/266.md +31 -0
- package/skills/cotutor-board/SKILL.md +373 -0
- package/skills/cotutor-board/references/README.md +38 -0
- package/skills/cotutor-board/references/canvas.md +68 -0
- package/skills/cotutor-board/references/choice.md +55 -0
- package/skills/cotutor-board/references/code.md +46 -0
- package/skills/cotutor-board/references/image.md +52 -0
- package/skills/cotutor-board/references/lecture.md +69 -0
- package/skills/cotutor-board/references/paint.md +77 -0
- package/skills/cotutor-board/references/photo.md +61 -0
- package/skills/cotutor-board/references/read.md +51 -0
- package/skills/cotutor-board/references/text.md +69 -0
- package/skills/cotutor-board/references/tianzige.md +78 -0
- package/skills/cotutor-board/references/word.md +91 -0
- package/skills/cotutor-home/SKILL.md +169 -0
- package/skills/cotutor-home/references/dictation.md +97 -0
- package/skills/cotutor-home/references/tutor.md +148 -0
- package/skills/cotutor-home/references//345/221/275/344/273/244.md +21 -0
- package/skills/cotutor-home/references//351/246/226/351/241/265/350/257/255/346/263/225.md +142 -0
- package/skills/cotutor-tune/SKILL.md +147 -0
- package/skills/cotutor-tune/references//345/255/227/346/256/265.md +50 -0
- package/skills/cotutor-tutor/SKILL.md +261 -0
- package/skills/cotutor-tutor/references//344/270/212/344/270/213/346/226/207/345/214/205.md +78 -0
- package/themes/default/kid.css +86 -0
- package/themes/default/theme.json +26 -0
- package/agents/chinese-tutor.md +0 -67
- package/agents/homework-tutor.md +0 -17
- package/agents/math-tutor.md +0 -68
- package/agents/planner.md +0 -18
- package/agents/reading-tutor.md +0 -65
- package/agents/scene-maker.md +0 -41
- package/dist/cards/canvas.d.ts +0 -22
- package/dist/cards/canvas.js +0 -65
- package/dist/cards/fill.d.ts +0 -14
- package/dist/cards/fill.js +0 -64
- package/dist/cards/index.d.ts +0 -48
- package/dist/cards/index.js +0 -115
- package/dist/cards/kind.js +0 -7
- package/dist/cards/scene.d.ts +0 -24
- package/dist/cards/scene.js +0 -67
- package/dist/cards/text.d.ts +0 -18
- package/dist/cards/text.js +0 -41
- package/dist/cli/doctor.js +0 -355
- package/dist/cli/init.js +0 -116
- package/dist/cli/main.js +0 -243
- package/dist/cli/serve.js +0 -56
- package/dist/cli/skeleton.d.ts +0 -39
- package/dist/cli/skeleton.js +0 -184
- package/dist/cli/skills.d.ts +0 -40
- package/dist/cli/skills.js +0 -170
- package/dist/cli/workspace.d.ts +0 -69
- package/dist/lib/agent-file.d.ts +0 -10
- package/dist/lib/agent-file.js +0 -16
- package/dist/lib/board.d.ts +0 -15
- package/dist/lib/board.js +0 -107
- package/dist/lib/context-pack.js +0 -55
- package/dist/lib/conversation.js +0 -88
- package/dist/lib/kid-board.d.ts +0 -148
- package/dist/lib/kid-board.js +0 -294
- package/dist/lib/kid-view.d.ts +0 -63
- package/dist/lib/kid-view.js +0 -93
- package/dist/lib/ledger.d.ts +0 -29
- package/dist/lib/run-plan.d.ts +0 -30
- package/dist/lib/run-plan.js +0 -32
- package/dist/lib/sections.d.ts +0 -12
- package/dist/lib/sections.js +0 -151
- package/dist/lib/stream.d.ts +0 -15
- package/dist/lib/stream.js +0 -69
- package/dist/lib/transcript.d.ts +0 -36
- package/dist/lib/transcript.js +0 -95
- package/dist/server/app.d.ts +0 -74
- package/dist/server/app.js +0 -406
- package/dist/server/kid-page.d.ts +0 -1
- package/dist/server/kid-page.js +0 -768
- package/dist/server/mock.js +0 -403
- package/dist/server/parent-page.d.ts +0 -8
- package/dist/server/parent-page.js +0 -393
- package/dist/server/runner.d.ts +0 -64
- package/dist/server/runner.js +0 -277
- package/dist/server/scene-props.d.ts +0 -16
- package/dist/server/scene-props.js +0 -39
- package/dist/server/store.d.ts +0 -43
- package/dist/server/store.js +0 -210
- package/dist/server/tts.d.ts +0 -51
- package/dist/server/tts.js +0 -99
- /package/dist/{cli → app/cli}/cert.d.ts +0 -0
- /package/dist/{cli → app/cli}/main.d.ts +0 -0
- /package/dist/{cards → board/cards}/choice.d.ts +0 -0
- /package/dist/{cards → board/cards}/code.d.ts +0 -0
- /package/dist/{cards → board/cards}/image.d.ts +0 -0
- /package/dist/{cards → board/cards}/read.d.ts +0 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { type CardPlace } from './index.ts';
|
|
2
|
+
/** 本包自带的卡协议目录(仓库检出与 npm 安装都在包根 cards/) */
|
|
3
|
+
export declare const PACKAGE_CARDS_DIR: string;
|
|
4
|
+
export interface CardDoc {
|
|
5
|
+
kind: string;
|
|
6
|
+
/** 整份 card.md */
|
|
7
|
+
md: string;
|
|
8
|
+
/** 各栏目正文(按 ## 标题切;没有的栏目是空串) */
|
|
9
|
+
sections: Record<string, string>;
|
|
10
|
+
/** 标题行后面那句(「text — 一段字」) */
|
|
11
|
+
headline: string;
|
|
12
|
+
}
|
|
13
|
+
/** md 按 `## ` 切栏目;`# ` 标题行单独取 */
|
|
14
|
+
export declare function splitSections(md: string): {
|
|
15
|
+
headline: string;
|
|
16
|
+
sections: Record<string, string>;
|
|
17
|
+
};
|
|
18
|
+
export declare function readCardDoc(kind: string, dir?: string): CardDoc;
|
|
19
|
+
/** 能用在某处的种类的协议(按注册表的顺序);缺省板书——cotutor-board 技能只列这些;给了 only 就只要这几种(按老师裁,boardGuideFor) */
|
|
20
|
+
export declare function cardDocs(dir?: string, place?: CardPlace, only?: readonly string[]): CardDoc[];
|
|
21
|
+
/** 板书写法的手写部分(开头的规矩、一节的例子、作业照片),人改的就是这一篇;`{{卡的种类}}` 那一行由下面拼的各种卡替换 */
|
|
22
|
+
export declare const BOARD_GUIDE_SOURCE = "\u677F\u4E66\u600E\u4E48\u5199.md";
|
|
23
|
+
/**
|
|
24
|
+
* 给老师看的语法表(SKILL.md 的正文):cards/板书怎么写.md(剥掉给人看的注释,按卡裁段落)+ 各 card.md 的「是什么 / 写法 / 例子」。
|
|
25
|
+
* kinds 不给 = 板书的全部种类(出厂的 SKILL.md);给了就只拼这几种(按老师裁,boardGuideFor)。
|
|
26
|
+
*/
|
|
27
|
+
export declare function boardSyntaxDoc(dir?: string, kinds?: readonly string[]): string;
|
|
28
|
+
/** 板书写法以外多带的几种卡(activity 要用、老师的清单里没有的),同板书写法里那一段的样子;递给老师前剥掉给人看的注释 */
|
|
29
|
+
export declare function cardGuidesFor(kinds: readonly string[], dir?: string): string;
|
|
30
|
+
/** 按老师裁的板书写法(递给老师的正文,同 boardGuideBody(SKILL.md) 的形状:没有 frontmatter、没有给人看的注释) */
|
|
31
|
+
export declare function boardGuideFor(kinds: readonly string[], dir?: string): string;
|
|
32
|
+
/** references/README.md:一行一种——名字、一句是什么、何时用;老师按需 @ 单张 */
|
|
33
|
+
export declare function cardsIndexDoc(dir?: string): string;
|
|
34
|
+
/** 技能名;目录 .agents/skills/cotutor-board/ */
|
|
35
|
+
export declare const BOARD_SKILL = "cotutor-board";
|
|
36
|
+
/** SKILL.md:frontmatter(name / description)+ 语法表;description 列出卡的种类,让模型不读正文也知道有哪几种 */
|
|
37
|
+
export declare function boardSkillDoc(dir?: string): string;
|
|
38
|
+
/** 技能目录的全部文件(相对技能根):SKILL.md + references/README.md + references/<kind>.md;scripts/gen-skills.ts 写进包根 skills/cotutor-board/,tests/skills.test.ts 断言入库的和它一致 */
|
|
39
|
+
export declare function boardSkillFiles(dir?: string): Record<string, string>;
|
|
40
|
+
/** 各种卡的结构样式(cards/<kind>/card.css)拼成一段,放在主题 css 前面(主题能盖) */
|
|
41
|
+
export declare function cardsCss(dir?: string): string;
|
|
42
|
+
/** 例子即测试用:md 里每个围栏 + 它前面的 expect 注释 */
|
|
43
|
+
export declare function docExamples(md: string): {
|
|
44
|
+
tag: string;
|
|
45
|
+
body: string;
|
|
46
|
+
expect: Record<string, unknown> | null;
|
|
47
|
+
}[];
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 卡的协议文件:每种能力型卡在包根 cards/<kind>/ 下有 card.md(协议:是什么 / 何时用 / 写法 / 例子 / 反例 /
|
|
3
|
+
* 孩子看到什么 / 你会收回什么 / 状态的形状)与 card.css(这种卡的结构样式,只用主题变量)。
|
|
4
|
+
* md 是可以单独 @ 的文件:init / upgrade 出厂成 workspace 里的**一个技能** .agents/skills/cotutor-board/:SKILL.md = 语法表(frontmatter + 各 md 的「是什么 / 写法 / 例子」拼),references/<kind>.md 逐张协议,
|
|
5
|
+
* references/README.md 索引;老师按需 @ 单张。写盘的在 app/cli/skills.ts `writeBoardSkill`。
|
|
6
|
+
* 例子即测试:tests/cards-doc.test.ts 把每个 card.md 里的围栏喂 parseCard,`<!-- expect {…} -->` 注释是期望。
|
|
7
|
+
*/
|
|
8
|
+
import { readFileSync } from 'node:fs';
|
|
9
|
+
import { join } from 'node:path';
|
|
10
|
+
import { fileURLToPath } from 'node:url';
|
|
11
|
+
import { CARD_KINDS, kindsFor } from "./index.js";
|
|
12
|
+
import { stripHumanNotes } from "../../shared/human-notes.js";
|
|
13
|
+
import { applyCardGuards } from "../card-guards.js";
|
|
14
|
+
/** 本包自带的卡协议目录(仓库检出与 npm 安装都在包根 cards/) */
|
|
15
|
+
export const PACKAGE_CARDS_DIR = fileURLToPath(new URL('../../../cards/', import.meta.url));
|
|
16
|
+
/** md 按 `## ` 切栏目;`# ` 标题行单独取 */
|
|
17
|
+
export function splitSections(md) {
|
|
18
|
+
const lines = md.split('\n');
|
|
19
|
+
// 标题行 = 第一个 ## 之前的那行 `# …`;栏目里的 `# 认边`(例子围栏里的)照收
|
|
20
|
+
let headline = '';
|
|
21
|
+
const sections = {};
|
|
22
|
+
let cur = null;
|
|
23
|
+
const buf = [];
|
|
24
|
+
const flush = () => {
|
|
25
|
+
if (cur !== null)
|
|
26
|
+
sections[cur] = buf.join('\n').trim();
|
|
27
|
+
buf.length = 0;
|
|
28
|
+
};
|
|
29
|
+
for (const l of lines) {
|
|
30
|
+
if (l.startsWith('## ')) {
|
|
31
|
+
flush();
|
|
32
|
+
cur = l.slice(3).trim();
|
|
33
|
+
}
|
|
34
|
+
else if (cur === null) {
|
|
35
|
+
if (!headline && l.startsWith('# '))
|
|
36
|
+
headline = l.slice(2).trim();
|
|
37
|
+
}
|
|
38
|
+
else
|
|
39
|
+
buf.push(l);
|
|
40
|
+
}
|
|
41
|
+
flush();
|
|
42
|
+
return { headline, sections };
|
|
43
|
+
}
|
|
44
|
+
export function readCardDoc(kind, dir = PACKAGE_CARDS_DIR) {
|
|
45
|
+
const md = readFileSync(join(dir, kind, 'card.md'), 'utf8');
|
|
46
|
+
const { headline, sections } = splitSections(md);
|
|
47
|
+
return { kind, md, sections, headline };
|
|
48
|
+
}
|
|
49
|
+
/** 能用在某处的种类的协议(按注册表的顺序);缺省板书——cotutor-board 技能只列这些;给了 only 就只要这几种(按老师裁,boardGuideFor) */
|
|
50
|
+
export function cardDocs(dir = PACKAGE_CARDS_DIR, place = 'board', only) {
|
|
51
|
+
return kindsFor(place)
|
|
52
|
+
.filter((k) => !only || only.includes(k.name))
|
|
53
|
+
.map((k) => readCardDoc(k.name, dir));
|
|
54
|
+
}
|
|
55
|
+
/** 例子里的 `<!-- expect {…} -->` 注释:给老师看的版本要去掉 */
|
|
56
|
+
const EXPECT_RE = /^\s*<!--\s*expect\b.*?-->\s*\n?/gm;
|
|
57
|
+
/** 板书写法的手写部分(开头的规矩、一节的例子、作业照片),人改的就是这一篇;`{{卡的种类}}` 那一行由下面拼的各种卡替换 */
|
|
58
|
+
export const BOARD_GUIDE_SOURCE = '板书怎么写.md';
|
|
59
|
+
const KINDS_SLOT = /^\{\{卡的种类\}\}$/m;
|
|
60
|
+
/**
|
|
61
|
+
* 给老师看的语法表(SKILL.md 的正文):cards/板书怎么写.md(剥掉给人看的注释,按卡裁段落)+ 各 card.md 的「是什么 / 写法 / 例子」。
|
|
62
|
+
* kinds 不给 = 板书的全部种类(出厂的 SKILL.md);给了就只拼这几种(按老师裁,boardGuideFor)。
|
|
63
|
+
*/
|
|
64
|
+
export function boardSyntaxDoc(dir = PACKAGE_CARDS_DIR, kinds) {
|
|
65
|
+
const all = kindsFor('board').map((k) => k.name);
|
|
66
|
+
const want = kinds ? all.filter((k) => kinds.includes(k)) : all;
|
|
67
|
+
const docs = cardDocs(dir, 'board', want).map(cardGuide).join('\n\n');
|
|
68
|
+
const guide = applyCardGuards(stripHumanNotes(readFileSync(join(dir, BOARD_GUIDE_SOURCE), 'utf8')), want);
|
|
69
|
+
if (!KINDS_SLOT.test(guide))
|
|
70
|
+
throw new Error(`cards/${BOARD_GUIDE_SOURCE} 里没有「{{卡的种类}}」那一行`);
|
|
71
|
+
return `${guide.replace(KINDS_SLOT, () => docs)}\n`;
|
|
72
|
+
}
|
|
73
|
+
/** 一种卡给老师看的那段:标题 + 是什么 / 写法 / 例子(去掉 expect);板书写法里「卡的种类」一节就是一张张拼的它 */
|
|
74
|
+
function cardGuide(d) {
|
|
75
|
+
const parts = [`### ${d.headline}`, d.sections['是什么'], d.sections['写法'], d.sections['例子']?.replace(EXPECT_RE, '')].filter((x) => x && x.trim());
|
|
76
|
+
return parts.join('\n\n').trim();
|
|
77
|
+
}
|
|
78
|
+
/** 板书写法以外多带的几种卡(activity 要用、老师的清单里没有的),同板书写法里那一段的样子;递给老师前剥掉给人看的注释 */
|
|
79
|
+
export function cardGuidesFor(kinds, dir = PACKAGE_CARDS_DIR) {
|
|
80
|
+
return stripHumanNotes(cardDocs(dir, 'board', kinds).map(cardGuide).join('\n\n'));
|
|
81
|
+
}
|
|
82
|
+
/** 按老师裁的板书写法(递给老师的正文,同 boardGuideBody(SKILL.md) 的形状:没有 frontmatter、没有给人看的注释) */
|
|
83
|
+
export function boardGuideFor(kinds, dir = PACKAGE_CARDS_DIR) {
|
|
84
|
+
return stripHumanNotes(boardSyntaxDoc(dir, kinds));
|
|
85
|
+
}
|
|
86
|
+
/** references/README.md:一行一种——名字、一句是什么、何时用;老师按需 @ 单张 */
|
|
87
|
+
export function cardsIndexDoc(dir = PACKAGE_CARDS_DIR) {
|
|
88
|
+
const rows = cardDocs(dir).map((d) => {
|
|
89
|
+
const what = (d.sections['是什么'] ?? '').split('\n').find((l) => l.trim()) ?? '';
|
|
90
|
+
const when = (d.sections['什么时候用 / 别用'] ?? '').split('\n').filter((l) => l.startsWith('- 用:')).map((l) => `\n - 用在:${l.slice(4).trim()}`).join('');
|
|
91
|
+
return `- **${d.kind}**(${d.kind}.md)—— ${what}${when}`;
|
|
92
|
+
});
|
|
93
|
+
return `# 卡的种类(索引)
|
|
94
|
+
|
|
95
|
+
每种卡一份协议:是什么、什么时候用 / 别用、写法、例子、反例、孩子看到什么、你会收回什么、状态的形状。讲解前只读需要的那一两张;总表在 ../SKILL.md。机器文件,init / upgrade 刷新。
|
|
96
|
+
|
|
97
|
+
${rows.join('\n')}
|
|
98
|
+
`;
|
|
99
|
+
}
|
|
100
|
+
/** 技能名;目录 .agents/skills/cotutor-board/ */
|
|
101
|
+
export const BOARD_SKILL = 'cotutor-board';
|
|
102
|
+
/** SKILL.md:frontmatter(name / description)+ 语法表;description 列出卡的种类,让模型不读正文也知道有哪几种 */
|
|
103
|
+
export function boardSkillDoc(dir = PACKAGE_CARDS_DIR) {
|
|
104
|
+
const kinds = kindsFor('board').map((k) => k.name).join(' / ');
|
|
105
|
+
const description = `cotutor 的板书怎么写:讲稿一行一句,围栏是卡(种类:${kinds})。应用已经递给老师,老师不用读;家长查阅用。每种卡完整的协议在 references/<种类>.md。机器生成,源在 cotutor 仓的 cards/,别在这里改。`;
|
|
106
|
+
return `---\nname: ${BOARD_SKILL}\ndescription: ${description}\n---\n\n${boardSyntaxDoc(dir)}`;
|
|
107
|
+
}
|
|
108
|
+
/** 技能目录的全部文件(相对技能根):SKILL.md + references/README.md + references/<kind>.md;scripts/gen-skills.ts 写进包根 skills/cotutor-board/,tests/skills.test.ts 断言入库的和它一致 */
|
|
109
|
+
export function boardSkillFiles(dir = PACKAGE_CARDS_DIR) {
|
|
110
|
+
const out = { 'SKILL.md': boardSkillDoc(dir), 'references/README.md': cardsIndexDoc(dir) };
|
|
111
|
+
for (const d of cardDocs(dir))
|
|
112
|
+
out[`references/${d.kind}.md`] = d.md;
|
|
113
|
+
return out;
|
|
114
|
+
}
|
|
115
|
+
/** 各种卡的结构样式(cards/<kind>/card.css)拼成一段,放在主题 css 前面(主题能盖) */
|
|
116
|
+
export function cardsCss(dir = PACKAGE_CARDS_DIR) {
|
|
117
|
+
return CARD_KINDS.map((k) => {
|
|
118
|
+
try {
|
|
119
|
+
return `/* ---- ${k.name}(cards/${k.name}/card.css)---- */\n${readFileSync(join(dir, k.name, 'card.css'), 'utf8').trim()}`;
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
return '';
|
|
123
|
+
}
|
|
124
|
+
})
|
|
125
|
+
.filter(Boolean)
|
|
126
|
+
.join('\n\n');
|
|
127
|
+
}
|
|
128
|
+
/** 例子即测试用:md 里每个围栏 + 它前面的 expect 注释 */
|
|
129
|
+
export function docExamples(md) {
|
|
130
|
+
const out = [];
|
|
131
|
+
const lines = md.split('\n');
|
|
132
|
+
let expect = null;
|
|
133
|
+
for (let i = 0; i < lines.length; i++) {
|
|
134
|
+
const l = lines[i];
|
|
135
|
+
const ex = /^<!--\s*expect\s+(\{.*\})\s*-->$/.exec(l.trim());
|
|
136
|
+
if (ex) {
|
|
137
|
+
expect = JSON.parse(ex[1]);
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
const open = /^```(.*)$/.exec(l);
|
|
141
|
+
if (open && !l.startsWith('````')) {
|
|
142
|
+
const body = [];
|
|
143
|
+
let j = i + 1;
|
|
144
|
+
for (; j < lines.length && !/^```\s*$/.test(lines[j]); j++)
|
|
145
|
+
body.push(lines[j]);
|
|
146
|
+
out.push({ tag: open[1].trim(), body: body.join('\n'), expect });
|
|
147
|
+
expect = null;
|
|
148
|
+
i = j;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return out;
|
|
152
|
+
}
|
|
@@ -12,6 +12,7 @@ export const ImagePropsSchema = z.object({
|
|
|
12
12
|
export const IMAGE_EXT = /\.(png|jpe?g|webp|gif|svg)$/i;
|
|
13
13
|
export const image = {
|
|
14
14
|
name: 'image',
|
|
15
|
+
where: ['board', 'home'],
|
|
15
16
|
props: ImagePropsSchema,
|
|
16
17
|
parse(body) {
|
|
17
18
|
const [src, ...rest] = bodyLines(body);
|
|
@@ -22,14 +23,4 @@ export const image = {
|
|
|
22
23
|
const caption = rest.join('\n');
|
|
23
24
|
return { src, ...(caption ? { caption } : {}) };
|
|
24
25
|
},
|
|
25
|
-
doc: `### image — 图片
|
|
26
|
-
|
|
27
|
-
第一行是图:workspace 里的相对路径(产物、孩子拍的照片,如 \`vault/照片/2026-09-10-作业.jpg\`)或 http(s) 地址;后面几行是图注。孩子点开能放大。
|
|
28
|
-
|
|
29
|
-
\`\`\`\`
|
|
30
|
-
\`\`\`image
|
|
31
|
-
vault/照片/2026-09-10-作业.jpg
|
|
32
|
-
你昨天写的这道题,看第二行。
|
|
33
|
-
\`\`\`
|
|
34
|
-
\`\`\`\``,
|
|
35
26
|
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { BoardCard, BoardSection } from '../presentation.ts';
|
|
2
|
+
import type { CardKind, CardPlace } from './kind.ts';
|
|
3
|
+
export { BUNDLE_ID_RE, type CardKind, type CardPlace } from './kind.ts';
|
|
4
|
+
export { text, TEXT_STYLES, type TextProps, type TextStyle } from './text.ts';
|
|
5
|
+
export { read, type ReadProps } from './read.ts';
|
|
6
|
+
export { choice, type ChoiceProps } from './choice.ts';
|
|
7
|
+
export { code, type CodeProps } from './code.ts';
|
|
8
|
+
export { image, IMAGE_EXT, type ImageProps } from './image.ts';
|
|
9
|
+
export { lecture, type LectureProps, type LectureState } from './lecture.ts';
|
|
10
|
+
export { canvas, type CanvasProps, type CanvasState } from './canvas.ts';
|
|
11
|
+
export { paint, PaintPropsSchema, PAINT_PANELS_MAX, type PaintCast, type PaintProps } from './paint.ts';
|
|
12
|
+
export { tianzige, HAN, TIANZIGE_MAX, type TianzigeProps } from './tianzige.ts';
|
|
13
|
+
export { word, wordChunks, WORD_MAX, WORD_MAX_WORDS, WORD_RE, type WordProps } from './word.ts';
|
|
14
|
+
export { tutor, BUTTON_LABEL_MAX, TUTOR_BUTTONS_MAX, TutorButtonSchema, type TutorButton, type TutorProps } from './tutor.ts';
|
|
15
|
+
export { dictation, dictationEmoji, dictationWordLang, DictationPropsSchema, DICTATION_EN_MAX, DICTATION_SAY_MAX, DICTATION_WORD_MAX, DICTATION_WORDS_MAX, EN_WORD_RE, type DictationLang, type DictationProps, type DictationWord } from './dictation.ts';
|
|
16
|
+
/** 全部种类:先板书的十一种(注册表顺序即技能里的顺序),再首页专属的 */
|
|
17
|
+
export declare const CARD_KINDS: readonly CardKind<any>[];
|
|
18
|
+
export declare function cardKind(name: string): CardKind | undefined;
|
|
19
|
+
/** 这种卡能不能用在这里(没写 where 的只板书) */
|
|
20
|
+
export declare function usableIn(kind: Pick<CardKind, 'where'>, place: CardPlace): boolean;
|
|
21
|
+
/** 能用在某处的种类(注册表顺序) */
|
|
22
|
+
export declare function kindsFor(place: CardPlace): readonly CardKind<any>[];
|
|
23
|
+
/**
|
|
24
|
+
* 这位老师的板书写法里讲哪几种卡(cotutor.json tutors.<老师>.cards,《卡片协议.md》「谁拿到哪些卡」):
|
|
25
|
+
* 没写 = null(全部,递出厂的 cotutor-board SKILL.md);写了 = 板书能用的、按注册表顺序,text 总在(写坏的卡退成它)。
|
|
26
|
+
*/
|
|
27
|
+
export declare function tutorCardKinds(cards: readonly string[] | undefined): string[] | null;
|
|
28
|
+
export interface ParsedCard {
|
|
29
|
+
card: BoardCard;
|
|
30
|
+
/** 没解析成时的一句(家长视图转录里显示);孩子端什么也不报 */
|
|
31
|
+
warning?: string;
|
|
32
|
+
/** 没照标签解析成(退成了文字卡 / 代码卡);首页检查据此判「要改」 */
|
|
33
|
+
fallback?: boolean;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* 围栏 → 卡。标签第一个词是 kind,其余是修饰;不认识的标签:板书里当代码卡原样显示,首页里退文字卡;
|
|
37
|
+
* 认识但正文解析不出、或这种卡不能用在这里(place)→ 文字卡显示原文 + warning。永不抛错。
|
|
38
|
+
*/
|
|
39
|
+
export declare function parseCard(tag: string, body: string, place?: CardPlace): ParsedCard;
|
|
40
|
+
/** 孩子端的一节:每张卡过本种卡的 strip(答案不下发);不认识的 kind 原样;孩子自己的状态与已生成的资产照给 */
|
|
41
|
+
export declare function stripSecrets(section: BoardSection): BoardSection;
|
|
42
|
+
/** 一张卡的标题(舞台顶栏、给老师的描述里用):文字卡的 title / text,选择题的问题,其余第一段有字的,田字格的字,单词卡的词,听写卡的词表 */
|
|
43
|
+
export declare function cardLabel(card: BoardCard): string;
|
|
44
|
+
/** 这张卡要后台预生成的配音(文件名相对它的资产目录);没有的种类 → [] */
|
|
45
|
+
export declare function cardAssets(card: BoardCard): {
|
|
46
|
+
file: string;
|
|
47
|
+
text: string;
|
|
48
|
+
}[];
|
|
49
|
+
export type CardStateResult = {
|
|
50
|
+
ok: true;
|
|
51
|
+
state: unknown;
|
|
52
|
+
} | {
|
|
53
|
+
ok: false;
|
|
54
|
+
why: string;
|
|
55
|
+
};
|
|
56
|
+
/** 孩子端 PUT 上来的状态过本种卡的契约;这种卡没有状态、或不认识的 kind → 不收 */
|
|
57
|
+
export declare function parseCardState(card: BoardCard, raw: unknown): CardStateResult;
|
|
58
|
+
/**
|
|
59
|
+
* 给老师的一句:「choice「问题」 选了「B …」(答案:「…」)」。props 用索引里的(带答案),状态是孩子的;
|
|
60
|
+
* 没有 describe 的种类把状态原样 JSON。id 由调用方拼在前面(<job>/<n>)。
|
|
61
|
+
*/
|
|
62
|
+
export declare function describeCard(card: BoardCard, state: unknown): string;
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 卡的注册表:加一种卡 = 加一个文件 + 这里一行;解析器、语法表、孩子端剥秘密都从这里走。
|
|
3
|
+
* 页面那一半在 kid-page.ts(渲染)与 board/presentation.ts(标注落点),按 kind 名对上。协议文档与结构样式在包根 cards/<kind>/(src/board/cards/docs.ts)。
|
|
4
|
+
*/
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import { canvas } from "./canvas.js";
|
|
7
|
+
import { choice } from "./choice.js";
|
|
8
|
+
import { code } from "./code.js";
|
|
9
|
+
import { tianzige } from "./tianzige.js";
|
|
10
|
+
import { word } from "./word.js";
|
|
11
|
+
import { image } from "./image.js";
|
|
12
|
+
import { read } from "./read.js";
|
|
13
|
+
import { paint } from "./paint.js";
|
|
14
|
+
import { photo } from "./photo.js";
|
|
15
|
+
import { lecture } from "./lecture.js";
|
|
16
|
+
import { text } from "./text.js";
|
|
17
|
+
import { tutor } from "./tutor.js";
|
|
18
|
+
import { dictation } from "./dictation.js";
|
|
19
|
+
export { BUNDLE_ID_RE } from "./kind.js";
|
|
20
|
+
export { text, TEXT_STYLES } from "./text.js";
|
|
21
|
+
export { read } from "./read.js";
|
|
22
|
+
export { choice } from "./choice.js";
|
|
23
|
+
export { code } from "./code.js";
|
|
24
|
+
export { image, IMAGE_EXT } from "./image.js";
|
|
25
|
+
export { lecture } from "./lecture.js";
|
|
26
|
+
export { canvas } from "./canvas.js";
|
|
27
|
+
export { paint, PaintPropsSchema, PAINT_PANELS_MAX } from "./paint.js";
|
|
28
|
+
export { tianzige, HAN, TIANZIGE_MAX } from "./tianzige.js";
|
|
29
|
+
export { word, wordChunks, WORD_MAX, WORD_MAX_WORDS, WORD_RE } from "./word.js";
|
|
30
|
+
export { tutor, BUTTON_LABEL_MAX, TUTOR_BUTTONS_MAX, TutorButtonSchema } from "./tutor.js";
|
|
31
|
+
export { dictation, dictationEmoji, dictationWordLang, DictationPropsSchema, DICTATION_EN_MAX, DICTATION_SAY_MAX, DICTATION_WORD_MAX, DICTATION_WORDS_MAX, EN_WORD_RE } from "./dictation.js";
|
|
32
|
+
/** 全部种类:先板书的十一种(注册表顺序即技能里的顺序),再首页专属的 */
|
|
33
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
34
|
+
export const CARD_KINDS = [text, read, choice, image, tianzige, word, lecture, canvas, paint, photo, code, tutor, dictation];
|
|
35
|
+
export function cardKind(name) {
|
|
36
|
+
return CARD_KINDS.find((k) => k.name === name);
|
|
37
|
+
}
|
|
38
|
+
/** 这种卡能不能用在这里(没写 where 的只板书) */
|
|
39
|
+
export function usableIn(kind, place) {
|
|
40
|
+
return (kind.where ?? ['board']).includes(place);
|
|
41
|
+
}
|
|
42
|
+
/** 能用在某处的种类(注册表顺序) */
|
|
43
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
44
|
+
export function kindsFor(place) {
|
|
45
|
+
return CARD_KINDS.filter((k) => usableIn(k, place));
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* 这位老师的板书写法里讲哪几种卡(cotutor.json tutors.<老师>.cards,《卡片协议.md》「谁拿到哪些卡」):
|
|
49
|
+
* 没写 = null(全部,递出厂的 cotutor-board SKILL.md);写了 = 板书能用的、按注册表顺序,text 总在(写坏的卡退成它)。
|
|
50
|
+
*/
|
|
51
|
+
export function tutorCardKinds(cards) {
|
|
52
|
+
if (!cards)
|
|
53
|
+
return null;
|
|
54
|
+
return kindsFor('board').map((k) => k.name).filter((k) => k === 'text' || cards.includes(k));
|
|
55
|
+
}
|
|
56
|
+
/** 正文是「字」的卡:老师把讲稿的 [词] 标注语法写进这些卡时,把括号剥掉(2026-09-11 真跑:孩子看到了「[直角边]」);choice 的 - [ ] / - [x] 不动 */
|
|
57
|
+
const TEXTUAL = new Set(['text', 'read', 'choice', 'image', 'word', 'paint']);
|
|
58
|
+
const MARK_IN_CARD = /\[([^\[\]\n]+)\]/g;
|
|
59
|
+
function unmark(body) {
|
|
60
|
+
let had = false;
|
|
61
|
+
const out = body.replace(MARK_IN_CARD, (m, inner) => {
|
|
62
|
+
if (/^[ xX]$/.test(inner))
|
|
63
|
+
return m;
|
|
64
|
+
had = true;
|
|
65
|
+
return inner;
|
|
66
|
+
});
|
|
67
|
+
return { body: out, had };
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* 围栏 → 卡。标签第一个词是 kind,其余是修饰;不认识的标签:板书里当代码卡原样显示,首页里退文字卡;
|
|
71
|
+
* 认识但正文解析不出、或这种卡不能用在这里(place)→ 文字卡显示原文 + warning。永不抛错。
|
|
72
|
+
*/
|
|
73
|
+
export function parseCard(tag, body, place = 'board') {
|
|
74
|
+
const [name, ...mods] = tag.trim().split(/\s+/).filter(Boolean);
|
|
75
|
+
const asText = (why) => ({ card: { kind: 'text', props: { text: body.trim() || name || '…' } }, warning: why, fallback: true });
|
|
76
|
+
if (!name)
|
|
77
|
+
return place === 'board' ? { card: { kind: 'code', props: code.parse(body, []) } } : asText('围栏没写种类');
|
|
78
|
+
const kind = cardKind(name.toLowerCase());
|
|
79
|
+
if (!kind)
|
|
80
|
+
return place === 'board' ? { card: { kind: 'code', props: code.parse(body, [name]) } } : asText(`不认识的卡:${name}`);
|
|
81
|
+
if (!usableIn(kind, place))
|
|
82
|
+
return asText(place === 'board' ? `${name} 是首页的卡,板书里不能用` : `首页放不了 ${name} 卡(它要交给某位老师,只能在板书里)`);
|
|
83
|
+
const um = TEXTUAL.has(kind.name) ? unmark(body) : { body, had: false };
|
|
84
|
+
try {
|
|
85
|
+
const props = kind.props.parse(kind.parse(um.body, mods));
|
|
86
|
+
const notes = [um.had ? `卡里的方括号去掉了:${name} — [词] 标注只写在讲稿句里,不写在卡里` : null, kind.note?.(um.body, props) ?? null].filter((x) => Boolean(x));
|
|
87
|
+
return { card: { kind: kind.name, props }, ...(notes.length ? { warning: notes.join(';') } : {}) };
|
|
88
|
+
}
|
|
89
|
+
catch (err) {
|
|
90
|
+
const why = err instanceof z.ZodError ? err.issues.map((i) => `${i.path.join('.')}:${i.message}`).join(';') : err instanceof Error ? err.message : String(err);
|
|
91
|
+
return asText(`卡片没解析成:${name} — ${why}`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/** 孩子端的一节:每张卡过本种卡的 strip(答案不下发);不认识的 kind 原样;孩子自己的状态与已生成的资产照给 */
|
|
95
|
+
export function stripSecrets(section) {
|
|
96
|
+
return {
|
|
97
|
+
...section,
|
|
98
|
+
cards: section.cards.map((c) => {
|
|
99
|
+
// 认不出的种类(删掉的卡:场景 10-07、填空 10-22):老对话里存下的退成一段字,只留它的那句,别的字段(答案、题面)不下发
|
|
100
|
+
const k = cardKind(c.kind);
|
|
101
|
+
if (!k)
|
|
102
|
+
return { ...c, kind: 'text', props: { text: typeof c.props.text === 'string' ? c.props.text : cardLabel(c) } };
|
|
103
|
+
return k.strip ? { ...c, props: k.strip(c.props) } : c;
|
|
104
|
+
}),
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
/** 一张卡的标题(舞台顶栏、给老师的描述里用):文字卡的 title / text,选择题的问题,其余第一段有字的,田字格的字,单词卡的词,听写卡的词表 */
|
|
108
|
+
export function cardLabel(card) {
|
|
109
|
+
const p = card.props;
|
|
110
|
+
const s = (v) => (typeof v === 'string' ? v.trim() : '');
|
|
111
|
+
const first = s(p.title) || s(p.question) || s(p.show) || s(p.text) || s(p.caption) || s(p.prompt) || (Array.isArray(p.segments) ? s(p.segments[0]) : '') || s(p.chars) || s(p.word) || (Array.isArray(p.words) ? p.words.map((w) => s(w?.chars)).filter(Boolean).join('、') : '');
|
|
112
|
+
const cps = Array.from(first.replace(/\s+/g, ' '));
|
|
113
|
+
return cps.length > 40 ? `${cps.slice(0, 40).join('')}…` : cps.join('');
|
|
114
|
+
}
|
|
115
|
+
/** 这张卡要后台预生成的配音(文件名相对它的资产目录);没有的种类 → [] */
|
|
116
|
+
export function cardAssets(card) {
|
|
117
|
+
const k = cardKind(card.kind);
|
|
118
|
+
if (!k?.assets)
|
|
119
|
+
return [];
|
|
120
|
+
const r = k.props.safeParse(card.props);
|
|
121
|
+
return r.success ? k.assets(r.data) : [];
|
|
122
|
+
}
|
|
123
|
+
/** 孩子端 PUT 上来的状态过本种卡的契约;这种卡没有状态、或不认识的 kind → 不收 */
|
|
124
|
+
export function parseCardState(card, raw) {
|
|
125
|
+
const k = cardKind(card.kind);
|
|
126
|
+
if (!k?.state)
|
|
127
|
+
return { ok: false, why: `${card.kind} 卡没有状态` };
|
|
128
|
+
const r = k.state.safeParse(raw);
|
|
129
|
+
if (!r.success)
|
|
130
|
+
return { ok: false, why: r.error.issues.map((i) => `${i.path.join('.')}:${i.message}`).join(';') };
|
|
131
|
+
return { ok: true, state: r.data };
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* 给老师的一句:「choice「问题」 选了「B …」(答案:「…」)」。props 用索引里的(带答案),状态是孩子的;
|
|
135
|
+
* 没有 describe 的种类把状态原样 JSON。id 由调用方拼在前面(<job>/<n>)。
|
|
136
|
+
*/
|
|
137
|
+
export function describeCard(card, state) {
|
|
138
|
+
const k = cardKind(card.kind);
|
|
139
|
+
const head = `${card.kind}「${cardLabel(card)}」`;
|
|
140
|
+
if (!k?.describe || !k.state)
|
|
141
|
+
return `${head} ${JSON.stringify(state)}`;
|
|
142
|
+
const r = k.state.safeParse(state);
|
|
143
|
+
return `${head} ${r.success ? k.describe(card.props, r.data) : JSON.stringify(state)}`;
|
|
144
|
+
}
|
|
@@ -1,14 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* 一种卡的服务端定义(
|
|
2
|
+
* 一种卡的服务端定义(见 docs/卡片协议.md):props 契约、围栏正文怎么解析、哪些字段不下发孩子端;给老师看的写法在包根 cards/<kind>/card.md(src/board/cards/docs.ts 读它);
|
|
3
3
|
* 有交互的卡再加 state 契约(孩子在卡上做的事,PUT 进来先过它)与 describe(把 props + state 说成给老师看的一句,进上下文包)。
|
|
4
|
-
* 页面那一半(紧凑态怎么画、舞台里怎么交互、标注落在哪些字上)在 kid-page.ts /
|
|
4
|
+
* 页面那一半(紧凑态怎么画、舞台里怎么交互、标注落在哪些字上)在 kid-page.ts / board/presentation.ts;两边靠 kind 名对上。
|
|
5
5
|
*/
|
|
6
6
|
import type { z } from 'zod';
|
|
7
|
+
/** 卡用在哪:板书(老师的回复)/ 首页(家长批准的那页) */
|
|
8
|
+
export type CardPlace = 'board' | 'home';
|
|
7
9
|
export interface CardKind<P = Record<string, unknown>, S = unknown> {
|
|
8
10
|
name: string;
|
|
11
|
+
/** 能用在哪;缺省只板书。首页专属的卡(tutor 等)不进 cotutor-board 技能,老师写了退文字卡 */
|
|
12
|
+
where?: readonly CardPlace[];
|
|
9
13
|
props: z.ZodType<P>;
|
|
10
14
|
/** 围栏正文 + 标签后的修饰词 → props;抛错 = 没解析成(退成文字卡显示原文,家长视图报一行) */
|
|
11
15
|
parse(body: string, mods: readonly string[]): P;
|
|
16
|
+
/** 解析成了、但正文有一部分没用上(田字格的拼音对不上字数):给家长视图的一句;没有 / null = 不报 */
|
|
17
|
+
note?(body: string, props: P): string | null;
|
|
12
18
|
/** 剥掉不下发孩子端的字段(答案);没有 = 全给 */
|
|
13
19
|
strip?(props: P): P;
|
|
14
20
|
/** 孩子在卡上做的事的形状;没有 = 这种卡没有状态,PUT 一律 400 */
|
|
@@ -20,8 +26,8 @@ export interface CardKind<P = Record<string, unknown>, S = unknown> {
|
|
|
20
26
|
file: string;
|
|
21
27
|
text: string;
|
|
22
28
|
}[];
|
|
23
|
-
/** 语法表里的一段:写法 + 例子(给老师看),由 boardSyntaxDoc 拼成 .cotutor/板书语法.md */
|
|
24
|
-
doc: string;
|
|
25
29
|
}
|
|
30
|
+
/** 课包 / 视频小课堂的 id(bundles/<id>/、lectures/<id>/):lecture 卡、画板的底、首页的小课堂按钮共用 */
|
|
31
|
+
export declare const BUNDLE_ID_RE: RegExp;
|
|
26
32
|
/** 围栏正文 → 非空行(各自 trim) */
|
|
27
33
|
export declare function bodyLines(body: string): string[];
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** 课包 / 视频小课堂的 id(bundles/<id>/、lectures/<id>/):lecture 卡、画板的底、首页的小课堂按钮共用 */
|
|
2
|
+
export const BUNDLE_ID_RE = /^[a-z0-9][a-z0-9-]{0,80}$/;
|
|
3
|
+
/** 围栏正文 → 非空行(各自 trim) */
|
|
4
|
+
export function bodyLines(body) {
|
|
5
|
+
return body
|
|
6
|
+
.split('\n')
|
|
7
|
+
.map((l) => l.trim())
|
|
8
|
+
.filter(Boolean);
|
|
9
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
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 { type CardKind } from './kind.ts';
|
|
9
|
+
export declare const LecturePropsSchema: z.ZodObject<{
|
|
10
|
+
bundle: z.ZodString;
|
|
11
|
+
from: z.ZodOptional<z.ZodNumber>;
|
|
12
|
+
to: z.ZodOptional<z.ZodNumber>;
|
|
13
|
+
text: z.ZodOptional<z.ZodString>;
|
|
14
|
+
title: z.ZodOptional<z.ZodString>;
|
|
15
|
+
start: z.ZodOptional<z.ZodNumber>;
|
|
16
|
+
end: z.ZodOptional<z.ZodNumber>;
|
|
17
|
+
still: z.ZodOptional<z.ZodNumber>;
|
|
18
|
+
ready: z.ZodOptional<z.ZodBoolean>;
|
|
19
|
+
video: z.ZodOptional<z.ZodBoolean>;
|
|
20
|
+
}, z.core.$strip>;
|
|
21
|
+
export type LectureProps = z.infer<typeof LecturePropsSchema>;
|
|
22
|
+
export declare const LectureStateSchema: z.ZodObject<{
|
|
23
|
+
done: z.ZodBoolean;
|
|
24
|
+
}, z.core.$strip>;
|
|
25
|
+
export type LectureState = z.infer<typeof LectureStateSchema>;
|
|
26
|
+
export declare const lecture: CardKind<LectureProps, LectureState>;
|
|
@@ -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>;
|