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.
- package/LICENSE +247 -21
- package/NOTICE +42 -0
- package/README.md +107 -24
- 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/app/cli/cert.d.ts +7 -0
- package/dist/app/cli/cert.js +36 -0
- 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/app/cli/doctor.d.ts +23 -0
- 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/app/cli/serve.d.ts +37 -0
- 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/app/cli/tutors.d.ts +73 -0
- package/dist/app/cli/tutors.js +250 -0
- 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/app/http/stage.d.ts +24 -0
- package/dist/app/http/stage.js +97 -0
- 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/app/mock/mock.d.ts +89 -0
- 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 +82 -36
- 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/board/cards/choice.d.ts +20 -0
- package/dist/board/cards/choice.js +64 -0
- package/dist/board/cards/code.d.ts +9 -0
- package/dist/board/cards/code.js +10 -0
- 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/board/cards/image.d.ts +13 -0
- package/dist/board/cards/image.js +26 -0
- package/dist/board/cards/index.d.ts +62 -0
- package/dist/board/cards/index.js +144 -0
- package/dist/board/cards/kind.d.ts +33 -0
- 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/board/cards/read.d.ts +8 -0
- package/dist/board/cards/read.js +18 -0
- 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 -8
- package/dist/lib/index.js +14 -8
- 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 +3 -1
- package/dist/{lib → memory}/plan.js +10 -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/memory/timetable.d.ts +19 -0
- package/dist/memory/timetable.js +95 -0
- 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 -32
- 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 +200 -0
- package/dist/schema/board.js +42 -0
- package/dist/schema/config.d.ts +353 -80
- package/dist/schema/config.js +293 -76
- package/dist/schema/context-pack.d.ts +82 -13
- package/dist/schema/context-pack.js +97 -10
- package/dist/schema/conversation-files.d.ts +43 -0
- package/dist/schema/conversation-files.js +26 -0
- package/dist/schema/conversation.d.ts +459 -13
- package/dist/schema/conversation.js +148 -8
- 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 +19 -4
- package/dist/schema/index.js +19 -4
- package/dist/schema/json-schema.d.ts +2 -0
- package/dist/schema/json-schema.js +23 -0
- package/dist/schema/kid-device.d.ts +20 -0
- package/dist/schema/kid-device.js +32 -0
- package/dist/schema/ledger.d.ts +9 -64
- 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 +26 -0
- package/dist/schema/timetable.js +18 -0
- 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/Assistant-Bold-ZDZZ6JHA.woff2 +0 -0
- package/dist/stage/Assistant-Medium-DZ25RZU3.woff2 +0 -0
- package/dist/stage/Assistant-Regular-PLF2XOGW.woff2 +0 -0
- package/dist/stage/Assistant-SemiBold-CZ5MX6FK.woff2 +0 -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 +11 -0
- package/dist/stage/stage.css +1 -0
- package/dist/stage/stage.js +1 -0
- 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 +32 -12
- 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-teacher.md +0 -19
- package/agents/homework-aide.md +0 -17
- package/agents/math-teacher.md +0 -19
- package/agents/planner.md +0 -18
- package/agents/reading-teacher.md +0 -19
- package/dist/cli/doctor.d.ts +0 -19
- package/dist/cli/doctor.js +0 -190
- package/dist/cli/init.js +0 -114
- package/dist/cli/main.js +0 -123
- package/dist/cli/serve.d.ts +0 -19
- package/dist/cli/serve.js +0 -22
- package/dist/cli/skeleton.d.ts +0 -21
- package/dist/cli/skeleton.js +0 -82
- package/dist/cli/workspace.d.ts +0 -61
- package/dist/lib/agent-file.d.ts +0 -10
- package/dist/lib/agent-file.js +0 -16
- package/dist/lib/context-pack.js +0 -46
- package/dist/lib/conversation.d.ts +0 -28
- package/dist/lib/conversation.js +0 -44
- package/dist/lib/kid-view.d.ts +0 -26
- package/dist/lib/kid-view.js +0 -38
- package/dist/lib/ledger.d.ts +0 -21
- package/dist/lib/sections.d.ts +0 -12
- package/dist/lib/sections.js +0 -151
- package/dist/lib/transcript.d.ts +0 -36
- package/dist/lib/transcript.js +0 -95
- package/dist/server/app.d.ts +0 -13
- package/dist/server/app.js +0 -45
- /package/dist/{cli → app/cli}/main.d.ts +0 -0
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 板书解析器:老师的回复正文(已剥掉「记账」段)→ 一节 BoardSection。
|
|
3
|
+
* 三条规则(见 docs/卡片协议.md):围栏 = 卡(标签第一个词是 kind),普通行 = 讲稿一句,第一个 H2 起是给家长的尾巴。
|
|
4
|
+
* 讲稿句里 [词] 是标注(落到第一张含这个词的卡,整节找,卡在前在后都行),[[名 参数]] 是对上一张卡的动作(cue)。
|
|
5
|
+
* partial 模式给流式用:没闭合的围栏和没换行结束的最后一行压着不算,下次整段重解析自然补上。
|
|
6
|
+
* 永不抛错:围栏没闭合当到文末,卡解析不出退成文字卡并记一句 warning。
|
|
7
|
+
* spans 是「这张卡 / 这句话是原文哪几行」,家长端「看原文」据此在原文旁边标出解析器怎么读的;孩子端的 BoardSection 不带它。
|
|
8
|
+
*/
|
|
9
|
+
import { parseCard } from "./cards/index.js";
|
|
10
|
+
import { anchorMarks, hasState, isAskCard, isHeading, isQuestion, lineTarget, MAX_CARDS_PER_ROW, phrasesIn, plainLine, standsAlone } from "./presentation.js";
|
|
11
|
+
import { parseSections } from "./sections.js";
|
|
12
|
+
const MOD_RE = /^(tint|look|emoji)=(.+)$/i;
|
|
13
|
+
export function splitMods(tag) {
|
|
14
|
+
const mods = {};
|
|
15
|
+
const warnings = [];
|
|
16
|
+
const rest = [];
|
|
17
|
+
for (const w of tag.trim().split(/\s+/).filter(Boolean)) {
|
|
18
|
+
if (w.toLowerCase() === 'same') {
|
|
19
|
+
mods.same = true;
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
const m = MOD_RE.exec(w);
|
|
23
|
+
if (!m) {
|
|
24
|
+
rest.push(w);
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
const key = m[1].toLowerCase();
|
|
28
|
+
const v = m[2];
|
|
29
|
+
if (key === 'emoji' && (Array.from(v).length > 2 || /[A-Za-z0-9]/.test(v))) {
|
|
30
|
+
warnings.push(`emoji=${v} 不像一个 emoji,不要了`);
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
mods[key] = v;
|
|
34
|
+
}
|
|
35
|
+
return { rest: rest.join(' '), mods, warnings };
|
|
36
|
+
}
|
|
37
|
+
/** 尾巴的末行:掐掉后面的空行,免得「看原文」把末尾空行也染成家长段 */
|
|
38
|
+
function tailTo(lines, from) {
|
|
39
|
+
let k = lines.length - 1;
|
|
40
|
+
while (k > from && !lines[k].trim())
|
|
41
|
+
k--;
|
|
42
|
+
return k;
|
|
43
|
+
}
|
|
44
|
+
const FENCE_OPEN = /^ {0,3}(`{3,}|~{3,})(.*)$/;
|
|
45
|
+
const H2 = /^##\s+\S/;
|
|
46
|
+
const CUE = /\[\[([^\[\]]+)\]\]/g;
|
|
47
|
+
function fenceClose(line, fence) {
|
|
48
|
+
const m = /^ {0,3}(`{3,}|~{3,})\s*$/.exec(line);
|
|
49
|
+
return Boolean(m && m[1][0] === fence[0] && m[1].length >= fence.length);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* 写成正文的工具调用:这轮没有那个工具时,qwen 照它自己的格式把调用写进正文——`<tool_call>` 独占一行起、`</tool_call>` 止
|
|
53
|
+
* (中间是 `<function=Read>` `<parameter=…>` 几行或一行 JSON),也见过不带外层的 `<function=名>` … `</function>`。
|
|
54
|
+
* 整块不是讲稿:板上不出、嘴不念(10-21 Ray 交画那轮,这 7 行在板上、嘴念了 25 秒)
|
|
55
|
+
*/
|
|
56
|
+
const TOOL_OPEN = /^\s*<(tool_call|function=[^>\s]+)>\s*$/;
|
|
57
|
+
const toolClose = (open) => (open === 'tool_call' ? /^\s*<\/tool_call>\s*$/ : /^\s*<\/function>\s*$/);
|
|
58
|
+
/** 块里调的是哪个工具:`<function=名>` 或 JSON 的 "name" */
|
|
59
|
+
function toolName(block) {
|
|
60
|
+
for (const l of block) {
|
|
61
|
+
const m = /<function=([^>\s]+)>/.exec(l) ?? /"name"\s*:\s*"([^"]+)"/.exec(l);
|
|
62
|
+
if (m)
|
|
63
|
+
return m[1];
|
|
64
|
+
}
|
|
65
|
+
return '?';
|
|
66
|
+
}
|
|
67
|
+
/** 讲稿一行的清洗:去掉老师不该写但常写的标题号、列表号、引用号、粗体号;整行的 HTML 注释不算话 */
|
|
68
|
+
export function cleanSpeech(line) {
|
|
69
|
+
const t = line.trim();
|
|
70
|
+
if (/^<!--.*-->$/.test(t))
|
|
71
|
+
return '';
|
|
72
|
+
return t
|
|
73
|
+
.replace(/^#{1,6}\s+/, '')
|
|
74
|
+
.replace(/^(?:[-*+]|\d+[.)])\s+/, '')
|
|
75
|
+
.replace(/^>\s*/, '')
|
|
76
|
+
.replace(/\*\*/g, '')
|
|
77
|
+
.trim();
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* 热身的记号:不锚卡,记在这句上。[[echo 词]] 跟我说、[[say 词]] 你先说(念完等孩子说「词」),[[call]] 念完进打电话。
|
|
81
|
+
* echo 没写词就取这句里的英文;一句写了几个,算最后一个
|
|
82
|
+
*/
|
|
83
|
+
const LINE_MARKS = new Set(['echo', 'say', 'call']);
|
|
84
|
+
const englishIn = (text) => (text.match(/[A-Za-z][A-Za-z']*/g) ?? []).join(' ');
|
|
85
|
+
/** 句子锚到上一张卡;小节标题行不算卡,跳过它 */
|
|
86
|
+
function lastCard(cards) {
|
|
87
|
+
for (let k = cards.length - 1; k >= 0; k--)
|
|
88
|
+
if (!isHeading(cards[k]))
|
|
89
|
+
return k;
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
function rawLine(line, cards, at) {
|
|
93
|
+
const anchor = lastCard(cards);
|
|
94
|
+
const cues = [];
|
|
95
|
+
let mark = null;
|
|
96
|
+
const text = line
|
|
97
|
+
.replace(CUE, (_, inner) => {
|
|
98
|
+
const [name, ...rest] = inner.trim().split(/\s+/);
|
|
99
|
+
const n = (name ?? '').toLowerCase();
|
|
100
|
+
if (LINE_MARKS.has(n))
|
|
101
|
+
mark = { name: n, arg: rest.join(' ') };
|
|
102
|
+
else if (name && anchor !== null)
|
|
103
|
+
cues.push({ card: anchor, name: n, ...(rest.length ? { arg: rest.join(' ') } : {}) });
|
|
104
|
+
return '';
|
|
105
|
+
})
|
|
106
|
+
.replace(/\s{2,}/g, ' ')
|
|
107
|
+
.trim();
|
|
108
|
+
const m = mark;
|
|
109
|
+
if (!m)
|
|
110
|
+
return { text, anchor, cues, line: at };
|
|
111
|
+
if (m.name === 'call')
|
|
112
|
+
return { text, anchor, cues, line: at, call: true };
|
|
113
|
+
const word = m.arg || (m.name === 'echo' ? englishIn(text) : '');
|
|
114
|
+
return { text, anchor, cues, line: at, echo: { word, ...(m.name === 'say' ? { say: true } : {}) } };
|
|
115
|
+
}
|
|
116
|
+
/** 一句讲稿交给嘴时要带的:[[play]] 到小课堂卡、热身的 echo / say、call(runner 的 line 事件、mock 的假嘴都用它) */
|
|
117
|
+
export function lineFlags(line, cards) {
|
|
118
|
+
return { ...(playsLecture(line, cards) ? { play: true } : {}), ...(line.echo ? { echo: line.echo } : {}), ...(line.call ? { call: true } : {}) };
|
|
119
|
+
}
|
|
120
|
+
/** 这句的 [[play]] 锚着小课堂卡:念完放卡上那一段(实时时服务端在这句之后等孩子端放完再交讲稿,src/runtime/delivery/queue.ts) */
|
|
121
|
+
export function playsLecture(line, cards) {
|
|
122
|
+
return (line.cues ?? []).some((c) => c.name === 'play' && cards[c.card]?.kind === 'lecture');
|
|
123
|
+
}
|
|
124
|
+
export function parseBoard(text, opts = {}) {
|
|
125
|
+
const partial = opts.partial === true;
|
|
126
|
+
const all = text.split('\n');
|
|
127
|
+
const lines = partial && !text.endsWith('\n') ? all.slice(0, -1) : all;
|
|
128
|
+
const cards = [];
|
|
129
|
+
const cardSpans = [];
|
|
130
|
+
/** 每张卡围栏行上的排版修饰词(与 cards 同序;没写就是空对象) */
|
|
131
|
+
const mods = [];
|
|
132
|
+
const raws = [];
|
|
133
|
+
const warnings = [];
|
|
134
|
+
const toolCalls = [];
|
|
135
|
+
let tail = null;
|
|
136
|
+
let tailFrom = -1;
|
|
137
|
+
let i = 0;
|
|
138
|
+
while (i < lines.length) {
|
|
139
|
+
const line = lines[i];
|
|
140
|
+
if (tail) {
|
|
141
|
+
tail.push(line);
|
|
142
|
+
i++;
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
const call = TOOL_OPEN.exec(line);
|
|
146
|
+
if (call) {
|
|
147
|
+
const close = toolClose(call[1]);
|
|
148
|
+
let j = i + 1;
|
|
149
|
+
while (j < lines.length && !close.test(lines[j]))
|
|
150
|
+
j++;
|
|
151
|
+
// 和围栏一样:流式时没收尾的块压着,后面的也不出
|
|
152
|
+
if (j >= lines.length && partial)
|
|
153
|
+
break;
|
|
154
|
+
const end = Math.min(j, lines.length - 1);
|
|
155
|
+
toolCalls.push([i, end]);
|
|
156
|
+
warnings.push({ text: `老师把工具调用写成了正文(${toolName(lines.slice(i, end + 1))}),不进板书`, line: i });
|
|
157
|
+
i = end + 1;
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
const open = FENCE_OPEN.exec(line);
|
|
161
|
+
if (open) {
|
|
162
|
+
const fence = open[1];
|
|
163
|
+
const tag = open[2].trim();
|
|
164
|
+
const body = [];
|
|
165
|
+
let j = i + 1;
|
|
166
|
+
let closed = false;
|
|
167
|
+
for (; j < lines.length; j++) {
|
|
168
|
+
if (fenceClose(lines[j], fence)) {
|
|
169
|
+
closed = true;
|
|
170
|
+
break;
|
|
171
|
+
}
|
|
172
|
+
body.push(lines[j]);
|
|
173
|
+
}
|
|
174
|
+
if (!closed && partial)
|
|
175
|
+
break;
|
|
176
|
+
if (!closed)
|
|
177
|
+
warnings.push({ text: `围栏没闭合(${tag || '无标签'}),当到文末`, line: i });
|
|
178
|
+
const sm = splitMods(tag);
|
|
179
|
+
const r = parseCard(sm.rest, body.join('\n'), opts.place);
|
|
180
|
+
const look = { ...(sm.mods.tint ? { tint: sm.mods.tint } : {}), ...(sm.mods.look ? { look: sm.mods.look } : {}), ...(sm.mods.emoji ? { emoji: sm.mods.emoji } : {}) };
|
|
181
|
+
cards.push(Object.keys(look).length && !isHeading(r.card) ? { ...r.card, look } : r.card);
|
|
182
|
+
mods.push(sm.mods);
|
|
183
|
+
cardSpans.push([i, closed ? j : Math.max(i, j - 1)]);
|
|
184
|
+
for (const w of sm.warnings)
|
|
185
|
+
warnings.push({ text: w, line: i });
|
|
186
|
+
if (r.warning)
|
|
187
|
+
warnings.push({ text: r.warning, line: i, ...(r.fallback ? { fallback: true } : {}) });
|
|
188
|
+
i = closed ? j + 1 : j;
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
if (H2.test(line)) {
|
|
192
|
+
tail = [line];
|
|
193
|
+
tailFrom = i;
|
|
194
|
+
i++;
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
const speech = cleanSpeech(line);
|
|
198
|
+
if (speech)
|
|
199
|
+
raws.push(rawLine(speech, cards, i));
|
|
200
|
+
i++;
|
|
201
|
+
}
|
|
202
|
+
// 标注整节找(老师把卡写在句子后面也认),所以卡收齐了再落
|
|
203
|
+
const kept = raws.filter((r) => r.text);
|
|
204
|
+
const out = kept.map((r) => {
|
|
205
|
+
const marks = anchorMarks(cards, phrasesIn(r.text));
|
|
206
|
+
const plain = plainLine(r.text);
|
|
207
|
+
return { text: plain, audio: null, marks, ask: isQuestion(plain), anchor: r.anchor, cues: r.cues, ...(r.echo ? { echo: r.echo } : {}), ...(r.call ? { call: true } : {}) };
|
|
208
|
+
});
|
|
209
|
+
// 排版:有卡写了 same 才排行(明写的并排,其余孩子端按宽度排);接不上(上一行满了、有独占一行的卡)就另起一行并提醒。提问卡(下面补的)不在行里,rowsFor 认前缀
|
|
210
|
+
let layout;
|
|
211
|
+
if (mods.some((m) => m.same)) {
|
|
212
|
+
const rows = [];
|
|
213
|
+
cards.forEach((c, n) => {
|
|
214
|
+
const last = rows[rows.length - 1];
|
|
215
|
+
const join = mods[n].same && last !== undefined && last.length < MAX_CARDS_PER_ROW && !standsAlone(c) && !last.some((i) => standsAlone(cards[i]));
|
|
216
|
+
if (mods[n].same && !join)
|
|
217
|
+
warnings.push({ text: `卡 ${n + 1} 写了 same,接不上上一行(${last === undefined ? '它是第一张' : last.length >= MAX_CARDS_PER_ROW ? `上一行已有 ${MAX_CARDS_PER_ROW} 张` : '有独占一行的卡'}),另起一行`, line: cardSpans[n][0] });
|
|
218
|
+
if (join)
|
|
219
|
+
last.push(n);
|
|
220
|
+
else
|
|
221
|
+
rows.push([n]);
|
|
222
|
+
});
|
|
223
|
+
layout = { for: opts.device ?? 'tablet-landscape', rows };
|
|
224
|
+
}
|
|
225
|
+
// 提问卡(2026-09-21):末句问句是孩子要答的那句,念完不能只剩字幕——没配能答的卡(choice / fill / canvas)就在节尾补一张文字卡写着这句。
|
|
226
|
+
// 末句的锚点不动(还在它讲的那张卡的拍里);提问卡自己一拍、没有讲稿。
|
|
227
|
+
// 老师还在写(partial)时不补:这时的末句不一定是最后一句。首页没有讲稿,不管;实时不补(板上放什么由脑定)
|
|
228
|
+
const lastLine = out[out.length - 1];
|
|
229
|
+
if (!partial && !opts.live && (opts.place ?? 'board') === 'board' && lastLine?.ask && !lastLine.cues.length && !lastLine.echo && !lastLine.call) {
|
|
230
|
+
const t = lineTarget(lastLine);
|
|
231
|
+
// 拍给我看卡也算能答:孩子拍来的照片进它的答案栏(board/presentation.ts 的 askCard)
|
|
232
|
+
const answerable = (c) => Boolean(c && (hasState(c) || c.kind === 'photo'));
|
|
233
|
+
if (!cards.some((c) => c.kind === 'photo') && !answerable(t === null ? undefined : cards[t]) && !answerable(cards[cards.length - 1])) {
|
|
234
|
+
cards.push({ kind: 'text', props: { text: lastLine.text, ask: true } });
|
|
235
|
+
cardSpans.push([kept[kept.length - 1].line, kept[kept.length - 1].line]);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return {
|
|
239
|
+
section: { cards, lines: out, ...(partial ? { partial: true } : {}), ...(layout ? { layout } : {}) },
|
|
240
|
+
warnings,
|
|
241
|
+
tail: tail ? tail.join('\n').trim() : '',
|
|
242
|
+
spans: {
|
|
243
|
+
cards: cardSpans,
|
|
244
|
+
lines: kept.map((r) => [r.line, r.line]),
|
|
245
|
+
tail: tail ? [tailFrom, tailTo(lines, tailFrom)] : null,
|
|
246
|
+
toolCalls,
|
|
247
|
+
},
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
/** 回复停在写成正文的工具调用上(后面只剩空行):老师在等工具的结果,这一轮其实没写完(runner 据此 resume 一次) */
|
|
251
|
+
export function endsWithToolCall(text) {
|
|
252
|
+
const { spans } = parseBoard(text);
|
|
253
|
+
const last = spans.toolCalls[spans.toolCalls.length - 1];
|
|
254
|
+
return Boolean(last) && text.split('\n').slice(last[1] + 1).every((l) => !l.trim());
|
|
255
|
+
}
|
|
256
|
+
const SECTION_HEAD = /^##\s+(.+?)\s*$/;
|
|
257
|
+
/**
|
|
258
|
+
* 家长端「看原文」用:把老师原文的每一行标上解析器怎么读的。
|
|
259
|
+
* 不另写一套解析——真跑 parseSections + parseBoard,再把它们的行号映回原文,所以永远不会和真解析漂开。
|
|
260
|
+
*/
|
|
261
|
+
export function annotateSource(text, opts = {}) {
|
|
262
|
+
const src = text.split('\n');
|
|
263
|
+
const { body, lineMap } = parseSections(text);
|
|
264
|
+
const board = parseBoard(body, opts);
|
|
265
|
+
const rows = src.map((t, line) => ({ line, text: t, role: t.trim() ? 'drop' : 'blank' }));
|
|
266
|
+
// 固定段吃掉的行:不在 lineMap 里的非空行,标题从上面最近的那个 H2 取
|
|
267
|
+
const keptSet = new Set(lineMap);
|
|
268
|
+
let head = '';
|
|
269
|
+
for (let i = 0; i < src.length; i++) {
|
|
270
|
+
const m = SECTION_HEAD.exec(src[i]);
|
|
271
|
+
if (m)
|
|
272
|
+
head = m[1];
|
|
273
|
+
if (keptSet.has(i) || !src[i].trim())
|
|
274
|
+
continue;
|
|
275
|
+
rows[i].role = 'section';
|
|
276
|
+
rows[i].label = head ? `段「${head}」· 不进板书` : '不进板书';
|
|
277
|
+
}
|
|
278
|
+
const at = (bodyLine) => lineMap[bodyLine];
|
|
279
|
+
board.spans.cards.forEach((span, n) => {
|
|
280
|
+
const card = board.section.cards[n];
|
|
281
|
+
// 提问卡是解析器补的,原文里没有它的围栏
|
|
282
|
+
if (isAskCard(card))
|
|
283
|
+
return;
|
|
284
|
+
for (let b = span[0]; b <= span[1]; b++) {
|
|
285
|
+
const i = at(b);
|
|
286
|
+
if (i === undefined)
|
|
287
|
+
continue;
|
|
288
|
+
rows[i].role = 'card';
|
|
289
|
+
rows[i].index = n;
|
|
290
|
+
if (b === span[0]) {
|
|
291
|
+
rows[i].open = true;
|
|
292
|
+
const style = typeof card.props.style === 'string' ? ` ${card.props.style}` : '';
|
|
293
|
+
rows[i].label = `卡 ${n + 1} · ${card.kind}${style}`;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
});
|
|
297
|
+
board.spans.lines.forEach((span, n) => {
|
|
298
|
+
const i = at(span[0]);
|
|
299
|
+
if (i === undefined)
|
|
300
|
+
return;
|
|
301
|
+
rows[i].role = 'say';
|
|
302
|
+
rows[i].index = n;
|
|
303
|
+
const l = board.section.lines[n];
|
|
304
|
+
const waits = l.ask && n === board.section.lines.length - 1;
|
|
305
|
+
const asked = waits && board.section.cards.some(isAskCard);
|
|
306
|
+
rows[i].label = `讲稿 ${n + 1}${waits ? ` · 问句,停下等${asked ? '(补提问卡)' : ''}` : ' · 播'}`;
|
|
307
|
+
});
|
|
308
|
+
// 整块照旧是 drop,开头那行点名
|
|
309
|
+
for (const span of board.spans.toolCalls) {
|
|
310
|
+
const i = at(span[0]);
|
|
311
|
+
if (i !== undefined)
|
|
312
|
+
rows[i].label = '写成正文的工具调用 · 不进板书';
|
|
313
|
+
}
|
|
314
|
+
if (board.spans.tail) {
|
|
315
|
+
for (let b = board.spans.tail[0]; b <= board.spans.tail[1]; b++) {
|
|
316
|
+
const i = at(b);
|
|
317
|
+
if (i === undefined)
|
|
318
|
+
continue;
|
|
319
|
+
rows[i].role = 'tail';
|
|
320
|
+
if (b === board.spans.tail[0])
|
|
321
|
+
rows[i].label = '家长尾巴 · 孩子看不到';
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
return {
|
|
325
|
+
rows,
|
|
326
|
+
warnings: board.warnings.map((w) => ({ text: w.text, ...(w.line !== undefined && at(w.line) !== undefined ? { line: at(w.line) } : {}) })),
|
|
327
|
+
section: board.section,
|
|
328
|
+
tail: board.tail,
|
|
329
|
+
};
|
|
330
|
+
}
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 板书(孩子端老师页)的纯逻辑:卡片 JSON 契约、标注锚点、播放状态机、字幕行与输入条的状态。
|
|
3
|
+
* 这份文件两处共用:服务端(解析器、测试)与孩子端页面——kid-page.ts 把它剥掉类型内联进 <script>,
|
|
4
|
+
* 所以**不能有运行时 import、不能碰 DOM、不能用 enum / namespace**(Node 的 stripTypeScriptTypes 只剥类型)。
|
|
5
|
+
*
|
|
6
|
+
* 契约的分工(见 docs/卡片协议.md):老师写「段落 = 讲稿,围栏 = 卡」的正文,服务端(src/board/parse.ts + src/board/cards/)解析成
|
|
7
|
+
* 下面的 BoardSection JSON 放进对话索引;孩子端只认 JSON。卡 = {kind, props},每种卡的 props 契约在 src/board/cards/<kind>.ts;
|
|
8
|
+
* 这里只知道每种卡「哪些字能被标注、笔是什么样」,不认识的 kind 也有兜底。
|
|
9
|
+
*/
|
|
10
|
+
import type { BoardCard, CardLook, PenName, Device, BoardLayout, BoardMark, BoardCue, BoardLine, BoardSection } from '../schema/board.ts';
|
|
11
|
+
export type { BoardCard, CardLook, PenName, Device, BoardLayout, BoardMark, BoardCue, BoardLine, BoardSection };
|
|
12
|
+
export declare const LINE_PENS: readonly PenName[];
|
|
13
|
+
/**
|
|
14
|
+
* 拍:一张卡 + 它后面直到下一张卡之前的讲稿句;第一张卡之前的句子是没有卡的一拍。
|
|
15
|
+
* 不进契约,从卡与句的顺序现算——句子锚到上一张卡(anchor),所以按 anchor 分组。
|
|
16
|
+
*/
|
|
17
|
+
export interface Beat {
|
|
18
|
+
card: number | null;
|
|
19
|
+
lines: number[];
|
|
20
|
+
}
|
|
21
|
+
export declare function beatsOf(section: Pick<BoardSection, 'cards' | 'lines'>): Beat[];
|
|
22
|
+
/**
|
|
23
|
+
* 流式时前几拍就绪了:一拍要「关了」(后面已经有下一张卡,或老师写完了)。讲稿不配音,不等配音。
|
|
24
|
+
* 返回就绪的拍数(前缀:第 k 拍就绪的前提是前面都就绪)。
|
|
25
|
+
*/
|
|
26
|
+
export declare function readyBeats(section: Pick<BoardSection, 'cards' | 'lines'>, opts: {
|
|
27
|
+
done: boolean;
|
|
28
|
+
}): number;
|
|
29
|
+
/** 一张卡上所有能被标注的文字;不认识的 kind 拿 props 里所有字符串 */
|
|
30
|
+
export declare function cardTexts(card: BoardCard): string[];
|
|
31
|
+
/**
|
|
32
|
+
* 词在一段字里的位置,数字与拉丁词按整词算(「5」不落在「25」里、「an」不落在「and」里),中文照子串;没有 → -1。
|
|
33
|
+
* 标注锚点(anchorMarks)与页面画笔的落点都用它,两处一条规则。
|
|
34
|
+
*/
|
|
35
|
+
export declare function findPhrase(text: string, phrase: string): number;
|
|
36
|
+
/** 讲稿里方括号的词落到哪张卡:第一张含这个词(整词,见 findPhrase)的卡;找不到的词丢掉(只出字幕,不报错) */
|
|
37
|
+
export declare function anchorMarks(cards: readonly BoardCard[], phrases: readonly string[]): BoardMark[];
|
|
38
|
+
/** 讲稿一句里的 [词] → 词列表;顺序保留 */
|
|
39
|
+
export declare function phrasesIn(line: string): string[];
|
|
40
|
+
/** 去掉讲稿一句里的方括号(念的时候不念括号) */
|
|
41
|
+
export declare function plainLine(line: string): string;
|
|
42
|
+
/** 小节标题(text 卡只有一行 `# 标题`):渲染成无底加粗一行,不算一张卡——不选中、不标注、不并排 */
|
|
43
|
+
export declare function isHeading(card: BoardCard): boolean;
|
|
44
|
+
/** 提问卡:末句问句没配能答的卡时解析器补的那张文字卡(《卡片协议.md》);字就是那句问话,独占一行 */
|
|
45
|
+
export declare function isAskCard(card: BoardCard): boolean;
|
|
46
|
+
/**
|
|
47
|
+
* 底色槽(机械规则;卡上写了 look.tint 就用它):做题的卡紫(plum),定义 / 结论蓝(sky),方法绿(moss),事实 / 例子 / 引言米(sand),
|
|
48
|
+
* 公式 / 图 / 代码白(paper)。名字对不上主题清单的,CSS 落回 paper。
|
|
49
|
+
*/
|
|
50
|
+
export declare function tintFor(card: BoardCard): string;
|
|
51
|
+
/** 字形槽(机械规则;卡上写了 look.look 就用它):formula → formula(衬线),其余 plain */
|
|
52
|
+
export declare function lookFor(card: BoardCard): string;
|
|
53
|
+
/**
|
|
54
|
+
* 笔(机械规则;标注带了 pen 就用它):选项 → 方框;填空、数字与拉丁词 → 下划线;点读段、公式、大字 → 荧光;
|
|
55
|
+
* 标题位上的词 → 圈;其余(正文里正在定义的词)→ 术语底。
|
|
56
|
+
*/
|
|
57
|
+
export declare function penFor(card: BoardCard, phrase: string): PenName;
|
|
58
|
+
/** 一行最多几张:明写的并排(课文件 / 老师的 same)能到 3 张;按宽度排的最多 2 张(半宽 + 半宽) */
|
|
59
|
+
export declare const MAX_CARDS_PER_ROW = 3;
|
|
60
|
+
/** 独占一行的卡:标题行、提问卡、画板、小课堂、画图、拍给我看(选择题量得下就能半宽,2026-10-01) */
|
|
61
|
+
export declare function standsAlone(card: BoardCard): boolean;
|
|
62
|
+
/** 能半宽的种类:文字、点读、代码、田字格、单词卡、选择题、填空题。字形(大字等)不算:字大放不下,量出来自然是全宽 */
|
|
63
|
+
export declare function canHalf(card: BoardCard): boolean;
|
|
64
|
+
/** 半宽时文字卡与点读最多几行(小标题也算一行);手机的半宽只有 170 来像素,一行七八个字,只放得下标题加一行 */
|
|
65
|
+
export declare const HALF_LINES: Record<Device, number>;
|
|
66
|
+
/** 页面把卡放进量具量出来的数:半宽 / 全宽时卡的高(像素)、半宽时文字有几行、半宽时有没有横着溢出 */
|
|
67
|
+
export interface CardFit {
|
|
68
|
+
half: number;
|
|
69
|
+
full: number;
|
|
70
|
+
lines: number;
|
|
71
|
+
overflow: boolean;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* 量出来的卡能不能半宽:文字卡与点读看行数,不超过 HALF_LINES;
|
|
75
|
+
* 公式、代码、田字格、单词卡、选择题、填空题半宽时不能比全宽高(折了行就是挤了:公式从中间断开没法看,选项挤成两行)。横着溢出的都不行
|
|
76
|
+
*/
|
|
77
|
+
export declare function fitsHalf(card: BoardCard, device: Device, m: CardFit): boolean;
|
|
78
|
+
/** 量不了时的估计(测试;页面还没有宽度时):文字卡,字数 ≤ 20 */
|
|
79
|
+
export declare function isShortCard(card: BoardCard): boolean;
|
|
80
|
+
/**
|
|
81
|
+
* 一节的行(2026-10-01 起排版归代码):每张卡半宽还是全宽,看它自己量出来的样子
|
|
82
|
+
* (half(i),页面在量具里量;没给就按 isShortCard 估)。从左往右排,只看前面的卡:
|
|
83
|
+
* - 相邻两张半宽的并一行;一张半宽后面跟的不是半宽,它自己一行、占左半(右边空着)
|
|
84
|
+
* - 全宽的一行一张;标题行、提问卡、画板、小课堂永远独占
|
|
85
|
+
* - 明写的并排(section.layout 里不止一张的行:课文件 / 老师写的 same)照办,最多 3 张;
|
|
86
|
+
* 别的端排的到了手机上,超过 2 张或有不能半宽的就拆开,再按宽度排
|
|
87
|
+
* 流式一张张来时,前面的行不会因为后来的卡变。
|
|
88
|
+
*/
|
|
89
|
+
export declare function rowsFor(section: BoardSection, device: Device, half?: (i: number) => boolean): number[][];
|
|
90
|
+
/** 一行几列:并排几张就几列;只有一张时,半宽的两列(占左半),全宽的一列 */
|
|
91
|
+
export declare function rowCols(section: BoardSection, row: readonly number[], half?: (i: number) => boolean): number;
|
|
92
|
+
/** 端:宽 ≥ 900 且横 → 平板横屏;短边 ≥ 600 → 平板竖屏;其余手机 */
|
|
93
|
+
export declare function deviceFor(width: number, height: number): Device;
|
|
94
|
+
/** 当前卡(选中态):播到这句该在的那张(lineTarget);句子没锚就是本节第一张不是标题行的卡;没在播 → null */
|
|
95
|
+
export declare function nowCard(sections: readonly BoardSection[], state: PlayerState): number | null;
|
|
96
|
+
export interface PenBox {
|
|
97
|
+
x: number;
|
|
98
|
+
y: number;
|
|
99
|
+
w: number;
|
|
100
|
+
h: number;
|
|
101
|
+
}
|
|
102
|
+
/** 笔画的框:相对被标注文字的一行矩形(宽 w、高 h),笔要伸出去多少 */
|
|
103
|
+
export declare function penBox(pen: PenName, w: number, h: number): PenBox;
|
|
104
|
+
/** 笔画的路径(viewBox 0 0 w h):下划线一笔、方框一圈、圈一圈多一点;seed 定抖动 */
|
|
105
|
+
export declare function penPath(pen: PenName, w: number, h: number, seed: string): string;
|
|
106
|
+
/** 有舞台交互(能改状态、能「交给老师」)的种类;其余点开只是放大看 */
|
|
107
|
+
export declare function hasState(card: BoardCard): boolean;
|
|
108
|
+
/** 画板上画了几笔(状态里的 ink 元素数) */
|
|
109
|
+
export declare function inkCount(card: BoardCard): number;
|
|
110
|
+
/** 重卡:舞台在 iframe 里的舞台包(/stage/)开,页面只管顶栏、字幕行、输入条 */
|
|
111
|
+
export declare function isHeavy(card: BoardCard): boolean;
|
|
112
|
+
/** 小课堂卡能不能放:课包读得出来,下发时服务端填 ready 与那一段的起止 */
|
|
113
|
+
export declare function lectureReady(card: BoardCard): boolean;
|
|
114
|
+
/** 点读第 k 段(0 起)的配音文件(相对 conversations/<老师>/);没生成好 → null(孩子端等它到,等不到不出声) */
|
|
115
|
+
export declare function segmentAudio(card: BoardCard, k: number): string | null;
|
|
116
|
+
/** 孩子在这张卡上做了什么(「交给老师」能不能按):选择题是选项;没做 → [] */
|
|
117
|
+
export declare function stateSummary(card: BoardCard): string[];
|
|
118
|
+
/** shi4 → shì:调号标在 a / e 上,ou 标在 o 上,否则标在最后一个元音上;5 是轻声不标;认不出的原样 */
|
|
119
|
+
export declare function toneMark(syl: string): string;
|
|
120
|
+
/** 舞台顶栏的名字:文字卡的标题 / 正文、选择题的问题、其余第一段有字的;截 24 字 */
|
|
121
|
+
export declare function cardTitle(card: BoardCard): string;
|
|
122
|
+
/** 选择题:点第 i 项后的选中集合——单选换成它(再点取消),多选切换 */
|
|
123
|
+
export declare function togglePick(picked: readonly number[], i: number, multi: boolean): number[];
|
|
124
|
+
/** 选择题当前选了什么(回显与紧凑态用):「B 三个」 */
|
|
125
|
+
export declare function pickedLabels(card: BoardCard): string[];
|
|
126
|
+
export declare function isQuestion(text: string): boolean;
|
|
127
|
+
/** 孩子端条目里页面用到的字段(与 kid-view 的 KidMessage 兼容) */
|
|
128
|
+
/** 孩子端一条带的小课堂:画的卡是截下来的图(没截图的课包现画那一刻再叠那几笔);家长端的画多一段老师拿到的话(text);again = 再看一遍又画的那条 */
|
|
129
|
+
export interface KidLecture {
|
|
130
|
+
bundle: string;
|
|
131
|
+
title: string;
|
|
132
|
+
again?: true;
|
|
133
|
+
video?: true;
|
|
134
|
+
marks?: {
|
|
135
|
+
atMs: number;
|
|
136
|
+
svgMs: number;
|
|
137
|
+
strokes: [number, number][][];
|
|
138
|
+
text?: string;
|
|
139
|
+
image?: string;
|
|
140
|
+
}[];
|
|
141
|
+
}
|
|
142
|
+
/** 孩子从纸上交的画在板上那张卡:图(相对 workspace 根)、几笔、画了多久 */
|
|
143
|
+
export interface KidDrawing {
|
|
144
|
+
image: string;
|
|
145
|
+
strokes: number;
|
|
146
|
+
ms?: number;
|
|
147
|
+
}
|
|
148
|
+
export interface BoardMessage {
|
|
149
|
+
job: string;
|
|
150
|
+
at?: string;
|
|
151
|
+
question: string | null;
|
|
152
|
+
reply: string | null;
|
|
153
|
+
pending: boolean;
|
|
154
|
+
section?: BoardSection | null;
|
|
155
|
+
/** 孩子这条带的作业照片(相对 workspace 根;R5):节头上回显缩略图 */
|
|
156
|
+
photos?: string[];
|
|
157
|
+
/** 看完小课堂后的第一条:这一节前面是小课堂卡 */
|
|
158
|
+
lecture?: KidLecture;
|
|
159
|
+
/** 孩子从左栏的纸交的画:这一节前面是孩子的画卡 */
|
|
160
|
+
drawing?: KidDrawing;
|
|
161
|
+
/** 孩子这条不是说的话:submit = 交卡(答案在卡上) */
|
|
162
|
+
action?: 'submit';
|
|
163
|
+
/** 按住说话的(索引里带 voice):板上去口头禅、一行截断 */
|
|
164
|
+
/** 首页按钮发的:按钮上的字,不是孩子说的 */
|
|
165
|
+
fromHome?: boolean;
|
|
166
|
+
/** 实时的一轮(讲稿嘴照念,不配音) */
|
|
167
|
+
live?: boolean;
|
|
168
|
+
}
|
|
169
|
+
/** 板上孩子的一句话:text 是显示的(语音去了口头禅),full 是原话 */
|
|
170
|
+
export interface KidSaid {
|
|
171
|
+
text: string;
|
|
172
|
+
full: string;
|
|
173
|
+
/** 答拍给我看卡时拍来的照片:进那张卡的答案栏,节头不再回显 */
|
|
174
|
+
photos?: string[];
|
|
175
|
+
}
|
|
176
|
+
export interface BoardEntry extends BoardSection {
|
|
177
|
+
job: string;
|
|
178
|
+
at?: string;
|
|
179
|
+
/** 老师还在说:卡只增不改;前 ready 拍就绪了就能播(2026-09-13 之前是整轮跑完才播);整轮跑完换成正式的一节 */
|
|
180
|
+
partial?: boolean;
|
|
181
|
+
/** 孩子问这节时拍的照片(节头上回显) */
|
|
182
|
+
photos?: string[];
|
|
183
|
+
/** 这一节答的是看完小课堂后的第一问:节前画小课堂卡 */
|
|
184
|
+
lecture?: KidLecture;
|
|
185
|
+
/** 这一节答的是孩子从纸上交的画:节前一张孩子的画卡 */
|
|
186
|
+
drawing?: KidDrawing;
|
|
187
|
+
/** 孩子引出这一节的那句话;saidOn = 它答的是哪一节的哪张问题卡(写进那张卡的答案栏),没有 = 在这一节开头单独一行。实时的节头不是它(看 head),它只给左栏用 */
|
|
188
|
+
said?: KidSaid;
|
|
189
|
+
saidOn?: {
|
|
190
|
+
job: string;
|
|
191
|
+
card: number;
|
|
192
|
+
};
|
|
193
|
+
/** 实时的一轮:卡闭合了就铺(不按拍);不出卡的板上留讲稿的字 */
|
|
194
|
+
live?: true;
|
|
195
|
+
/** 实时:这一轮开头是脑写的节头(只有一行 # 标题的文字卡),从这里起新的一件事,head 是它的标题(liveHead) */
|
|
196
|
+
head?: string;
|
|
197
|
+
/** 实时:这一轮开头没写节头,接着上一节画 */
|
|
198
|
+
cont?: true;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* 实时的一节怎么接:新一节的开头由脑定,不再机械是孩子那句。
|
|
202
|
+
* 这一轮第一张卡是节头 → head;没写(只有讲稿、开头是别的卡、还没写出卡)→ cont,接着上一节。一轮中间的节头卡,是从那张卡起新一节
|
|
203
|
+
*/
|
|
204
|
+
export declare function liveHead(s: Pick<BoardSection, 'cards'>): {
|
|
205
|
+
head: string;
|
|
206
|
+
} | {
|
|
207
|
+
cont: true;
|
|
208
|
+
};
|
|
209
|
+
/**
|
|
210
|
+
* 一节的问题卡:孩子下一条答的写进它的答案栏;没有 = null。
|
|
211
|
+
* 有拍给我看卡就是它(最后那张),末句问不问都算:老师要的是照片;
|
|
212
|
+
* 否则末句是问句(不交给小课堂)、它锚着的是文字卡(不是小节标题),或解析器补的提问卡。
|
|
213
|
+
*/
|
|
214
|
+
export declare function askCard(section: Pick<BoardSection, 'cards' | 'lines' | 'partial'>): number | null;
|
|
215
|
+
/**
|
|
216
|
+
* 每条孩子的话放在板上哪:交卡、首页按钮、空的不放;答的是上一节的问题卡就进那张卡的答案栏(on),
|
|
217
|
+
* 否则在它引出的那一节开头单独一行(on = null)。看完小课堂后的第一问不算答卡。按 job 给,还在跑的那条也有(刚发出去先挂上)。
|
|
218
|
+
*/
|
|
219
|
+
export declare function kidSaid(messages: readonly BoardMessage[]): Map<string, {
|
|
220
|
+
said: KidSaid;
|
|
221
|
+
on: {
|
|
222
|
+
job: string;
|
|
223
|
+
card: number;
|
|
224
|
+
} | null;
|
|
225
|
+
}>;
|
|
226
|
+
/**
|
|
227
|
+
* 孩子端条目 → 板书节(没有 section 的条目不出节);
|
|
228
|
+
* 孩子的话挂在它引出的那一节上(said / saidOn,kidSaid);还在跑的只有带 partial 板书(流式,已有卡或已有配好的句;实时的有句就算)才出节且标 partial,其余不出。
|
|
229
|
+
*/
|
|
230
|
+
export declare function sectionsFromMessages(messages: readonly BoardMessage[]): BoardEntry[];
|
|
231
|
+
/** 一节在目录里的名字:小节标题 > 有名字的文字卡 > 第一张有字的卡 > 第一句讲稿;截到 14 个字 */
|
|
232
|
+
export declare function sectionTitle(s: BoardSection): string;
|
|
233
|
+
/** 板上的位置。孩子端不念讲稿了:讲稿由嘴照念(runtime/delivery/player.ts 的 liveStep),这里的状态只剩
|
|
234
|
+
* thinking = 老师还在写 · waiting = 写完了、末句是问句 · done = 写完了 · idle = 板上还没东西。
|
|
235
|
+
* playing 只出现在录像里孩子的屏幕(嘴在念这一句),孩子端自己不会进 */
|
|
236
|
+
export type PlayStatus = 'idle' | 'playing' | 'waiting' | 'done' | 'thinking';
|
|
237
|
+
export interface PlayerState {
|
|
238
|
+
section: number;
|
|
239
|
+
line: number;
|
|
240
|
+
status: PlayStatus;
|
|
241
|
+
}
|
|
242
|
+
/** 打开页面时的位置:停在最后一节末尾;末句是问句就等着 */
|
|
243
|
+
export declare function playerAtEnd(sections: readonly BoardSection[]): PlayerState;
|
|
244
|
+
/** 播到这句该滚到哪张卡:标注所在的卡优先,其次锚点卡,再没有就 null(页面滚到本节第一张) */
|
|
245
|
+
export declare function lineTarget(line: BoardLine): number | null;
|
|
246
|
+
export interface PlayerModel {
|
|
247
|
+
state: PlayerState;
|
|
248
|
+
}
|
|
249
|
+
/** step 要读的页面状态(只读) */
|
|
250
|
+
export interface PlayerCtx {
|
|
251
|
+
sections: readonly BoardSection[];
|
|
252
|
+
}
|
|
253
|
+
export type PlayerEvent = {
|
|
254
|
+
type: 'reset';
|
|
255
|
+
} | {
|
|
256
|
+
type: 'halt';
|
|
257
|
+
} | {
|
|
258
|
+
type: 'liveStart';
|
|
259
|
+
section: number;
|
|
260
|
+
} | {
|
|
261
|
+
type: 'liveBeat';
|
|
262
|
+
section: number;
|
|
263
|
+
} | {
|
|
264
|
+
type: 'liveFinal';
|
|
265
|
+
section: number;
|
|
266
|
+
} | {
|
|
267
|
+
type: 'liveDropped';
|
|
268
|
+
} | {
|
|
269
|
+
type: 'fresh';
|
|
270
|
+
sections: number[];
|
|
271
|
+
};
|
|
272
|
+
/** stop 只停声音(卡的点读、单词);paint = 把某节的标注画齐;showNow = 选中态照现在的位置;scrollLast = 滚到最后一节 */
|
|
273
|
+
export type PlayerEffect = {
|
|
274
|
+
kind: 'stop';
|
|
275
|
+
} | {
|
|
276
|
+
kind: 'render';
|
|
277
|
+
} | {
|
|
278
|
+
kind: 'showNow';
|
|
279
|
+
} | {
|
|
280
|
+
kind: 'paint';
|
|
281
|
+
section: number;
|
|
282
|
+
} | {
|
|
283
|
+
kind: 'scrollLast';
|
|
284
|
+
};
|
|
285
|
+
export declare function initialPlayer(): PlayerModel;
|
|
286
|
+
export declare function step(model: PlayerModel, ev: PlayerEvent, ctx: PlayerCtx): {
|
|
287
|
+
model: PlayerModel;
|
|
288
|
+
effects: PlayerEffect[];
|
|
289
|
+
};
|
|
290
|
+
export type BarMode = 'idle' | 'typing' | 'holding';
|
|
291
|
+
export type BarEvent = 'tap' | 'holdStart' | 'holdEnd' | 'holdCancel' | 'sent' | 'blur';
|
|
292
|
+
/** 输入条中间那段:点 → 打字;按住 → 说话;松手 / 上滑取消 / 发出 / 失焦 → 回到闲置 */
|
|
293
|
+
export declare function barNext(mode: BarMode, ev: BarEvent): BarMode;
|
|
294
|
+
/** 一句念多久(毫秒):按字数估(mock 的假嘴、录像) */
|
|
295
|
+
export declare function lineDurationMs(text: string): number;
|