cotutor 0.2.0 → 0.4.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 +249 -21
- package/NOTICE +42 -0
- package/README.md +115 -20
- package/avatars/chinese.webp +0 -0
- package/avatars/english.webp +0 -0
- package/avatars/math.webp +0 -0
- package/bin/cotutor.js +15 -5
- 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 +22 -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 +79 -0
- package/cards/tutor/card.md +149 -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 +159 -0
- package/dist/app/build.d.ts +11 -0
- package/dist/app/build.js +45 -0
- package/dist/app/cli/activities.d.ts +70 -0
- package/dist/app/cli/activities.js +196 -0
- package/dist/app/cli/cert.d.ts +12 -0
- package/dist/app/cli/cert.js +49 -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 +157 -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 +199 -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 +24 -0
- package/dist/app/cli/doctor.js +553 -0
- package/dist/app/cli/firewall.d.ts +24 -0
- package/dist/app/cli/firewall.js +79 -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 +158 -0
- package/dist/app/cli/main.js +1038 -0
- package/dist/app/cli/migrate.d.ts +49 -0
- package/dist/app/cli/migrate.js +195 -0
- package/dist/app/cli/port-holder.d.ts +16 -0
- package/dist/app/cli/port-holder.js +34 -0
- package/dist/app/cli/port.d.ts +37 -0
- package/dist/app/cli/port.js +116 -0
- package/dist/app/cli/sandbox.d.ts +25 -0
- package/dist/app/cli/sandbox.js +166 -0
- package/dist/app/cli/serve-log.d.ts +13 -0
- package/dist/app/cli/serve-log.js +90 -0
- package/dist/app/cli/serve.d.ts +51 -0
- package/dist/app/cli/serve.js +168 -0
- package/dist/app/cli/service-windows.d.ts +50 -0
- package/dist/app/cli/service-windows.js +117 -0
- package/dist/app/cli/service.d.ts +138 -0
- package/dist/app/cli/service.js +429 -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 +59 -0
- package/dist/app/cli/skills.js +199 -0
- package/dist/app/cli/themes.d.ts +52 -0
- package/dist/app/cli/themes.js +148 -0
- package/dist/app/cli/tray-icons.d.ts +11 -0
- package/dist/app/cli/tray-icons.js +87 -0
- package/dist/app/cli/tray-ids.d.ts +6 -0
- package/dist/app/cli/tray-ids.js +6 -0
- package/dist/app/cli/tray-mac.d.ts +8 -0
- package/dist/app/cli/tray-mac.js +140 -0
- package/dist/app/cli/tray-run.d.ts +1 -0
- package/dist/app/cli/tray-run.js +33 -0
- package/dist/app/cli/tray-windows.d.ts +5 -0
- package/dist/app/cli/tray-windows.js +166 -0
- package/dist/app/cli/tray.d.ts +205 -0
- package/dist/app/cli/tray.js +618 -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 +35 -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 +511 -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 +241 -0
- package/dist/app/http/app.js +1159 -0
- package/dist/app/http/avatars.d.ts +17 -0
- package/dist/app/http/avatars.js +35 -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 +51 -0
- package/dist/app/http/parent-home.js +266 -0
- package/dist/app/http/parent-look.d.ts +2 -0
- package/dist/app/http/parent-look.js +151 -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/http/voice-preview.d.ts +4 -0
- package/dist/app/http/voice-preview.js +34 -0
- package/dist/app/machine/bailian.d.ts +26 -0
- package/dist/app/machine/bailian.js +87 -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 +38 -5
- package/dist/app/mock/mock.js +1125 -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 +63 -0
- package/dist/{cli → app}/workspace.js +100 -52
- package/dist/app/ws/route.d.ts +31 -0
- package/dist/app/ws/route.js +33 -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 +118 -0
- package/dist/board/parse.js +324 -0
- package/dist/board/presentation.d.ts +289 -0
- package/dist/board/presentation.js +613 -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 +191 -0
- package/dist/brain/api.d.ts +57 -0
- package/dist/brain/api.js +394 -0
- package/dist/brain/index.d.ts +97 -0
- package/dist/brain/index.js +11 -0
- package/dist/brain/log.d.ts +5 -0
- package/dist/brain/log.js +22 -0
- package/dist/brain/runtime.d.ts +30 -0
- package/dist/brain/runtime.js +23 -0
- package/dist/brain/stream-json.d.ts +16 -0
- package/dist/brain/stream-json.js +82 -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/brain/types.d.ts +99 -0
- package/dist/brain/types.js +14 -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 +289 -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 +21 -0
- package/dist/realtime/voices.js +71 -0
- package/dist/runtime/activities.d.ts +29 -0
- package/dist/runtime/activities.js +72 -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 +191 -0
- package/dist/runtime/home/home.js +318 -0
- package/dist/runtime/home/store.d.ts +142 -0
- package/dist/runtime/home/store.js +455 -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 +42 -0
- package/dist/runtime/journal/mix.js +129 -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 +91 -0
- package/dist/runtime/journal/recorder.js +148 -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 +194 -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 +231 -0
- package/dist/runtime/live/call.js +1244 -0
- package/dist/runtime/live/turns.d.ts +48 -0
- package/dist/runtime/live/turns.js +102 -0
- package/dist/runtime/runner.d.ts +243 -0
- package/dist/runtime/runner.js +777 -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 +171 -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 +339 -103
- package/dist/schema/config.js +269 -84
- 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 +391 -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 +56 -0
- package/dist/schema/home.js +35 -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 +68 -0
- package/dist/schema/workspace.js +37 -0
- package/dist/shared/default-port.d.ts +2 -0
- package/dist/shared/default-port.js +2 -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 +54 -0
- package/dist/shared/qianwen.js +113 -0
- package/dist/shared/site-url.d.ts +2 -0
- package/dist/shared/site-url.js +5 -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 +2021 -0
- package/dist/ui/dev/dev-theme.d.ts +6 -0
- package/dist/ui/dev/dev-theme.js +67 -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/home-tiles.d.ts +14 -0
- package/dist/ui/kid/home-tiles.js +44 -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 +3684 -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 +68 -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 +722 -0
- package/dist/ui/parent/parent-page.d.ts +2 -0
- package/dist/ui/parent/parent-page.js +511 -0
- package/dist/ui/parent/parent-settings-page.d.ts +1 -0
- package/dist/ui/parent/parent-settings-page.js +133 -0
- package/dist/ui/parent/qr-page.d.ts +8 -0
- package/dist/ui/parent/qr-page.js +66 -0
- package/dist/ui/shared/brand.d.ts +38 -0
- package/dist/ui/shared/brand.js +53 -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/243/200/346/237/245/344/275/234/344/270/232.md +81 -0
- package/grades/grade-2/agents/chinese-tutor/activities//346/243/200/346/237/245/344/275/234/344/270/232./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/243/200/346/237/245/344/275/234/344/270/232.md +80 -0
- package/grades/grade-2/agents/english-tutor/activities//346/243/200/346/237/245/344/275/234/344/270/232./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/243/200/346/237/245/344/275/234/344/270/232.md +80 -0
- package/grades/grade-2/agents/math-tutor/activities//346/243/200/346/237/245/344/275/234/344/270/232./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 +27 -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 +170 -0
- package/skills/cotutor-home/references/dictation.md +97 -0
- package/skills/cotutor-home/references/tutor.md +149 -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 +143 -0
- package/skills/cotutor-tune/SKILL.md +147 -0
- package/skills/cotutor-tune/references//345/255/227/346/256/265.md +53 -0
- package/skills/cotutor-tutor/SKILL.md +253 -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/cert.d.ts +0 -7
- package/dist/cli/cert.js +0 -36
- package/dist/cli/doctor.d.ts +0 -22
- 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.d.ts +0 -30
- 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}/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,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 实时老师每次让嘴开口的那句指令(response.instructions):纯函数。
|
|
3
|
+
* 嘴自己不决定说什么,只两件事:几种场合先说一句(拍照、没听清、热身)、把脑写的讲稿原样念。说法是 2026-10-19 P1 实测过的(scripts/probe-live.mjs cue):
|
|
4
|
+
* 「原样说」和那句一起放进 response.instructions,4/4 一字不差;只放 system 消息、或要说的话当用户消息发,它会改写、会把问题自己答了。
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* 嘴先说的那句;没写的那几种嘴不出声,等脑的第一句。
|
|
8
|
+
* 10-20 晚 Ray 真用:「好,我讲给你听」「我想一想怎么讲」每轮都有,和孩子说的对不上(「老师。」也接成讲给你听),脑还常把它再说一遍;脑的第一句 3–5 秒就到
|
|
9
|
+
*/
|
|
10
|
+
const CATCH = {
|
|
11
|
+
// 拍照脑要读 14–29 秒,先说一句;说明白看的是孩子发的图片
|
|
12
|
+
photo: '孩子拍来了照片。只说一句「我看一看图片」,不说你看到了什么,说完就停。',
|
|
13
|
+
// 听不清由应用判(转写是空的),不交给脑,嘴不说孩子就不知道要再说一遍
|
|
14
|
+
empty: '孩子按了说话,但什么都没说清。只说一句「没听清,再说一遍吧」,说完就停。',
|
|
15
|
+
warm: '孩子拍好了今天的口语单,要开始上口语课。只说一句「好,我们先热热身!」,说完就停。',
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* 口语课打电话那段:老师说英文,嘴先说的也换英文。
|
|
19
|
+
* 指令照旧用中文写(嘴听得懂),要它说的是英文
|
|
20
|
+
*/
|
|
21
|
+
const CATCH_EN = {
|
|
22
|
+
photo: '孩子拍来了照片。只说一句「Let me look at your picture.」,不说你看到了什么,说完就停。',
|
|
23
|
+
empty: '孩子说了,但什么都没说清。只说一句「Sorry? Say it again.」,说完就停。',
|
|
24
|
+
warm: '孩子要开始上口语课。只说一句「Okay, let\'s start!」,说完就停。',
|
|
25
|
+
};
|
|
26
|
+
/** 这一轮嘴先说的那句的指令;null = 嘴不出声。en = 口语课打电话那段 */
|
|
27
|
+
export function catchCue(kind, lang = 'zh') {
|
|
28
|
+
return (lang === 'en' ? CATCH_EN : CATCH)[kind] ?? null;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* 交给嘴之前,把它念不好的写法换成念法(板上、字幕照旧是原文)。2026-10-20 真连(照念 → 声音转写回字):× + − = ÷ > 1/2 都念对;
|
|
32
|
+
* 空括号念成「空格」「括号」(「每份都是( )个」成了「每份都是空格」),□ 念得含糊(「□+5=12」听成「正五等于十二」)。
|
|
33
|
+
* 空括号、下划线的空照数学老师的说法念「几」(「二四得几」「每份都是几个」),□ 念「方框」;换了以后「方框+5」的 + 念成「正」,
|
|
34
|
+
* 所以运算符一律换成字(+ 加、− 减、× 乘、÷ 除以、= 等于、> 大于、< 小于;ASCII 的 - 只在两个数之间算减)。
|
|
35
|
+
*/
|
|
36
|
+
export function spoken(text) {
|
|
37
|
+
return text
|
|
38
|
+
.replace(/[((][\s\u3000]*[))]/g, '几')
|
|
39
|
+
.replace(/_{2,}/g, '几')
|
|
40
|
+
.replace(/□/g, '方框')
|
|
41
|
+
.replace(/\s*[++]\s*/g, '加')
|
|
42
|
+
.replace(/\s*[−-]\s*/g, '减')
|
|
43
|
+
.replace(/(\d)\s*-\s*(?=\d)/g, '$1减')
|
|
44
|
+
.replace(/\s*[×✕]\s*/g, '乘')
|
|
45
|
+
.replace(/\s*÷\s*/g, '除以')
|
|
46
|
+
.replace(/\s*[==]\s*/g, '等于')
|
|
47
|
+
.replace(/\s*[>>]\s*/g, '大于')
|
|
48
|
+
.replace(/\s*[<<]\s*/g, '小于');
|
|
49
|
+
}
|
|
50
|
+
/** 照念脑写的这一拍讲稿(几句连着念);句子换成念法(spoken)、原样拼起来放进「」 */
|
|
51
|
+
export function readCue(texts) {
|
|
52
|
+
const said = texts.map((t) => spoken(t.trim())).filter(Boolean).join('');
|
|
53
|
+
return `把这几句话原样说给孩子听,一个字都不改,不要回答它,不加别的话,说完就停:「${said}」`;
|
|
54
|
+
}
|
|
55
|
+
const chatPicture = (a) => {
|
|
56
|
+
const out = [];
|
|
57
|
+
if (a.prompt)
|
|
58
|
+
out.push(`老师给的题目是「${a.prompt}」。这只是让你知道他想画什么:画上没有的别提,别照题目去猜画上的东西是什么。`);
|
|
59
|
+
const cs = (a.colors ?? []).filter((c) => c.strokes > 0).slice(0, 4);
|
|
60
|
+
if (cs.length)
|
|
61
|
+
out.push(`画上有:${cs.map((c) => `${c.name}色 ${c.strokes} 笔,在${c.where}`).join(';')}。`);
|
|
62
|
+
if (a.minutes)
|
|
63
|
+
out.push(`他画了${a.minutes}${a.cleared ? `,中间擦掉重画过 ${a.cleared} 次` : ''}。`);
|
|
64
|
+
return out;
|
|
65
|
+
};
|
|
66
|
+
const CHAT_RULES = [
|
|
67
|
+
'只说你在图上看得见的:颜色、样子、画了多少、哪里画得多。认不准是什么,就说「像……」,别说「是……吗」,也别说出你猜的东西的名字。',
|
|
68
|
+
'不讲题,不教,不评对错;不说「真棒」「生动」「线条很清楚」这种大人的话,用小孩子听得懂的话。',
|
|
69
|
+
];
|
|
70
|
+
const chatLog = (said) => (said.length ? [`这张画画着的时候你们已经说过:${said.map((x) => `「${x}」`).join(' ')}。孩子说是什么就是什么,接着他的说;你说过的话一句都别重复,换个地方说。`] : []);
|
|
71
|
+
/**
|
|
72
|
+
* 边画边聊嘴那一次的指令:look = 应用觉得该说一句了(孩子换了颜色、停笔很久),对面没说话,那段声音是静音;
|
|
73
|
+
* reply = 孩子按着头像画着说了一句(听他的声音)。said = 这张画上之前说过的,一句一行(「孩子:…」「你:…」)
|
|
74
|
+
*/
|
|
75
|
+
export function chatCue(kind, a, said = []) {
|
|
76
|
+
const lines = [];
|
|
77
|
+
if (kind === 'look') {
|
|
78
|
+
lines.push('孩子正在画板上自己画画,刚才那张图就是他这一刻的画;那段声音是静音,他没说话。你坐在旁边看他画,主动说一句。');
|
|
79
|
+
lines.push(...chatPicture(a));
|
|
80
|
+
lines.push(a.color ? `说说他刚画完的${a.color}色那部分。` : '说说整张画。');
|
|
81
|
+
lines.push(...CHAT_RULES);
|
|
82
|
+
lines.push(a.ask === false ? '这次只说一句,不问。' : `说完问一句,问${a.color ? `${a.color}色画的` : '他画的'}是什么,只问这一个。`);
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
lines.push('孩子正在画板上自己画画,一边画一边跟你说了一句(听他的声音),刚才那张图是他这一刻的画。像坐在旁边看他画的老师那样,接住他的话。');
|
|
86
|
+
lines.push(...chatPicture(a));
|
|
87
|
+
lines.push(...CHAT_RULES);
|
|
88
|
+
lines.push('他说是什么就是什么,顺着他说,说一句你在图上看得见的;可以再问一句,也可以不问。');
|
|
89
|
+
lines.push('他要是问题目、问怎么做、要你教他,别答,说「按住『给老师看』跟老师说,老师好好看看」。');
|
|
90
|
+
}
|
|
91
|
+
lines.push(...chatLog(said));
|
|
92
|
+
lines.push('一共一两句,短,说完就停。');
|
|
93
|
+
return lines.join('\n');
|
|
94
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 一直听:VAD 切出来、转写回来的一句,收下(算孩子对老师说的,同按下 + 松手)还是放过。纯函数。
|
|
3
|
+
* 按顺序:空的(咳嗽、碰桌子)→ 只有语气词、老师上一句又不是问句 → 是嘴自己的回声(开口时嘴的声音还在放,且和嘴最近说过的字重合过六成)→ 其余收下。
|
|
4
|
+
* 回声只在嘴出声的时候才有:嘴停了以后孩子照着说一遍(跟读、复述老师的话)字一样也是孩子的(2026-10-20 评估口语课时改)。
|
|
5
|
+
* 「不是对老师说的」(孩子跟家长说话)不在这里判(待)。
|
|
6
|
+
*/
|
|
7
|
+
export type Skip = 'empty' | 'filler' | 'echo';
|
|
8
|
+
export type Verdict = {
|
|
9
|
+
take: true;
|
|
10
|
+
} | {
|
|
11
|
+
take: false;
|
|
12
|
+
why: Skip;
|
|
13
|
+
};
|
|
14
|
+
/** 嘴说过的字留多久用来比回声 */
|
|
15
|
+
export declare const ECHO_WINDOW_MS = 10000;
|
|
16
|
+
/** 只留字:去标点、空白,英文小写 */
|
|
17
|
+
export declare const bare: (s: string) => string;
|
|
18
|
+
/** text 有几成落在 said 里(按相邻两字比,中英都行) */
|
|
19
|
+
export declare function overlap(text: string, said: string): number;
|
|
20
|
+
/**
|
|
21
|
+
* 判一句。asked = 老师上一句是问句(孩子在答,「嗯」「对」就是回答);said = 嘴最近说过的话(带说完的墙钟),now 用来挑 ECHO_WINDOW_MS 以内的;
|
|
22
|
+
* mouthOn = 孩子开口那一刻嘴的声音还在放(或刚放完 300 毫秒内),false 时不比回声
|
|
23
|
+
*/
|
|
24
|
+
export declare function judge(text: string, o: {
|
|
25
|
+
asked: boolean;
|
|
26
|
+
said: {
|
|
27
|
+
text: string;
|
|
28
|
+
at: number;
|
|
29
|
+
}[];
|
|
30
|
+
now: number;
|
|
31
|
+
mouthOn?: boolean;
|
|
32
|
+
}): Verdict;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 一直听:VAD 切出来、转写回来的一句,收下(算孩子对老师说的,同按下 + 松手)还是放过。纯函数。
|
|
3
|
+
* 按顺序:空的(咳嗽、碰桌子)→ 只有语气词、老师上一句又不是问句 → 是嘴自己的回声(开口时嘴的声音还在放,且和嘴最近说过的字重合过六成)→ 其余收下。
|
|
4
|
+
* 回声只在嘴出声的时候才有:嘴停了以后孩子照着说一遍(跟读、复述老师的话)字一样也是孩子的(2026-10-20 评估口语课时改)。
|
|
5
|
+
* 「不是对老师说的」(孩子跟家长说话)不在这里判(待)。
|
|
6
|
+
*/
|
|
7
|
+
/** 嘴说过的字留多久用来比回声 */
|
|
8
|
+
export const ECHO_WINDOW_MS = 10_000;
|
|
9
|
+
/** 重合到这么多算回声 */
|
|
10
|
+
const ECHO_RATIO = 0.6;
|
|
11
|
+
/** 语气词与笑声:中文按字(全是这些字就算,「哈哈哈」「嗯嗯」也算),英文按词(server_vad 把「嗯」转成 And.,2026-10-20 探针) */
|
|
12
|
+
const FILLER_CHARS = new Set([...'嗯啊哦呃哈额唔噢诶欸哎呵嘿']);
|
|
13
|
+
const FILLER_WORDS = new Set(['um', 'uh', 'hmm', 'mm', 'mhm', 'ah', 'oh', 'eh', 'en', 'and', 'haha', 'hahaha']);
|
|
14
|
+
const isFiller = (text) => {
|
|
15
|
+
const t = bare(text);
|
|
16
|
+
if (t && [...t].every((c) => FILLER_CHARS.has(c)))
|
|
17
|
+
return true;
|
|
18
|
+
const words = text.toLowerCase().split(/[^a-z]+/).filter(Boolean);
|
|
19
|
+
return words.length > 0 && words.length <= 3 && words.every((w) => FILLER_WORDS.has(w)) && !/[\u4e00-\u9fff]/.test(text);
|
|
20
|
+
};
|
|
21
|
+
/** 只留字:去标点、空白,英文小写 */
|
|
22
|
+
export const bare = (s) => s.toLowerCase().replace(/[\s\p{P}\p{S}]/gu, '');
|
|
23
|
+
/** 相邻两个字一组;一个字的就是它自己 */
|
|
24
|
+
function pairs(s) {
|
|
25
|
+
const cs = [...s];
|
|
26
|
+
if (cs.length < 2)
|
|
27
|
+
return cs;
|
|
28
|
+
return cs.slice(1).map((c, i) => cs[i] + c);
|
|
29
|
+
}
|
|
30
|
+
/** text 有几成落在 said 里(按相邻两字比,中英都行) */
|
|
31
|
+
export function overlap(text, said) {
|
|
32
|
+
const t = pairs(bare(text));
|
|
33
|
+
if (!t.length)
|
|
34
|
+
return 0;
|
|
35
|
+
const s = new Set(pairs(bare(said)));
|
|
36
|
+
return t.filter((p) => s.has(p)).length / t.length;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* 判一句。asked = 老师上一句是问句(孩子在答,「嗯」「对」就是回答);said = 嘴最近说过的话(带说完的墙钟),now 用来挑 ECHO_WINDOW_MS 以内的;
|
|
40
|
+
* mouthOn = 孩子开口那一刻嘴的声音还在放(或刚放完 300 毫秒内),false 时不比回声
|
|
41
|
+
*/
|
|
42
|
+
export function judge(text, o) {
|
|
43
|
+
const t = bare(text);
|
|
44
|
+
if (!t)
|
|
45
|
+
return { take: false, why: 'empty' };
|
|
46
|
+
if (!o.asked && isFiller(text))
|
|
47
|
+
return { take: false, why: 'filler' };
|
|
48
|
+
const recent = o.said.filter((x) => o.now - x.at <= ECHO_WINDOW_MS).map((x) => x.text).join('');
|
|
49
|
+
// 两个字以内的不比回声(「对」「好的」碰巧在嘴的话里也常见)
|
|
50
|
+
if (o.mouthOn !== false && recent && t.length > 2 && overlap(t, recent) >= ECHO_RATIO)
|
|
51
|
+
return { take: false, why: 'echo' };
|
|
52
|
+
return { take: true };
|
|
53
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export declare function previewVoice(o: {
|
|
2
|
+
voice: string;
|
|
3
|
+
text: string;
|
|
4
|
+
model?: string;
|
|
5
|
+
env?: NodeJS.ProcessEnv;
|
|
6
|
+
endpoint?: string;
|
|
7
|
+
timeoutMs?: number;
|
|
8
|
+
}): Promise<{
|
|
9
|
+
wav: Buffer;
|
|
10
|
+
} | {
|
|
11
|
+
error: string;
|
|
12
|
+
}>;
|
|
13
|
+
/** 试连一次(家长端配百炼、doctor --live):握手到 session.updated 就挂,不出声、不花钱;null = 通,否则是原因(no_auth / connect / timeout / 服务端的话) */
|
|
14
|
+
export declare function probeRealtime(o?: {
|
|
15
|
+
auth?: {
|
|
16
|
+
key: string;
|
|
17
|
+
workspaceId: string;
|
|
18
|
+
};
|
|
19
|
+
model?: string;
|
|
20
|
+
env?: NodeJS.ProcessEnv;
|
|
21
|
+
endpoint?: string;
|
|
22
|
+
timeoutMs?: number;
|
|
23
|
+
}): Promise<string | null>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 试听嘴的一个音色(工作台音色页「实时的嘴」):真连一次百炼 realtime,让它照念一句(同实时老师的照念指令),收下 24k PCM 包成 wav。
|
|
3
|
+
* 几分钱一次;调用方按「音色 + 句子」缓存,同一句同一个音色只念一次。
|
|
4
|
+
*/
|
|
5
|
+
import { readCue } from "./cues.js";
|
|
6
|
+
import { wavOfPcm } from "../shared/wav.js";
|
|
7
|
+
import { OUTPUT_RATE, RealtimeSession } from "./bailian.js";
|
|
8
|
+
export async function previewVoice(o) {
|
|
9
|
+
const chunks = [];
|
|
10
|
+
let err = '';
|
|
11
|
+
let done = false;
|
|
12
|
+
const s = new RealtimeSession({ instructions: '你是一位小学老师。', voice: o.voice, model: o.model, turn: 'manual', env: o.env, endpoint: o.endpoint }, {
|
|
13
|
+
onAudio: (pcm) => { chunks.push(pcm); },
|
|
14
|
+
onError: (m) => { err = m; },
|
|
15
|
+
onResponse: (st) => { if (st === 'done')
|
|
16
|
+
done = true; },
|
|
17
|
+
});
|
|
18
|
+
const why = await s.connect();
|
|
19
|
+
if (why !== null)
|
|
20
|
+
return { error: why === 'no_auth' ? '没有百炼的 key 或业务空间 id(家长端「首页」里填,存在 ~/.config/cotutor/bailian.json)' : `连不上:${why}` };
|
|
21
|
+
s.createResponse(readCue([o.text]));
|
|
22
|
+
const until = Date.now() + (o.timeoutMs ?? 20_000);
|
|
23
|
+
while (!done && !err && Date.now() < until)
|
|
24
|
+
await new Promise((r) => setTimeout(r, 50));
|
|
25
|
+
s.close('preview');
|
|
26
|
+
if (err)
|
|
27
|
+
return { error: err };
|
|
28
|
+
if (!chunks.length)
|
|
29
|
+
return { error: done ? '没出声' : '超时' };
|
|
30
|
+
return { wav: wavOfPcm(Buffer.concat(chunks), OUTPUT_RATE) };
|
|
31
|
+
}
|
|
32
|
+
/** 试连一次(家长端配百炼、doctor --live):握手到 session.updated 就挂,不出声、不花钱;null = 通,否则是原因(no_auth / connect / timeout / 服务端的话) */
|
|
33
|
+
export async function probeRealtime(o = {}) {
|
|
34
|
+
const s = new RealtimeSession({ instructions: '试连。', turn: 'manual', model: o.model, auth: o.auth, env: o.env, endpoint: o.endpoint, timeoutMs: o.timeoutMs }, {});
|
|
35
|
+
const why = await s.connect();
|
|
36
|
+
s.close('probe');
|
|
37
|
+
return why;
|
|
38
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 实时老师的嘴的系统指令:只放人设与规矩,不放老师文件、activity 的流程——
|
|
3
|
+
* 2026-10-19 P1 实测:流程放进去它也带不动(看图说话六轮只接话不问),要说的话由应用每次放进 response.instructions(src/realtime/cues.ts)。
|
|
4
|
+
*/
|
|
5
|
+
export function mouthInstructions(o) {
|
|
6
|
+
return [
|
|
7
|
+
`你是这个家的${o.display},对面是一个孩子,叫${o.kidName}。`,
|
|
8
|
+
'你是用嘴说话的那一位:每一次,我都会告诉你这一次说什么。只照做:接住孩子的话,或者把给你的句子原样说出来。',
|
|
9
|
+
'不讲新内容,不回答题目,不评对错,不问问题。',
|
|
10
|
+
'只有一种时候例外:我让你看孩子正在画的画,你照我那一次说的,看着画说一两句、问一句;那时也不讲题、不评对错。',
|
|
11
|
+
'说话亲切、慢一点,像当面说话;不念标点,不念括号。',
|
|
12
|
+
].join('\n');
|
|
13
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 嘴(百炼 realtime,qwen3.8-omni-flash-realtime)认的音色:官方列表 https://www.alibabacloud.com/help/zh/model-studio/omni-voice-list 里
|
|
3
|
+
* 「Qwen3.8-Omni 系列」那 56 个(2026-10-19 照抄;每个都真连过一次让它说一个字,都出声)。trait 是官方描述的概括,lang 是除外语以外会说的(都另会 28 种外语)。
|
|
4
|
+
* 旧模型的 Bella、Pip、Chelsie、Ethan 这个模型不认:连接照样连得上,第一次开口才报 InvalidParameter——所以写错的音色要在配置这一头拦(工作台、doctor)。
|
|
5
|
+
* 工作台音色页「实时的嘴」那一半照这张表列、试听、挑(写进 cotutor.json 的 live.voices)。
|
|
6
|
+
* 英语老师的讲稿是中文里夹英文(「apple 苹果,banana 香蕉」):2026-10-20 真连(照念 → 转写回字)Serena、Tina、Maia、Liora Mira、Mione、Theo Calm 都念对,
|
|
7
|
+
* Jennifer、Mia 的中文带英文腔(Jennifer:「腿」成了 tway,「它是什么颜色」没了),trait 里记着。
|
|
8
|
+
*/
|
|
9
|
+
export interface RealtimeVoice {
|
|
10
|
+
/** session.update 的 voice 参数(大小写、空格照官方) */
|
|
11
|
+
voice: string;
|
|
12
|
+
/** 官方的中文名 */
|
|
13
|
+
name: string;
|
|
14
|
+
/** 男 / 女:官方表没有这一栏,照名字与描述标;看不出的三个(Theo Calm、Arda、longanlingxin)2026-11-03 真念一句量了音高 */
|
|
15
|
+
gender: '男' | '女';
|
|
16
|
+
trait: string;
|
|
17
|
+
lang: string;
|
|
18
|
+
}
|
|
19
|
+
export declare const REALTIME_VOICES: readonly RealtimeVoice[];
|
|
20
|
+
/** 这个模型认不认这个音色(工作台、doctor 拦写错的) */
|
|
21
|
+
export declare function isRealtimeVoice(voice: string): boolean;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 嘴(百炼 realtime,qwen3.8-omni-flash-realtime)认的音色:官方列表 https://www.alibabacloud.com/help/zh/model-studio/omni-voice-list 里
|
|
3
|
+
* 「Qwen3.8-Omni 系列」那 56 个(2026-10-19 照抄;每个都真连过一次让它说一个字,都出声)。trait 是官方描述的概括,lang 是除外语以外会说的(都另会 28 种外语)。
|
|
4
|
+
* 旧模型的 Bella、Pip、Chelsie、Ethan 这个模型不认:连接照样连得上,第一次开口才报 InvalidParameter——所以写错的音色要在配置这一头拦(工作台、doctor)。
|
|
5
|
+
* 工作台音色页「实时的嘴」那一半照这张表列、试听、挑(写进 cotutor.json 的 live.voices)。
|
|
6
|
+
* 英语老师的讲稿是中文里夹英文(「apple 苹果,banana 香蕉」):2026-10-20 真连(照念 → 转写回字)Serena、Tina、Maia、Liora Mira、Mione、Theo Calm 都念对,
|
|
7
|
+
* Jennifer、Mia 的中文带英文腔(Jennifer:「腿」成了 tway,「它是什么颜色」没了),trait 里记着。
|
|
8
|
+
*/
|
|
9
|
+
const v = (voice, name, gender, trait, lang = '普通话') => ({ voice, name, gender, trait, lang });
|
|
10
|
+
export const REALTIME_VOICES = [
|
|
11
|
+
v('Tina', '甜甜', '女', '甜美温暖,解决问题果断(缺省)'),
|
|
12
|
+
v('Cindy', '林欣宜', '女', '台湾腔嗲嗲的小姐姐', '台湾口音'),
|
|
13
|
+
v('Liora Mira', '清欢', '女', '温柔的烟火人间感'),
|
|
14
|
+
v('Raymond', '林川野', '男', '声音清亮,爱吃外卖的宅男'),
|
|
15
|
+
v('Zane', '泽恩', '男', '磁性迷人'),
|
|
16
|
+
v('Katerina', '卡捷琳娜', '女', '御姐音,韵律感强'),
|
|
17
|
+
v('Ryan', '甜茶', '男', '节奏感强,戏感足'),
|
|
18
|
+
v('Mia', '舒然', '女', '细腻,生活美学风格的温柔博主;中英夹着说时中文带英文腔'),
|
|
19
|
+
v('Cici', '绵绵', '女', '邻家妹妹,活泼软糯'),
|
|
20
|
+
v('Theo Calm', '予安', '男', '沉静,治愈感'),
|
|
21
|
+
v('Serena', '苏瑶', '女', '温柔小姐姐'),
|
|
22
|
+
v('Maia', '四月', '女', '知性与温柔'),
|
|
23
|
+
v('Evan', '江晨', '男', '男大学生,年下奶狗'),
|
|
24
|
+
v('Qiao', '小乔妹', '女', '表面甜妹,个性十足', '台湾口音'),
|
|
25
|
+
v('Momo', '茉兔', '女', '撒娇搞怪'),
|
|
26
|
+
v('Wil', '伟伦', '男', '深圳长大的港台腔小哥哥'),
|
|
27
|
+
v('Angel', '安琪', '女', '带台式口音,甜美'),
|
|
28
|
+
v('Li Cassian', '李公公', '男', '话中有留白,善察言观色'),
|
|
29
|
+
v('Joyner', '阿逗', '男', '搞笑、夸张、接地气'),
|
|
30
|
+
v('Gold', '金爷', '男', '西海岸黑人说唱歌手风格'),
|
|
31
|
+
v('Jennifer', '詹妮弗', '女', '电影质感的美语女声;中英夹着说时中文带英文腔(苹果念成 pingguo)'),
|
|
32
|
+
v('Aiden', '艾登', '男', '精通厨艺的美语大男孩'),
|
|
33
|
+
v('Mione', '敏儿', '女', '成熟知性的英国邻家妹妹'),
|
|
34
|
+
v('Sunny', '晴儿', '女', '甜美的川妹子', '四川话'),
|
|
35
|
+
v('Dylan', '晓东', '男', '北京胡同长大的少年', '北京话'),
|
|
36
|
+
v('Eric', '程川', '男', '成都市井男子,跳脱', '四川话'),
|
|
37
|
+
v('Peter', '李彼得', '男', '天津相声,专业捧哏', '天津话'),
|
|
38
|
+
v('Joseph Chen', '阿樸伯', '男', '南洋老华侨', '闽南话'),
|
|
39
|
+
v('Marcus', '秦川', '男', '老陕风格,面宽话短', '陕西话'),
|
|
40
|
+
v('Li', '老李', '男', '南京话伯伯,爱骂骂咧咧', '南京话'),
|
|
41
|
+
v('Rocky', '阿强', '男', '幽默风趣,在线陪聊', '粤语'),
|
|
42
|
+
v('Kiki', '阿清', '女', '甜美的港妹闺蜜', '粤语'),
|
|
43
|
+
v('Sohee', '素熙', '女', '温柔开朗的韩国欧尼'),
|
|
44
|
+
v('Eliška', '艾莉卡', '女', '中欧风格'),
|
|
45
|
+
v('Alek', '阿列克', '男', '战斗民族的冷与暖'),
|
|
46
|
+
v('Arda', '阿尔达', '男', '干净利落,温润'),
|
|
47
|
+
v('Dolce', '多尔切', '男', '慵懒的意大利大叔'),
|
|
48
|
+
v('Lenn', '莱恩', '男', '德国青年,理性中带叛逆'),
|
|
49
|
+
v('Ono Anna', '小野杏', '女', '鬼灵精怪的青梅竹马'),
|
|
50
|
+
v('Sonrisa', '索尼莎', '女', '热情开朗的拉美大姐'),
|
|
51
|
+
v('Bodega', '博德加', '男', '热情的西班牙大叔'),
|
|
52
|
+
v('Andre', '安德雷', '男', '磁性、沉稳的男生'),
|
|
53
|
+
v('Radio Gol', '拉迪奥·戈尔', '男', '足球解说风格'),
|
|
54
|
+
v('Rizky', '阿力', '男', '印尼青年,声线个性'),
|
|
55
|
+
v('Roya', '萝雅', '女', '热爱运动的女孩'),
|
|
56
|
+
v('Hana', '阿幸', '女', '越南成熟姐姐'),
|
|
57
|
+
v('Jakub', '雅克', '男', '波兰文艺青年,声线磁性'),
|
|
58
|
+
v('Griet', '海娜', '女', '荷兰成熟文艺女性'),
|
|
59
|
+
v('Marina', '玛丽娜', '女', '多元文化城市长大的女孩'),
|
|
60
|
+
v('Siiri', '西芮', '女', '内敛温柔,语速舒缓'),
|
|
61
|
+
v('Ingrid', '林恩', '女', '挪威乡村姑娘'),
|
|
62
|
+
v('Sigga', '海娜', '女', '冰岛小镇知性女青年'),
|
|
63
|
+
v('Bea', '雅娜', '女', '爱喝咖啡的甜美姐姐'),
|
|
64
|
+
v('Chloe', '思怡', '女', '马来西亚白领女生'),
|
|
65
|
+
v('Emilien', '埃米尔安', '男', '浪漫的法国大哥哥'),
|
|
66
|
+
v('longanlingxin', '龙安灵心', '女', '知心温暖音'),
|
|
67
|
+
];
|
|
68
|
+
/** 这个模型认不认这个音色(工作台、doctor 拦写错的) */
|
|
69
|
+
export function isRealtimeVoice(voice) {
|
|
70
|
+
return REALTIME_VOICES.some((x) => x.voice === voice);
|
|
71
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { ActivityRun } from '../schema/index.ts';
|
|
2
|
+
export declare const ACTIVITIES_DIR = "activities";
|
|
3
|
+
export interface ActivityRef {
|
|
4
|
+
tutor: string;
|
|
5
|
+
name: string;
|
|
6
|
+
/** 文件的绝对路径 */
|
|
7
|
+
file: string;
|
|
8
|
+
}
|
|
9
|
+
/** 例子文件(cotutor activity eval 用):和 activity 放在一起,`<名>.例子.md`;跟着 activity 一起出厂,检查时不当 activity */
|
|
10
|
+
export declare const EXAMPLES_SUFFIX = ".\u4F8B\u5B50";
|
|
11
|
+
/** 某个根下(包的 agents/,或 workspace 的 agents/)每位老师的 activities/*.md;examples = 连例子文件一起(出厂、升级用) */
|
|
12
|
+
export declare function listActivities(agentsDir: string, tutor?: string, opts?: {
|
|
13
|
+
examples?: boolean;
|
|
14
|
+
}): Promise<ActivityRef[]>;
|
|
15
|
+
/** workspace 里那份的位置(就是这个名字,不认改过的名;装、升级、写都用它) */
|
|
16
|
+
export declare function activityFile(root: string, tutor: string, name: string): string;
|
|
17
|
+
/**
|
|
18
|
+
* 改过名的出厂 activity:旧名 → 新名。2026-11-03 批改 → 检查作业(孩子端方砖上的字)。
|
|
19
|
+
* upgrade 把 workspace 里的旧文件挪成新名(src/app/cli/activities.ts);旧草稿里的 `activity 批改`、旧话题记的名字照样认(activityName)
|
|
20
|
+
*/
|
|
21
|
+
export declare const ACTIVITY_RENAMES: Readonly<Record<string, string>>;
|
|
22
|
+
/**
|
|
23
|
+
* 这个名字在这位老师家里实际是哪个文件:有同名的就是它;旧名的文件挪走了认新名;新名的还没有(没 upgrade 过)认旧名。都没有 → 原样
|
|
24
|
+
* (读的时候用:跑话题、首页检查、方砖;lint 的 fileName 也要用这个,不然 name 对不上)
|
|
25
|
+
*/
|
|
26
|
+
export declare function activityName(root: string, tutor: string, name: string): string;
|
|
27
|
+
/** 读的时候找的那份:认改过的名(activityName) */
|
|
28
|
+
export declare function findActivityFile(root: string, tutor: string, name: string): string;
|
|
29
|
+
export declare function activityRunFor(root: string, tutor: string, name: string, raw?: string): Promise<ActivityRun>;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 读 activity 文件(从 app/cli/activities.ts 拆出来,2026-10-29,行为不变):在哪、每位老师有哪几个、按「名=值」的参数拼成一次跑。
|
|
3
|
+
* 运行层每轮都要读,所以不放在命令行那一层;装、升级、还原、检查仍在 app/cli/activities.ts。
|
|
4
|
+
*/
|
|
5
|
+
import { existsSync } from 'node:fs';
|
|
6
|
+
import { readFile, readdir } from 'node:fs/promises';
|
|
7
|
+
import { join } from 'node:path';
|
|
8
|
+
import { parseActivity, resolveParams } from "./activity.js";
|
|
9
|
+
import { UsageError } from "../shared/errors.js";
|
|
10
|
+
export const ACTIVITIES_DIR = 'activities';
|
|
11
|
+
/** 例子文件(cotutor activity eval 用):和 activity 放在一起,`<名>.例子.md`;跟着 activity 一起出厂,检查时不当 activity */
|
|
12
|
+
export const EXAMPLES_SUFFIX = '.例子';
|
|
13
|
+
/** 某个根下(包的 agents/,或 workspace 的 agents/)每位老师的 activities/*.md;examples = 连例子文件一起(出厂、升级用) */
|
|
14
|
+
export async function listActivities(agentsDir, tutor, opts = {}) {
|
|
15
|
+
const out = [];
|
|
16
|
+
const tutors = tutor ? [tutor] : (await readdir(agentsDir, { withFileTypes: true }).catch(() => [])).filter((d) => d.isDirectory()).map((d) => d.name).sort();
|
|
17
|
+
for (const t of tutors) {
|
|
18
|
+
const dir = join(agentsDir, t, ACTIVITIES_DIR);
|
|
19
|
+
const files = (await readdir(dir).catch(() => [])).filter((f) => f.endsWith('.md')).sort();
|
|
20
|
+
for (const f of files)
|
|
21
|
+
if (opts.examples || !f.slice(0, -3).endsWith(EXAMPLES_SUFFIX))
|
|
22
|
+
out.push({ tutor: t, name: f.slice(0, -3), file: join(dir, f) });
|
|
23
|
+
}
|
|
24
|
+
return out;
|
|
25
|
+
}
|
|
26
|
+
/** workspace 里那份的位置(就是这个名字,不认改过的名;装、升级、写都用它) */
|
|
27
|
+
export function activityFile(root, tutor, name) {
|
|
28
|
+
return join(root, 'agents', tutor, ACTIVITIES_DIR, `${name}.md`);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* 改过名的出厂 activity:旧名 → 新名。2026-11-03 批改 → 检查作业(孩子端方砖上的字)。
|
|
32
|
+
* upgrade 把 workspace 里的旧文件挪成新名(src/app/cli/activities.ts);旧草稿里的 `activity 批改`、旧话题记的名字照样认(activityName)
|
|
33
|
+
*/
|
|
34
|
+
export const ACTIVITY_RENAMES = { 批改: '检查作业' };
|
|
35
|
+
/**
|
|
36
|
+
* 这个名字在这位老师家里实际是哪个文件:有同名的就是它;旧名的文件挪走了认新名;新名的还没有(没 upgrade 过)认旧名。都没有 → 原样
|
|
37
|
+
* (读的时候用:跑话题、首页检查、方砖;lint 的 fileName 也要用这个,不然 name 对不上)
|
|
38
|
+
*/
|
|
39
|
+
export function activityName(root, tutor, name) {
|
|
40
|
+
const has = (n) => existsSync(activityFile(root, tutor, n));
|
|
41
|
+
if (has(name))
|
|
42
|
+
return name;
|
|
43
|
+
const to = ACTIVITY_RENAMES[name];
|
|
44
|
+
if (to && has(to))
|
|
45
|
+
return to;
|
|
46
|
+
const from = Object.keys(ACTIVITY_RENAMES).find((k) => ACTIVITY_RENAMES[k] === name);
|
|
47
|
+
if (from && has(from))
|
|
48
|
+
return from;
|
|
49
|
+
return name;
|
|
50
|
+
}
|
|
51
|
+
/** 读的时候找的那份:认改过的名(activityName) */
|
|
52
|
+
export function findActivityFile(root, tutor, name) {
|
|
53
|
+
return activityFile(root, tutor, activityName(root, tutor, name));
|
|
54
|
+
}
|
|
55
|
+
export async function activityRunFor(root, tutor, name, raw = '') {
|
|
56
|
+
const file = findActivityFile(root, tutor, name);
|
|
57
|
+
const text = await readFile(file, 'utf8').catch(() => null);
|
|
58
|
+
if (text === null)
|
|
59
|
+
throw new UsageError(`${file} 不在;cotutor activity check ${tutor} 看这位老师有哪些`);
|
|
60
|
+
const params = {};
|
|
61
|
+
for (const pair of raw.split(/[;;]/).map((x) => x.trim()).filter(Boolean)) {
|
|
62
|
+
// 值可以有几行(口语课的口语单)
|
|
63
|
+
const m = /^([^=]+)=([\s\S]*)$/.exec(pair);
|
|
64
|
+
if (!m)
|
|
65
|
+
throw new UsageError(`--param 写成「名=值」,几个用 ; 隔开,如 --param '词=播种、羞愧;最多画=1'(「${pair}」不对)`);
|
|
66
|
+
params[m[1].trim()] = m[2].trim();
|
|
67
|
+
}
|
|
68
|
+
const r = resolveParams(parseActivity(text).activity, params);
|
|
69
|
+
if (r.issues.length)
|
|
70
|
+
throw new UsageError(r.issues.join(';'));
|
|
71
|
+
return { name, params: r.values };
|
|
72
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Workspace } from '../schema/index.ts';
|
|
2
|
+
import { type Activity, type ActivityRun, type ActivityValue, type ConversationMessage } from '../schema/index.ts';
|
|
3
|
+
/** 这个话题是从哪个 activity 起的:话题里第一条带 activity 的消息(只记在第一条);没有 → null */
|
|
4
|
+
export declare function threadActivity(messages: readonly ConversationMessage[], thread: string): ActivityRun | null;
|
|
5
|
+
/** 读 workspace 里那份 activity 文件;不在 → null */
|
|
6
|
+
export declare function readActivity(ws: Workspace, tutor: string, name: string): Promise<Activity | null>;
|
|
7
|
+
/**
|
|
8
|
+
* 应用算的值,只算 activity 文件「应用算的」里列了的:
|
|
9
|
+
* 还能画 = 参数「最多画」减这个话题画了的(画好的与在画的),不小于 0;家长没填最多画 = 不限,不写这一项(拦法「还能画」照过)
|
|
10
|
+
* 缺 = 这个话题最后一张画图卡被哪条拦法拦下了;画了、没被拦、还没有画图卡 → 空
|
|
11
|
+
*/
|
|
12
|
+
export declare function activityState(ws: Workspace, tutor: string, date: string, messages: readonly ConversationMessage[], thread: string, run: ActivityRun, a: Pick<Activity, 'state'>, now?: number): Promise<Record<string, ActivityValue>>;
|
|
13
|
+
/** 这一轮(job)所在话题的 activity 文件「画家收到什么」;不在 activity 话题、文件不在、没有那节 → null(照 cotutor.json 的画风) */
|
|
14
|
+
export declare function paintTool(ws: Workspace, tutor: string, date: string, job: string): Promise<{
|
|
15
|
+
prompt: string;
|
|
16
|
+
negative?: string;
|
|
17
|
+
} | null>;
|
|
18
|
+
/**
|
|
19
|
+
* 画图前的拦:这一轮(job)在 activity 话题里,就照 activity 文件「应用拦的」查;不在 activity 话题、文件不在 → null(照旧画)。
|
|
20
|
+
* 返回的函数在画图队里现调,同一轮第二张看得到第一张已经在画。
|
|
21
|
+
*/
|
|
22
|
+
export declare function paintGate(ws: Workspace, tutor: string, date: string, job: string, now: () => number): Promise<(() => Promise<string | null>) | null>;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* activity 话题里应用算的值与拦法的接线(4.1):读这个话题的 activity 文件、
|
|
3
|
+
* 数这个话题画了几张、今天还剩几张、上一张为什么没画。纯判断在 src/runtime/activity.ts(gatePasses / failingGate),这里只管读盘。
|
|
4
|
+
*/
|
|
5
|
+
import { readFile } from 'node:fs/promises';
|
|
6
|
+
import { findActivityFile } from "./activities.js";
|
|
7
|
+
import { failingGate, parseActivity } from "./activity.js";
|
|
8
|
+
import { threads } from "../schema/index.js";
|
|
9
|
+
import {} from "../schema/index.js";
|
|
10
|
+
import { paintRecordAt } from "../scenes/paint/painter.js";
|
|
11
|
+
/** 这个话题是从哪个 activity 起的:话题里第一条带 activity 的消息(只记在第一条);没有 → null */
|
|
12
|
+
export function threadActivity(messages, thread) {
|
|
13
|
+
const ths = threads(messages);
|
|
14
|
+
return messages.find((m, i) => ths[i] === thread && m.activity)?.activity ?? null;
|
|
15
|
+
}
|
|
16
|
+
/** 读 workspace 里那份 activity 文件;不在 → null */
|
|
17
|
+
export async function readActivity(ws, tutor, name) {
|
|
18
|
+
const text = await readFile(findActivityFile(ws.root, tutor, name), 'utf8').catch(() => null);
|
|
19
|
+
return text === null ? null : parseActivity(text).activity;
|
|
20
|
+
}
|
|
21
|
+
/** 这个话题里的画图卡,文件顺序:哪一轮第几张 */
|
|
22
|
+
function paintCards(messages, thread) {
|
|
23
|
+
const ths = threads(messages);
|
|
24
|
+
return messages.flatMap((m, i) => (ths[i] === thread && m.section ? m.section.cards.flatMap((c, n) => (c.kind === 'paint' ? [{ job: m.job, n }] : [])) : []));
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* 应用算的值,只算 activity 文件「应用算的」里列了的:
|
|
28
|
+
* 还能画 = 参数「最多画」减这个话题画了的(画好的与在画的),不小于 0;家长没填最多画 = 不限,不写这一项(拦法「还能画」照过)
|
|
29
|
+
* 缺 = 这个话题最后一张画图卡被哪条拦法拦下了;画了、没被拦、还没有画图卡 → 空
|
|
30
|
+
*/
|
|
31
|
+
export async function activityState(ws, tutor, date, messages, thread, run, a, now = Date.now()) {
|
|
32
|
+
const out = {};
|
|
33
|
+
const want = new Set(a.state.map((s) => s.name));
|
|
34
|
+
if (!want.size)
|
|
35
|
+
return out;
|
|
36
|
+
const cards = paintCards(messages, thread);
|
|
37
|
+
const records = await Promise.all(cards.map((c) => paintRecordAt(ws, tutor, date, c.job, c.n, now)));
|
|
38
|
+
if (want.has('还能画')) {
|
|
39
|
+
const drawn = records.filter((r) => r?.state === 'done' || r?.state === 'drawing').length;
|
|
40
|
+
if (typeof run.params.最多画 === 'number')
|
|
41
|
+
out.还能画 = Math.max(0, run.params.最多画 - drawn);
|
|
42
|
+
}
|
|
43
|
+
if (want.has('缺')) {
|
|
44
|
+
const last = records[records.length - 1];
|
|
45
|
+
out.缺 = last?.state === 'none' && last.error.startsWith('gate:') ? last.error.slice(5) : '';
|
|
46
|
+
}
|
|
47
|
+
return out;
|
|
48
|
+
}
|
|
49
|
+
/** 这一轮(job)所在话题的 activity 文件「画家收到什么」;不在 activity 话题、文件不在、没有那节 → null(照 cotutor.json 的画风) */
|
|
50
|
+
export async function paintTool(ws, tutor, date, job) {
|
|
51
|
+
const { readIndex } = await import("./journal/store.js");
|
|
52
|
+
const index = await readIndex(ws, tutor, date);
|
|
53
|
+
const at = index.messages.findIndex((m) => m.job === job);
|
|
54
|
+
if (at < 0)
|
|
55
|
+
return null;
|
|
56
|
+
const run = threadActivity(index.messages, threads(index.messages)[at]);
|
|
57
|
+
const t = run ? (await readActivity(ws, tutor, run.name))?.tools.find((x) => x.tool === '画家') : null;
|
|
58
|
+
return t ? { prompt: t.prompt, ...(t.negative ? { negative: t.negative } : {}) } : null;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* 画图前的拦:这一轮(job)在 activity 话题里,就照 activity 文件「应用拦的」查;不在 activity 话题、文件不在 → null(照旧画)。
|
|
62
|
+
* 返回的函数在画图队里现调,同一轮第二张看得到第一张已经在画。
|
|
63
|
+
*/
|
|
64
|
+
export async function paintGate(ws, tutor, date, job, now) {
|
|
65
|
+
const { readIndex } = await import("./journal/store.js");
|
|
66
|
+
const index = await readIndex(ws, tutor, date);
|
|
67
|
+
const at = index.messages.findIndex((m) => m.job === job);
|
|
68
|
+
if (at < 0)
|
|
69
|
+
return null;
|
|
70
|
+
const thread = threads(index.messages)[at];
|
|
71
|
+
const run = threadActivity(index.messages, thread);
|
|
72
|
+
const a = run ? await readActivity(ws, tutor, run.name) : null;
|
|
73
|
+
if (!run || !a || !a.gates.length)
|
|
74
|
+
return null;
|
|
75
|
+
return async () => {
|
|
76
|
+
const latest = await readIndex(ws, tutor, date);
|
|
77
|
+
const ths = threads(latest.messages);
|
|
78
|
+
const mine = latest.messages.filter((_, i) => ths[i] === thread);
|
|
79
|
+
// 这一轮还没轮到的卡没有记录,不算;同一轮前面那张已经在画,算
|
|
80
|
+
const state = await activityState(ws, tutor, date, mine, thread, run, { state: [{ name: '还能画', type: '数', line: 0 }] }, now());
|
|
81
|
+
return failingGate(a, { thread: mine, job, state });
|
|
82
|
+
};
|
|
83
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* activity 文件的纯函数(形状在 src/schema/activity.ts):
|
|
3
|
+
* 解析(永不抛,写坏的行变成问题)、检查(带行号,fix = 要改 / note = 提醒)、递给老师的那节(剥注释、按参数与卡裁段)、工具人模板填插槽。不读文件。
|
|
4
|
+
*/
|
|
5
|
+
import { type Activity, type ActivityValue, type ConversationMessage } from '../schema/index.ts';
|
|
6
|
+
export type ActivityIssueLevel = 'fix' | 'note';
|
|
7
|
+
export interface ActivityIssue {
|
|
8
|
+
/** fix = 要改;note = 提醒 */
|
|
9
|
+
level: ActivityIssueLevel;
|
|
10
|
+
text: string;
|
|
11
|
+
/** 原文行号,1 起 */
|
|
12
|
+
line?: number;
|
|
13
|
+
}
|
|
14
|
+
export interface ParsedActivity {
|
|
15
|
+
activity: Activity;
|
|
16
|
+
/** 写法上的问题(哪行解析不了);对不对得上注册表由 checkActivity 查 */
|
|
17
|
+
issues: ActivityIssue[];
|
|
18
|
+
}
|
|
19
|
+
/** 解析一份 activity 文件。永不抛:写坏的行进 issues,其余照常解析 */
|
|
20
|
+
export declare function parseActivity(text: string): ParsedActivity;
|
|
21
|
+
export interface CheckOptions {
|
|
22
|
+
/** 文件名(不带 .md);给了就查 name 和它一样 */
|
|
23
|
+
fileName?: string;
|
|
24
|
+
/** 这位老师的卡(cotutor.json tutors.<老师>.cards);不给 = 全部 */
|
|
25
|
+
tutorCards?: readonly string[];
|
|
26
|
+
}
|
|
27
|
+
/** 这个 activity 的话题里老师有哪些卡:老师的并上 activity 头上的,text 总在 */
|
|
28
|
+
export declare function activityCards(a: Activity, tutorCards?: readonly string[]): string[];
|
|
29
|
+
/** 对注册表查:参数、应用算的、应用拦的、裁段的名字、正文用的卡、插槽、第一句与收 */
|
|
30
|
+
export declare function checkActivity(a: Activity, opts?: CheckOptions): ActivityIssue[];
|
|
31
|
+
/** 解析 + 检查,按行号排 */
|
|
32
|
+
export declare function lintActivity(text: string, opts?: CheckOptions): {
|
|
33
|
+
activity: Activity;
|
|
34
|
+
issues: ActivityIssue[];
|
|
35
|
+
};
|
|
36
|
+
/** 填了没有:空字符串、空列表、没给都算没填 */
|
|
37
|
+
export declare function isFilled(v: unknown): boolean;
|
|
38
|
+
/**
|
|
39
|
+
* 递给老师的那节:剥掉给人看的注释,`{{有 名}}` 按「参数填了」或「这个话题有这种卡」留或去。
|
|
40
|
+
* 没有「老师怎么带」返回 null。守卫不配对会抛(checkActivity 先报)。
|
|
41
|
+
*/
|
|
42
|
+
export declare function renderTutorSection(a: Activity, opts: {
|
|
43
|
+
params?: Record<string, unknown>;
|
|
44
|
+
cards: readonly string[];
|
|
45
|
+
}): string | null;
|
|
46
|
+
/**
|
|
47
|
+
* 首页按钮下面家长填的参数(原文)→ 按 activity 文件的「家长填的」解析成值:按声明的顺序、补缺省、按类型转。
|
|
48
|
+
* 写了没有的参数、要填的没填、类型不对,进 issues(一条一句,给首页检查);值里只留解析得了的。
|
|
49
|
+
*/
|
|
50
|
+
export declare function resolveParams(a: Activity, raw: Readonly<Record<string, string>>): {
|
|
51
|
+
values: Record<string, ActivityValue>;
|
|
52
|
+
issues: string[];
|
|
53
|
+
};
|
|
54
|
+
/** 拦法要看的:这个话题的消息(文件顺序)、这一轮的 job、应用算好的值 */
|
|
55
|
+
export interface GateInput {
|
|
56
|
+
thread: readonly Pick<ConversationMessage, 'job' | 'from' | 'action' | 'section'>[];
|
|
57
|
+
job: string;
|
|
58
|
+
state: Readonly<Record<string, ActivityValue>>;
|
|
59
|
+
}
|
|
60
|
+
/** 一条拦法过没过(规则名见 ACTIVITY_GATES;不认得的当过,activity check 会报) */
|
|
61
|
+
export declare function gatePasses(rule: string, input: GateInput): boolean;
|
|
62
|
+
/** 按 activity 文件「应用拦的」的顺序,第一条没过的规则名;都过了 → null */
|
|
63
|
+
export declare function failingGate(a: Pick<Activity, 'gates'>, input: GateInput): string | null;
|