cotutor 0.4.3 → 0.4.5
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/CHANGELOG.md +47 -0
- package/INSTALL.md +159 -0
- package/README.md +64 -17
- package/dist/app/cli/activities.d.ts +1 -1
- package/dist/app/cli/activities.js +2 -2
- package/dist/app/cli/cert.js +2 -1
- package/dist/app/cli/chalk/main.d.ts +0 -1
- package/dist/app/cli/chalk/main.js +8 -12
- package/dist/app/cli/commands.d.ts +50 -0
- package/dist/app/cli/commands.js +353 -0
- package/dist/app/cli/doctor.js +32 -17
- package/dist/app/cli/guide.d.ts +6 -0
- package/dist/app/cli/guide.js +17 -0
- package/dist/app/cli/init.d.ts +2 -0
- package/dist/app/cli/init.js +60 -6
- package/dist/app/cli/main.js +109 -46
- package/dist/app/cli/migrate.js +1 -1
- package/dist/app/cli/port.js +2 -10
- package/dist/app/cli/root-ca.d.ts +8 -0
- package/dist/app/cli/root-ca.js +33 -0
- package/dist/app/cli/sandbox.js +2 -7
- package/dist/app/cli/serve.d.ts +11 -2
- package/dist/app/cli/serve.js +49 -3
- package/dist/app/cli/service.d.ts +4 -1
- package/dist/app/cli/service.js +5 -2
- package/dist/app/cli/shipped.js +1 -1
- package/dist/app/cli/skeleton.d.ts +2 -0
- package/dist/app/cli/skeleton.js +3 -2
- package/dist/app/cli/skills.js +2 -2
- package/dist/app/cli/themes.js +2 -2
- package/dist/app/cli/tray.d.ts +6 -1
- package/dist/app/cli/tray.js +8 -5
- package/dist/app/cli/tutors.d.ts +2 -2
- package/dist/app/cli/tutors.js +4 -4
- package/dist/app/cli/update-cmd.js +4 -4
- package/dist/app/cli/usage.d.ts +26 -2
- package/dist/app/cli/usage.js +167 -38
- package/dist/app/http/access.js +1 -1
- package/dist/app/http/app.js +5 -1
- package/dist/app/http/parent-home.js +5 -0
- package/dist/app/http/stage.js +2 -2
- package/dist/app/mock/mock.js +3 -0
- package/dist/app/skills/analyze-doc.js +4 -8
- package/dist/app/skills/home-doc.js +3 -7
- package/dist/app/skills/tune-doc.js +4 -8
- package/dist/app/workspace.d.ts +16 -3
- package/dist/app/workspace.js +31 -9
- package/dist/runtime/home/home.js +1 -1
- package/dist/runtime/runner.js +2 -2
- package/dist/shared/home.d.ts +2 -0
- package/dist/shared/home.js +9 -0
- package/dist/stage/fonts/Assistant/Assistant-Bold.woff2 +0 -0
- package/dist/stage/fonts/Assistant/Assistant-Medium.woff2 +0 -0
- package/dist/stage/fonts/Assistant/Assistant-Regular.woff2 +0 -0
- package/dist/stage/fonts/Assistant/Assistant-SemiBold.woff2 +0 -0
- package/dist/stage/fonts/Cascadia/CascadiaCode-Regular.woff2 +0 -0
- package/dist/stage/fonts/ComicShanns/ComicShanns-Regular-279a7b317d12eb88de06167bd672b4b4.woff2 +0 -0
- package/dist/stage/fonts/ComicShanns/ComicShanns-Regular-6e066e8de2ac57ea9283adb9c24d7f0c.woff2 +0 -0
- package/dist/stage/fonts/ComicShanns/ComicShanns-Regular-dc6a8806fa96795d7b3be5026f989a17.woff2 +0 -0
- package/dist/stage/fonts/ComicShanns/ComicShanns-Regular-fcb0fc02dcbee4c9846b3e2508668039.woff2 +0 -0
- package/dist/stage/fonts/Excalifont/Excalifont-Regular-349fac6ca4700ffec595a7150a0d1e1d.woff2 +0 -0
- package/dist/stage/fonts/Excalifont/Excalifont-Regular-3f2c5db56cc93c5a6873b1361d730c16.woff2 +0 -0
- package/dist/stage/fonts/Excalifont/Excalifont-Regular-41b173a47b57366892116a575a43e2b6.woff2 +0 -0
- package/dist/stage/fonts/Excalifont/Excalifont-Regular-623ccf21b21ef6b3a0d87738f77eb071.woff2 +0 -0
- package/dist/stage/fonts/Excalifont/Excalifont-Regular-a88b72a24fb54c9f94e3b5fdaa7481c9.woff2 +0 -0
- package/dist/stage/fonts/Excalifont/Excalifont-Regular-b9dcf9d2e50a1eaf42fc664b50a3fd0d.woff2 +0 -0
- package/dist/stage/fonts/Excalifont/Excalifont-Regular-be310b9bcd4f1a43f571c46df7809174.woff2 +0 -0
- package/dist/stage/fonts/Liberation/LiberationSans-Regular.woff2 +0 -0
- package/dist/stage/fonts/Lilita/Lilita-Regular-i7dPIFZ9Zz-WBtRtedDbYE98RXi4EwSsbg.woff2 +0 -0
- package/dist/stage/fonts/Lilita/Lilita-Regular-i7dPIFZ9Zz-WBtRtedDbYEF8RXi4EwQ.woff2 +0 -0
- package/dist/stage/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTA3j6zbXWjgevT5.woff2 +0 -0
- package/dist/stage/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTQ3j6zbXWjgeg.woff2 +0 -0
- package/dist/stage/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTk3j6zbXWjgevT5.woff2 +0 -0
- package/dist/stage/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTo3j6zbXWjgevT5.woff2 +0 -0
- package/dist/stage/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTs3j6zbXWjgevT5.woff2 +0 -0
- package/dist/stage/fonts/Virgil/Virgil-Regular.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-019d66dcad46dc156b162d267f981c20.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-04b718e5623574919c8b0dea5f301444.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-069e77aac84590e2e991d0a0176d34f2.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-06c77b8c66e51ed6c63ccb502dd8b8af.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-08e0dc436ad0ad61ba5558db0674d762.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-093b9ef39a46ceae95a1df18a0a3a326.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-095c169f3314805276f603a362766abd.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-09850c4077f3fffe707905872e0e2460.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-0986d134c05864f5025962eef9f994a0.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-0b5d723fdc4e249c140f0909e87d03b4.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-0f626226ba1272e832aea87bafd9720e.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-0f7fb1e0d5015bb1371343153ecf7ce3.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-0fa55a080fcd0f9dc2e0b0058b793df8.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-0facdf1ea213ba40261022f5d5ed4493.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-10a7ae9a371830a80c3d844acf1c02d7.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-112c051027b2d766c19a519f6ee1f4f7.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-11c345711937f0ba4b8f7b6b919c8440.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-12b52b58eb3df36804b9a654ec9ee194.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-13ae07ed2e272d26d59bc0691cd7117a.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-13d2887ec8ee73c43acdabc52a05af7b.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-145aa02cdd91946e67dc934e1acffe75.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-15dc6d811c9cd078f9086a740d5a1038.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-173945821411c09f70c95f98d590e697.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-1b611157cd46bb184d4fa4dae2d6a2b8.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-1e6fd68f1f3902ce48ce8c69df385622.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-1ee544f0f1dac422545c505baa788992.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-1fdc0c67ed57263a80fd108c1f6ccf24.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-203b0e569e3b14aac86a003dc3fa523e.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-20cc1bbf50e7efb442756cb605672c1f.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-20e7bf72fa05de9adf7dbcc7bf51dde6.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-21430ee05a1248901da8d0de08744d47.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-23686f7f29da6e8008c36dd3a80c83d6.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-23ad2d71b280f00b1363b95b7bea94eb.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-23f228f3999c01983860012330e4be08.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-24476a126f129212beb33f66853ea151.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-24a21c1e4449222e8d1898d69ff3a404.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-25b7f38e18f035f96cb5e547bd2bd08c.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-29cec36cd205b211da97acabaa62f055.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-2a26d20a23b00898ce82f09d2ee47c3f.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-2adbc89c11e65905393d3dfc468b9d5b.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-2b7441d46298788ac94e610ffcc709b6.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-2b77e8ebfb2367ab2662396a60e7d320.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-2cf96d082d35ea3d8106851223ad0d16.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-2d43040e86ff03ba677f6f9c04cd0805.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-2e33e8dc771ef5e1d9127d60a6b73679.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-33432927cd87d40cfe393c7482bf221f.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-353f33792a8f60dc69323ddf635a269e.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-36925dfe329a45086cbb7fc5c20d45ac.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-3717077e38f98d89eae729b6c14e56dc.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-3756e81d3e149cf6099163ee79944fec.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-395c35dd584b56b0789f58a0559beaf1.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-3c9de2ae0ea4bc91a510942dfa4be8d2.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-3cc70dbb64df5b21f1326cc24dee2195.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-3e1f8f654357353bf0e04ba5c34b5f7f.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-3e63ed8162808a9e425ed80a8bc79114.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-3eaa538115d76932653c21d8dc28f207.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-4095eb84ef3874e2600247bee0b04026.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-41521fade99856108931b4768b1b2648.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-450da755d5bcb70906e1295e559b9602.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-452225341522a7942f0f6aab1a5c91a3.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-4535823663ad81405188a528d8f2b1a2.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-4806e761d750087c2d734fc64596eaff.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-4a0fdb40036e87b40aa08dd30584cb85.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-4a38cc3e9cf104e69ba246d37f8cf135.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-4aca6a43e59aceee2166b0c7e4e85ef1.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-4bfaa8ffa64c5ee560aa2daba7c9cbd3.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-4dc6d5f188d5c96d44815cd1e81aa885.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-4ddc14ed3eb0c3e46364317dfc0144a3.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-4ee10ae43505e2e0bc62656ced49c0fa.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-4f50e5136e136527280bc902c5817561.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-51502f1206be09c565f1547c406e9558.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-51a0e808bbc8361236ac521a119758a3.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-52a84a22fd1369bffeaf21da2d6158dc.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-5330a2119a716e4e7224ed108b085dac.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-543fa46ace099a7099dad69123399400.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-544fc28abe2c5c30e62383fd4dac255f.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-54acdfc2166ad7fcbd074f75fd4a56ba.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-5572b3513ba8df57a3d5d7303ee6b11b.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-56467a5c8840c4d23a60b2f935114848.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-56a32a7689abd0326e57c10c6c069bb4.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-57862b464a55b18c7bf234ce22907d73.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-583d166e56ba0de4b77eabb47ef67839.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-5882ffa04f32584d26109137e2da4352.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-58fd02350d0bc52cf1ca3bb32ce9766e.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-5935a5775af3d5c6307ac667bd9ae74e.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-59e9ff77b0efaf684bc09274fb6908c9.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-5a1ce3117cfe90c48e8fb4a9a00f694d.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-5a45d991244d4c7140217e1e5f5ca4f4.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-5a7fac4b8b23a6e4e5ba0c9bf1756c91.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-5b0ed6971aaab9c8ad563230bd5471a7.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-5d2898fbc097a7e24c6f38d80587621e.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-603aefd23e350ba7eb124273e3c9bcf1.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-60a3089806700d379f11827ee9843b6b.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-60a41c7e1c68f22424e6d22df544bc82.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-642b26e2e5f5fb780b51b593dbc8c851.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-66493ba5a8367f2928812f446f47b56a.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-670ba603758d94268e8606f240a42e12.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-671a2c20b1eb9e4ef8a192833940e319.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-684d65f1793cac449dde5d59cb3c47fb.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-69c09cc5fa3e55c74fc4821f76909cc3.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-6ae5b42180ad70b971c91e7eefb8eba2.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-6e092f71c1e634059ada0e52abadce67.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-6f3256af8454371776bc46670d33cc65.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-6fe5c5973cc06f74b2387a631ea36b88.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-70c2eb8d64e71a42a834eb857ea9df51.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-70e811fd7994e61f408c923de6ddd078.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-7197d6fda6cba7c3874c53d6381ca239.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-72252d73220fa3cd856677888cee1635.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-72536a3d71b694a0d53dd90ddceae41e.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-726303e0774b4e678bff8c2deb6ca603.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-733171b4ffcd17ea1fe1c0ba627173bf.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-739bc1a567439c7cffcd1614644593d2.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-73e309718fd16cea44b4d54a33581811.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-7494dc504ae00ee9cd0505f990f88c5d.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-74e2263a91439c25b91d5132ce9f4d62.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-761d05e3cd968cf574166867998ef06a.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-7718fe60986d8b42b1be9c5ace5ccf25.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-774d4f764a1299da5d28ec2f2ffe0d69.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-79d494361ae093b69e74ee9dbe65bfd4.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-79f007c1c6d07557120982951ea67998.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-7a07ddc0f0c0f5f4a9bad6ee3dda66b5.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-7ab2bed91166a9dca83a5ebfbe2a7f38.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-7ccce86603f80a099ddb0cb21d4ae3e3.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-7e4bde7e9c7f84cd34d8a845e384c746.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-7e929f262f30c8ee78bf398150b1a7cd.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-7eb9fffd1aa890d07d0f88cc82e6cfe4.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-7f855356ab893b0d2b9c1c83b8116f0e.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-829615148e6357d826b9242eb7fbbd1e.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-866fa7613df6b3fd272bcfd4530c0bb9.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-87599f94b6cc129d505b375798d0d751.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-8c2f33cee3993174f7e87c28e4bf42ee.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-8d3bcabb847b56243b16afe62adaaf21.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-8de5b863cb50dfefdd07cb11c774d579.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-8e9f97f01034820170065b2921b4fb5e.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-8f476c4c99813d57cbe6eca4727388ad.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-903bb6865f3452e2fda42e3a25547bc5.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-91ddb2969bf2d31ba02ad82998d1314c.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-938d90c10ff8c20386af7f242c05d6b0.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-93fc8f28a33234bcadf1527cafabd502.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-95429962233afd82db1c27df1500a28c.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-9544732d2e62d1a429674f8ee41b5d3a.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-9592bfc861f07bcb8d75c196b370e548.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-95bfd249da4902577b4b7d76ebdd0b44.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-968cffdc8ee679da094e77ebf50f58ef.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-97f7f48ce90c9429bf32ae51469db74d.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-982b630266d87db93d2539affb1275c6.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-98f2ad84457de7f3740d9920b8fa8667.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-99a16ef6a64934d5781933dbd9c46b2e.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-9cfb2a77a4e45025105ad29a1748b90d.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-9d81066dd2b337c938df6e90380a00dc.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-9eb5a99df4e76ac3363453ac9ca288b1.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-a004ddfcb26e67bd6e678c8ed19e25ce.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-a0ca5df4258213d7fc9fce80f65ce760.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-a1f916d6039285c4ffb900cd654e418f.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-a203b91dad570bf05a58c3c3ddb529bf.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-a365e82ed54697a52f27adcea1315fe8.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-a4c34be6d42152e64b0df90bc4607f64.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-a7accba310e821da5505f71c03b76bdb.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-aa0d470430e6391eca720c7cfa44446f.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-aa5c9ca6cf4fba00433b7aa3fa10671a.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-ac9ceb44437becc3e9c4dbfebab7fc2d.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-b1220a3c61f85cc0408deedb4c5f57a2.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-b358f7a51ece39a3247942b1feabdb29.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-b57aaedfd8ebdf3931f25119dc6a5eb2.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-b5c1596551c256e0e9cf02028595b092.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-b6d128682ee29e471486354d486a1b90.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-b6fd38ca30869792244804b04bc058da.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-b7d203b051eff504ff59ddca7576b6a9.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-b96d9226ce77ec94ceca043d712182e6.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-ba3de316d63c7e339987b16f41a0b879.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-bafff7a14c27403dcc6cf1432e8ea836.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-bd77e3c7f9e0b072d96af37f73d1aa32.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-be549ab72f0719d606a5c01e2c0219b6.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-c16ed9740b85badf16e86ea782a3062f.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-c1f94158256bb1f3bf665b053d895af9.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-c40533fdf4cc57177b12803598af7e59.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-c4a687ac4f0c2766eefc9f77ed99cddf.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-c69f61a4ab18d0488c8d1fc12e7028e8.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-c8b71798409ccc126ee264a00aadcf21.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-c99eda15fc26a2941579560f76c3a5cf.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-cb17fc3db95f6d139afc9d31a8e93293.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-cbaaefaaf326668277aa24dfa93c4d28.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-cd145ce4a0ea18469358df53c207bc1b.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-cdbce89e82cc1ab53a2decbf5819278f.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-ce4884f96f11589608b76b726a755803.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-cf2cc71752631e579e35b0e423bf2638.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-cf6ff4e0f491ca0cf3038187a997b9b4.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-cfb211578629b7e8153b37240de6a9d5.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-d0cf73942fea1c74edbdf0b3011f4656.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-d2666cbed13462c5dc36fa2f15c202ca.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-d3716376641d615e2995605b29bca7b6.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-dac48066b5883d8b4551fc584f0c2a3e.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-dbea1af6dcd9860be40c3d18254338f5.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-e11567fd2accf9957cd0d3c2be937d87.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-e2ead7ea7da0437f085f42ffc05f8d13.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-e3fcf5180fd466c8915c4e8069491054.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-e480d9c614742d05f0e78f274f1e69e6.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-e4bca6cfa53e499cae0a6be4894a90e9.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-e51ef413167c6e14e0c0fdcc585f2fc9.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-e5f453bb04da18eed01675eeebd88bf8.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-e656f091b9dc4709722c9f4b84d3c797.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-ec181b795ac1fb5a50d700b6e996d745.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-ee8bae97908d5147b423f77ad0d3c1bb.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-f0f13b5c60e0af5553bd359f5513be1b.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-f2b54d4e7be0eaefe1c2c56836fa5368.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-f56414bf9bced67990def8660e306759.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-f5d079153c99a25b9be5b8583c4cc8a7.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-f6032fc06eb20480f096199713f70885.woff2 +0 -0
- package/dist/stage/fonts/Xiaolai/Xiaolai-Regular-f8ee5d36068a42b51d0e4a1116cfcec1.woff2 +0 -0
- package/dist/ui/dev/dev-page.js +5 -5
- package/dist/ui/kid/kid-page.js +2 -0
- package/dist/ui/kid/offline-sw.d.ts +1 -0
- package/dist/ui/kid/offline-sw.js +42 -0
- package/dist/ui/parent/parent-home-page.js +9 -6
- package/install.ps1 +67 -0
- package/install.sh +84 -0
- package/package.json +15 -10
- package/skills/cotutor-analyze/SKILL.md +1 -1
- package/skills/cotutor-analyze/references//345/221/275/344/273/244/344/270/216/346/226/207/344/273/266.md +168 -10
- package/skills/cotutor-home/SKILL.md +1 -1
- package/skills/cotutor-home/references//345/221/275/344/273/244.md +75 -7
- package/skills/cotutor-tune/SKILL.md +8 -8
- package/skills/cotutor-tune/references//345/255/227/346/256/265.md +164 -10
- package/skills/cotutor-tutor/SKILL.md +1 -1
package/dist/app/cli/sandbox.js
CHANGED
|
@@ -5,21 +5,16 @@
|
|
|
5
5
|
* 已经在 sandbox 里(cwd 在里面、--workspace 指过来)就用它;--fresh 从它记着的真 workspace 重新分,不套娃。
|
|
6
6
|
*/
|
|
7
7
|
import { copyFile, cp, mkdir, readdir, rename, rm, stat, writeFile } from 'node:fs/promises';
|
|
8
|
-
import { basename, dirname,
|
|
8
|
+
import { basename, dirname, join, relative } from 'node:path';
|
|
9
9
|
import { PATH_ROLES, ROLE_DEFAULTS, WORKSPACE_ROLES } from "../../schema/index.js";
|
|
10
10
|
import { SANDBOX_DIR, SANDBOX_KEEP_MACHINE, SANDBOX_MARK, SANDBOX_SKIP, SANDBOX_TITLE, SANDBOX_VAULT } from "../../schema/workspace.js";
|
|
11
|
-
import { CONFIG_FILE, UsageError, expandPath, loadWorkspace, parseConfig, readJson, readSandboxMark, redactHome, resolveRoot } from "../workspace.js";
|
|
11
|
+
import { CONFIG_FILE, UsageError, expandPath, isInside as inside, loadWorkspace, parseConfig, readJson, readSandboxMark, redactHome, resolveRoot } from "../workspace.js";
|
|
12
12
|
import { sandboxPort } from "./port.js";
|
|
13
13
|
import { DIRS, LEDGER_FILES } from "./skeleton.js";
|
|
14
14
|
/** vault 侧指在外面也不怕的角色:只读的材料,老师不往里写 */
|
|
15
15
|
const READ_ONLY_ROLES = ['textbooks', 'reference'];
|
|
16
16
|
/** ~/cotutor/ray → ~/cotutor/.sandbox/ray */
|
|
17
17
|
export const sandboxRootOf = (real) => join(dirname(real), SANDBOX_DIR, basename(real));
|
|
18
|
-
/** p 是 dir 本身或在它里面 */
|
|
19
|
-
function inside(p, dir) {
|
|
20
|
-
const r = relative(dir, p);
|
|
21
|
-
return r === '' || (r !== '..' && !r.startsWith(`..${sep}`) && !isAbsolute(r));
|
|
22
|
-
}
|
|
23
18
|
async function exists(p) {
|
|
24
19
|
return stat(p).then(() => true, () => false);
|
|
25
20
|
}
|
package/dist/app/cli/serve.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { type Server } from 'node:http';
|
|
1
|
+
import { type RequestListener, type Server } from 'node:http';
|
|
2
|
+
import { type Server as NetServer } from 'node:net';
|
|
2
3
|
import { siteUrl } from '../../shared/site-url.ts';
|
|
3
4
|
import type { ListenInfo } from '../../ui/parent/qr-page.ts';
|
|
4
5
|
import { type AppContext } from '../http/app.ts';
|
|
@@ -14,7 +15,8 @@ export interface ServeOptions extends ResolveOptions {
|
|
|
14
15
|
awake?: boolean;
|
|
15
16
|
}
|
|
16
17
|
export interface ServeResult {
|
|
17
|
-
|
|
18
|
+
/** 用 https 时是前面那层(同一个端口分给 https 和 http);不用 https 就是 http 服务本身 */
|
|
19
|
+
server: NetServer;
|
|
18
20
|
ctx: AppContext;
|
|
19
21
|
ws: Workspace;
|
|
20
22
|
port: number;
|
|
@@ -42,6 +44,13 @@ export declare function localName(name?: string): string;
|
|
|
42
44
|
export declare function certCovers(certFile: string, host: string): boolean;
|
|
43
45
|
/** 扫码页要的三样;listen 之后才知道真端口 */
|
|
44
46
|
export declare function listenInfo(https: boolean, port: number): ListenInfo;
|
|
47
|
+
/**
|
|
48
|
+
* 用 https 时 http 那一面只做两件事:给根证书(平板扫码装证书,这时还不信任 https,所以走 http)、别的都跳到 https
|
|
49
|
+
* (切到 https 以前开着的页面、旧书签、手输的 http 地址)。只给 rootCA.pem,私钥永远不给;找不到就说怎么弄。
|
|
50
|
+
*/
|
|
51
|
+
export declare function plainHandler(caFile: () => string | null): RequestListener;
|
|
52
|
+
/** 同一个端口既认 https 又认 http:看第一个字节,TLS 握手(0x16)交给 https,别的交给 http 那一面 */
|
|
53
|
+
export declare function httpAndHttps(secure: Server, plain: Server): NetServer;
|
|
45
54
|
export declare function serveWorkspace(opts?: ServeOptions): Promise<ServeResult>;
|
|
46
55
|
/**
|
|
47
56
|
* busy() 为真就起一个拦闲置睡眠的子进程,为假就停;serve 没了它自己退:macOS 是 caffeinate -i -w <pid>,Windows 是一段 PowerShell(service-windows.ts 的 awakeScript);Linux 什么都不做。
|
package/dist/app/cli/serve.js
CHANGED
|
@@ -7,9 +7,11 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { execFileSync, spawn } from 'node:child_process';
|
|
9
9
|
import { X509Certificate } from 'node:crypto';
|
|
10
|
-
import { readFileSync } from 'node:fs';
|
|
10
|
+
import { createReadStream, existsSync, readFileSync } from 'node:fs';
|
|
11
11
|
import { createServer as createHttp } from 'node:http';
|
|
12
12
|
import { createServer as createHttps } from 'node:https';
|
|
13
|
+
import { createServer as createNetServer } from 'node:net';
|
|
14
|
+
import { rootCaFile } from "./root-ca.js";
|
|
13
15
|
import { hostname, networkInterfaces } from 'node:os';
|
|
14
16
|
import { join } from 'node:path';
|
|
15
17
|
import { siteUrl } from "../../shared/site-url.js";
|
|
@@ -91,6 +93,47 @@ export function listenInfo(https, port) {
|
|
|
91
93
|
const ip = lanAddresses()[0];
|
|
92
94
|
return { name: siteUrl(scheme, localName(), port), ip: ip ? siteUrl(scheme, ip, port) : null, https };
|
|
93
95
|
}
|
|
96
|
+
/**
|
|
97
|
+
* 用 https 时 http 那一面只做两件事:给根证书(平板扫码装证书,这时还不信任 https,所以走 http)、别的都跳到 https
|
|
98
|
+
* (切到 https 以前开着的页面、旧书签、手输的 http 地址)。只给 rootCA.pem,私钥永远不给;找不到就说怎么弄。
|
|
99
|
+
*/
|
|
100
|
+
export function plainHandler(caFile) {
|
|
101
|
+
return (req, res) => {
|
|
102
|
+
const path = (req.url ?? '/').split('?')[0];
|
|
103
|
+
if (req.method === 'GET' && (path === '/ca.crt' || path === '/ca')) {
|
|
104
|
+
const file = caFile();
|
|
105
|
+
if (file && existsSync(file)) {
|
|
106
|
+
res.writeHead(200, { 'content-type': 'application/x-x509-ca-cert', 'content-disposition': 'attachment; filename="cotutor-ca.crt"', 'cache-control': 'no-store' });
|
|
107
|
+
createReadStream(file).pipe(res);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
res.writeHead(404, { 'content-type': 'text/plain; charset=utf-8' });
|
|
111
|
+
res.end('这台电脑上没找到根证书:先在电脑上跑 mkcert -install 和 cotutor cert');
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
res.writeHead(301, { location: `https://${req.headers.host ?? 'localhost'}${req.url ?? '/'}`, 'cache-control': 'no-store' });
|
|
115
|
+
res.end();
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
/** 同一个端口既认 https 又认 http:看第一个字节,TLS 握手(0x16)交给 https,别的交给 http 那一面 */
|
|
119
|
+
export function httpAndHttps(secure, plain) {
|
|
120
|
+
const front = createNetServer((sock) => {
|
|
121
|
+
sock.on('error', () => undefined);
|
|
122
|
+
sock.once('data', (first) => {
|
|
123
|
+
sock.pause();
|
|
124
|
+
sock.unshift(first);
|
|
125
|
+
(first[0] === 0x16 ? secure : plain).emit('connection', sock);
|
|
126
|
+
process.nextTick(() => sock.resume());
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
front.once('close', () => {
|
|
130
|
+
for (const s of [secure, plain]) {
|
|
131
|
+
s.close();
|
|
132
|
+
s.closeAllConnections();
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
return front;
|
|
136
|
+
}
|
|
94
137
|
export async function serveWorkspace(opts = {}) {
|
|
95
138
|
const ws = loadWorkspace(opts.workspace, opts);
|
|
96
139
|
// 不探 CLI(起服务不用等它);防火墙要查:平板连不上时这里是家长唯一看得到提醒的地方
|
|
@@ -101,10 +144,13 @@ export async function serveWorkspace(opts = {}) {
|
|
|
101
144
|
ctx.openCalls = () => liveUpgrade.openCalls();
|
|
102
145
|
const handler = createHandler(ctx);
|
|
103
146
|
const tls = opts.http ? null : httpsFiles(ws);
|
|
104
|
-
const
|
|
147
|
+
const app = tls ? createHttps({ cert: readFileSync(tls.cert), key: readFileSync(tls.key) }, handler) : createHttp(handler);
|
|
105
148
|
// WebSocket:实时老师的那条线(src/app/ws/);不认就关掉
|
|
106
|
-
|
|
149
|
+
app.on('upgrade', (req, socket, head) => { void liveUpgrade(req, socket, head, ctx).then((took) => { if (!took)
|
|
107
150
|
socket.destroy(); }, () => socket.destroy()); });
|
|
151
|
+
// 用 https 时同一个端口也认 http(给平板装根证书、把 http 的跳过去)
|
|
152
|
+
const caFile = tls ? await rootCaFile() : null;
|
|
153
|
+
const server = tls ? httpAndHttps(app, createHttp(plainHandler(() => caFile))) : app;
|
|
108
154
|
// 别的程序只占着 127.0.0.1 时,绑通配地址照样成功:平板连到这边,这台电脑上开 localhost 却到了别的程序。先问一声,当被占处理(main.ts 接)
|
|
109
155
|
if (port !== 0 && (await answersLocally(port)))
|
|
110
156
|
throw Object.assign(new Error(`port ${port} answers on 127.0.0.1`), { code: 'EADDRINUSE', port });
|
|
@@ -82,7 +82,10 @@ export interface ServiceSpec {
|
|
|
82
82
|
export declare const xml: (s: string) => string;
|
|
83
83
|
/** macOS 的 LaunchAgent */
|
|
84
84
|
export declare function launchdPlist(s: ServiceSpec): string;
|
|
85
|
-
/**
|
|
85
|
+
/**
|
|
86
|
+
* Linux 的 systemd 用户服务。WorkingDirectory= 不认引号(只有 ExecStart=、Environment= 这种列表才认),
|
|
87
|
+
* 加了引号 systemd 当它是相对路径,整个服务起不来(2026-11-09 在 Ubuntu 22.04 / systemd 249 上撞到);它只要 % 写两个
|
|
88
|
+
*/
|
|
86
89
|
export declare function systemdUnit(s: ServiceSpec): string;
|
|
87
90
|
/** 从服务文件里读回跑的参数(找它是哪个 workspace 的) */
|
|
88
91
|
export declare function serviceArgs(text: string): string[];
|
package/dist/app/cli/service.js
CHANGED
|
@@ -218,7 +218,10 @@ ${s.args.map((a) => ` ${str(a)}`).join('\n')}
|
|
|
218
218
|
}
|
|
219
219
|
/** systemd 的一个参数:双引号括起来,反斜杠与引号转义,% 写两个 */
|
|
220
220
|
const sd = (v) => `"${v.replaceAll('\\', '\\\\').replaceAll('"', '\\"').replaceAll('%', '%%')}"`;
|
|
221
|
-
/**
|
|
221
|
+
/**
|
|
222
|
+
* Linux 的 systemd 用户服务。WorkingDirectory= 不认引号(只有 ExecStart=、Environment= 这种列表才认),
|
|
223
|
+
* 加了引号 systemd 当它是相对路径,整个服务起不来(2026-11-09 在 Ubuntu 22.04 / systemd 249 上撞到);它只要 % 写两个
|
|
224
|
+
*/
|
|
222
225
|
export function systemdUnit(s) {
|
|
223
226
|
return `# cotutor service install 写的;改了会被下次 install 盖掉。卸掉:cotutor service uninstall --workspace ${s.root}
|
|
224
227
|
[Unit]
|
|
@@ -227,7 +230,7 @@ After=network-online.target
|
|
|
227
230
|
|
|
228
231
|
[Service]
|
|
229
232
|
ExecStart=${s.args.map(sd).join(' ')}
|
|
230
|
-
WorkingDirectory=${
|
|
233
|
+
WorkingDirectory=${s.root.replaceAll('%', '%%')}
|
|
231
234
|
Environment=${sd(`PATH=${s.path}`)}
|
|
232
235
|
Environment=${sd(`COTUTOR_SERVICE=${s.label}`)}
|
|
233
236
|
Restart=on-failure
|
package/dist/app/cli/shipped.js
CHANGED
|
@@ -42,6 +42,6 @@ export async function writeManifest(root, m) {
|
|
|
42
42
|
const file = join(root, SHIPPED_FILE);
|
|
43
43
|
await mkdir(dirname(file), { recursive: true });
|
|
44
44
|
const tmp = `${file}.tmp`;
|
|
45
|
-
await writeFile(tmp, `${JSON.stringify({ ...m, _note: '出厂时老师文件的 hash,cotutor
|
|
45
|
+
await writeFile(tmp, `${JSON.stringify({ ...m, _note: '出厂时老师文件的 hash,cotutor refresh 据此分辨「没改过」与「改过」;机器写,不用手改' }, null, 2)}\n`);
|
|
46
46
|
await rename(tmp, file);
|
|
47
47
|
}
|
|
@@ -30,6 +30,8 @@ export interface ConfigTemplateInput {
|
|
|
30
30
|
slug: string;
|
|
31
31
|
name?: string;
|
|
32
32
|
port?: number;
|
|
33
|
+
/** 写进 paths.vault 的(~/… 或绝对路径);不给就不写,vault 落在 workspace 根(旧版的布局) */
|
|
34
|
+
vault?: string;
|
|
33
35
|
tutors: ShippedAgent[];
|
|
34
36
|
}
|
|
35
37
|
/** cotutor.json 模板:只在文件不存在时写入;政策文件永不自动重建或覆盖(家长的决定不由机器代做)。 */
|
package/dist/app/cli/skeleton.js
CHANGED
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
* cotutor.json / .cotutor/shipped.json(出厂 hash)/ .agents/skills/(技能;.claude/skills 是指过去的链,给 Claude Code)
|
|
5
5
|
* agents/<name>.md(老师文件,拷自本包 grades/grade-<n>/agents/,是家长的;所有运行时都从这里拿老师正文)与 agents/<name>/(老师的家 = 会话 cwd)
|
|
6
6
|
* ledger/(产物账本)/ conversations/(对话索引与转录)
|
|
7
|
-
* vault 侧(《obsidian仓库设计.md》):档案 / 课程表 / 日记 / 教材 / 计划 / 参考,init 只建档案与参考 README(缺了才写)
|
|
7
|
+
* vault 侧(《obsidian仓库设计.md》):档案 / 课程表 / 日记 / 教材 / 计划 / 参考,init 只建档案与参考 README(缺了才写);
|
|
8
|
+
* vault 不在 workspace 里,缺省是旁边的 <目录名>-vault/(2026-11-09;旧版没写 paths.vault 的落在 workspace 根)
|
|
8
9
|
*/
|
|
9
10
|
import { readFileSync } from 'node:fs';
|
|
10
11
|
import { readFile, readdir } from 'node:fs/promises';
|
|
@@ -140,7 +141,7 @@ export function configTemplate(input) {
|
|
|
140
141
|
title: input.name ? `${input.name}的老师们` : 'cotutor',
|
|
141
142
|
kid: { slug: input.slug, ...(input.name ? { name: input.name } : {}) },
|
|
142
143
|
server: { port: input.port ?? DEFAULT_PORT },
|
|
143
|
-
paths: {},
|
|
144
|
+
paths: input.vault ? { vault: input.vault } : {},
|
|
144
145
|
policyDefaults: {},
|
|
145
146
|
tutors,
|
|
146
147
|
// 缺省 api:应用直连百炼,家长端「首页」填一次按量 key + 业务空间 id 就能用(2026-10-31);2026-11-02 起只有 API 运行时
|
package/dist/app/cli/skills.js
CHANGED
|
@@ -124,7 +124,7 @@ export async function installSkills(root) {
|
|
|
124
124
|
steps.push({ item, action: 'exists', note: s.state === 'latest' ? '已按本包刷新(机器件)' : '已按本包换新(机器件,不认改动)' });
|
|
125
125
|
}
|
|
126
126
|
else
|
|
127
|
-
steps.push({ item, action: 'exists', note: s.state === 'custom' ? `自定义(基于 ${s.basedOn})` : s.state === 'upgradable' ? '可升级(cotutor
|
|
127
|
+
steps.push({ item, action: 'exists', note: s.state === 'custom' ? `自定义(基于 ${s.basedOn})` : s.state === 'upgradable' ? '可升级(cotutor refresh)' : s.state === 'untracked' ? '已有(没有出厂记录);升级时当自定义对待' : undefined });
|
|
128
128
|
}
|
|
129
129
|
if (touched)
|
|
130
130
|
await writeManifest(root, { ...manifest, version: PACKAGE_VERSION });
|
|
@@ -187,7 +187,7 @@ export async function linkClaudeSkills(root) {
|
|
|
187
187
|
return key(resolve(dirname(link), to.replace(/^\\\\\?\\/, ''))) === key(resolve(root, SKILLS_DIR)) ? { item, action: 'exists' } : { item, action: 'kept', note: `已经是指向 ${to} 的链,没动` };
|
|
188
188
|
}
|
|
189
189
|
if (st)
|
|
190
|
-
return { item, action: 'kept', note: `${CLAUDE_SKILLS_LINK} 是实体目录,没建链:把里面的技能挪进 ${SKILLS_DIR}/、删掉它,再跑 cotutor
|
|
190
|
+
return { item, action: 'kept', note: `${CLAUDE_SKILLS_LINK} 是实体目录,没建链:把里面的技能挪进 ${SKILLS_DIR}/、删掉它,再跑 cotutor refresh` };
|
|
191
191
|
await mkdir(dirname(link), { recursive: true });
|
|
192
192
|
try {
|
|
193
193
|
await symlink(target, link, process.platform === 'win32' ? 'junction' : undefined);
|
package/dist/app/cli/themes.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* 主题(themes/<name>/theme.json + kid.css):孩子端板书的样子。样子的真相在主题里,不在卡的协议里。
|
|
3
3
|
* 出厂主题 default 在包根 themes/default/;init **拷贝**进 workspace 的 themes/default/(拷进来就是家长的,改了刷新就有),
|
|
4
|
-
* 目录 hash 记 .cotutor/shipped.json 的 themes,与老师文件 / skill 同一套:没改过的随 cotutor
|
|
4
|
+
* 目录 hash 记 .cotutor/shipped.json 的 themes,与老师文件 / skill 同一套:没改过的随 cotutor refresh 换新,改过的报 diff 保留。
|
|
5
5
|
* 自家的主题(cotutor add-theme <name> 拷一份 default 来改,或直接建目录)永远 untracked,upgrade 不碰。
|
|
6
6
|
*/
|
|
7
7
|
import { cp, lstat, mkdir, readFile, readdir, rm, writeFile } from 'node:fs/promises';
|
|
@@ -103,7 +103,7 @@ export async function installThemes(root) {
|
|
|
103
103
|
steps.push({ item, action: 'created', note: '孩子端的主题(theme.json 槽的清单 + kid.css 样式),拷自本包,改了刷新就有' });
|
|
104
104
|
}
|
|
105
105
|
else
|
|
106
|
-
steps.push({ item, action: 'exists', note: s.state === 'custom' ? `自定义(基于 ${s.basedOn})` : s.state === 'upgradable' ? '可升级(cotutor
|
|
106
|
+
steps.push({ item, action: 'exists', note: s.state === 'custom' ? `自定义(基于 ${s.basedOn})` : s.state === 'upgradable' ? '可升级(cotutor refresh)' : s.state === 'untracked' ? '已有(没有出厂记录);升级时当自定义对待' : undefined });
|
|
107
107
|
}
|
|
108
108
|
if (touched)
|
|
109
109
|
await writeManifest(root, { ...manifest, version: PACKAGE_VERSION });
|
package/dist/app/cli/tray.d.ts
CHANGED
|
@@ -37,6 +37,8 @@ export interface TrayProbe {
|
|
|
37
37
|
name: string;
|
|
38
38
|
kid: string;
|
|
39
39
|
root: string;
|
|
40
|
+
/** vault 在哪(cotutor.json 的 paths.vault;没写就是 root):Windows 上读不到 vault 时打开它 */
|
|
41
|
+
vault: string;
|
|
40
42
|
logDir: string | null;
|
|
41
43
|
port: number;
|
|
42
44
|
health: Health | null;
|
|
@@ -142,6 +144,7 @@ export interface TrayDeps {
|
|
|
142
144
|
inspect(s: InstalledService): Promise<{
|
|
143
145
|
kid: string;
|
|
144
146
|
port: number;
|
|
147
|
+
vault: string;
|
|
145
148
|
}>;
|
|
146
149
|
probe(port: number): Promise<Health | null>;
|
|
147
150
|
holder(port: number): Promise<string | null>;
|
|
@@ -188,10 +191,12 @@ export declare function openCommand(platform: NodeJS.Platform, target: string):
|
|
|
188
191
|
export declare function openTarget(platform: NodeJS.Platform, target: string): void;
|
|
189
192
|
/** 日志:一个文件,过 1 MB 换一次,只留上一份 */
|
|
190
193
|
export declare function trayNote(dir: string): (text: string) => void;
|
|
191
|
-
/**
|
|
194
|
+
/** 孩子叫什么、哪个端口、vault 在哪:只读这三样,不加载 zod(托盘进程常驻,要轻);读不了就用服务名、缺省端口、workspace 根。
|
|
195
|
+
* vault 照 workspace.ts 的 resolvePaths 算:paths.vault 相对 workspace 根,没写就是根(旧版的布局) */
|
|
192
196
|
export declare function inspectService(s: InstalledService): Promise<{
|
|
193
197
|
kid: string;
|
|
194
198
|
port: number;
|
|
199
|
+
vault: string;
|
|
195
200
|
}>;
|
|
196
201
|
/** 真的依赖,给 runTray */
|
|
197
202
|
export declare function realTrayDeps(host: ServiceHost, dir: string, file: string, version: () => string): TrayDeps;
|
package/dist/app/cli/tray.js
CHANGED
|
@@ -16,6 +16,7 @@ import { join } from 'node:path';
|
|
|
16
16
|
import { createInterface } from 'node:readline';
|
|
17
17
|
import { DEFAULT_PORT } from "../../shared/default-port.js";
|
|
18
18
|
import { UsageError } from "../../shared/errors.js";
|
|
19
|
+
import { expandPath } from "../../shared/home.js";
|
|
19
20
|
import { siteUrl } from "../../shared/site-url.js";
|
|
20
21
|
import { isNewer } from "../../shared/upgrade.js";
|
|
21
22
|
import { portHolder } from "./port-holder.js";
|
|
@@ -60,7 +61,7 @@ export function issuesOf(p, o) {
|
|
|
60
61
|
if (h.configError)
|
|
61
62
|
out.push({ text: 'cotutor.json 写坏了:改的没生效', fix: { kind: 'open', target: p.root } });
|
|
62
63
|
if (h.vault === 'denied')
|
|
63
|
-
out.push(o.platform === 'darwin' ? { text: '读不到 vault:要给 node 开磁盘权限', fix: { kind: 'open', target: MAC_FULL_DISK } } : { text: '读不到 vault:看看这个目录的权限', fix: { kind: 'open', target: p.
|
|
64
|
+
out.push(o.platform === 'darwin' ? { text: '读不到 vault:要给 node 开磁盘权限', fix: { kind: 'open', target: MAC_FULL_DISK } } : { text: '读不到 vault:看看这个目录的权限', fix: { kind: 'open', target: p.vault } });
|
|
64
65
|
else if (h.vault === 'missing')
|
|
65
66
|
out.push({ text: 'vault 不在了:看看 cotutor.json 的 paths.vault', fix: { kind: 'open', target: p.root } });
|
|
66
67
|
if (h.bailian === false)
|
|
@@ -371,7 +372,7 @@ export function runTray(d) {
|
|
|
371
372
|
}
|
|
372
373
|
else
|
|
373
374
|
holders.delete(s.name);
|
|
374
|
-
probes.push({ name: s.name, kid: w.kid, root: s.root, logDir: s.logDir, port: w.port, health, holder });
|
|
375
|
+
probes.push({ name: s.name, kid: w.kid, root: s.root, vault: w.vault, logDir: s.logDir, port: w.port, health, holder });
|
|
375
376
|
}
|
|
376
377
|
const r = model.update(probes, d.now());
|
|
377
378
|
rows = r.rows;
|
|
@@ -501,15 +502,17 @@ export function trayNote(dir) {
|
|
|
501
502
|
catch { /* 写不了日志不能把图标带倒 */ }
|
|
502
503
|
};
|
|
503
504
|
}
|
|
504
|
-
/**
|
|
505
|
+
/** 孩子叫什么、哪个端口、vault 在哪:只读这三样,不加载 zod(托盘进程常驻,要轻);读不了就用服务名、缺省端口、workspace 根。
|
|
506
|
+
* vault 照 workspace.ts 的 resolvePaths 算:paths.vault 相对 workspace 根,没写就是根(旧版的布局) */
|
|
505
507
|
export async function inspectService(s) {
|
|
506
508
|
try {
|
|
507
509
|
const c = JSON.parse(await readFile(join(s.root, 'cotutor.json'), 'utf8'));
|
|
508
510
|
const kid = typeof c.kid?.name === 'string' && c.kid.name ? c.kid.name : typeof c.kid?.slug === 'string' && c.kid.slug ? c.kid.slug : s.name;
|
|
509
|
-
|
|
511
|
+
const vault = typeof c.paths?.vault === 'string' && c.paths.vault ? expandPath(c.paths.vault, s.root) : s.root;
|
|
512
|
+
return { kid, port: typeof c.server?.port === 'number' ? c.server.port : DEFAULT_PORT, vault };
|
|
510
513
|
}
|
|
511
514
|
catch {
|
|
512
|
-
return { kid: s.name, port: DEFAULT_PORT };
|
|
515
|
+
return { kid: s.name, port: DEFAULT_PORT, vault: s.root };
|
|
513
516
|
}
|
|
514
517
|
}
|
|
515
518
|
/** 真的依赖,给 runTray */
|
package/dist/app/cli/tutors.d.ts
CHANGED
|
@@ -43,7 +43,7 @@ export interface UpgradeStep {
|
|
|
43
43
|
/** 最小行 diff(LCS),只为让家长看清改了哪几行;不追求 git 那么好 */
|
|
44
44
|
export declare function lineDiff(a: string, b: string): string[];
|
|
45
45
|
/**
|
|
46
|
-
* cotutor
|
|
46
|
+
* cotutor refresh:latest 跳过;upgradable 换新;custom / untracked 只报 diff 并保留(--force <name> 才覆盖,原文留 .bak);缺的补。
|
|
47
47
|
*/
|
|
48
48
|
export declare function upgradeTutors(root: string, opts?: {
|
|
49
49
|
force?: string[];
|
|
@@ -65,7 +65,7 @@ export declare function removeTutorFile(root: string, name: string): Promise<{
|
|
|
65
65
|
/** 出厂那份老师文件的原文;不是出厂的 → null */
|
|
66
66
|
export declare function shippedTutorText(name: string, root?: string): Promise<string | null>;
|
|
67
67
|
/**
|
|
68
|
-
* 只把一位出厂老师的文件换回出厂那份(工作台「恢复出厂」,与
|
|
68
|
+
* 只把一位出厂老师的文件换回出厂那份(工作台「恢复出厂」,与 cotutor reset <老师> 同一条路,但不碰别的老师):
|
|
69
69
|
* 现在那份和出厂不一样就先存 .bak。不是出厂的 → UsageError。返回 .bak 的路径(没存就是 null)
|
|
70
70
|
*/
|
|
71
71
|
export declare function restoreTutor(root: string, name: string): Promise<{
|
package/dist/app/cli/tutors.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* 和老师的家 agents/<name>/ 并排,同包里一样(2026-10-30 从 .claude/agents/ 挪来,老 workspace 由 migrate.ts 的 migrateLayout 搬)。
|
|
5
5
|
* 出厂时的内容 hash 记在 .cotutor/shipped.json(机器文件,家长不用管),据此分三种状态:
|
|
6
6
|
* latest 与本包一致
|
|
7
|
-
* upgradable 与记录的出厂 hash 一致(没改过,只是包更新了)→ cotutor
|
|
7
|
+
* upgradable 与记录的出厂 hash 一致(没改过,只是包更新了)→ cotutor refresh 直接换新
|
|
8
8
|
* custom 改过 → upgrade 只报 diff,不动
|
|
9
9
|
* untracked 没有记录(旧workspace、或家长手写的老师)→ 当 custom 对待
|
|
10
10
|
*/
|
|
@@ -82,7 +82,7 @@ export async function installTutors(root, configured = []) {
|
|
|
82
82
|
steps.push({ item, action: 'kept', note: '已有(不是出厂件,或没有记录);升级时当自定义对待' });
|
|
83
83
|
}
|
|
84
84
|
else {
|
|
85
|
-
steps.push({ item, action: 'exists', note: s.state === 'custom' ? `自定义(基于 ${s.basedOn})` : s.state === 'upgradable' ? `可升级(cotutor
|
|
85
|
+
steps.push({ item, action: 'exists', note: s.state === 'custom' ? `自定义(基于 ${s.basedOn})` : s.state === 'upgradable' ? `可升级(cotutor refresh)` : undefined });
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
88
|
for (const name of configured.filter((n) => !shipped.some((a) => a.name === n))) {
|
|
@@ -151,7 +151,7 @@ export function lineDiff(a, b) {
|
|
|
151
151
|
return out;
|
|
152
152
|
}
|
|
153
153
|
/**
|
|
154
|
-
* cotutor
|
|
154
|
+
* cotutor refresh:latest 跳过;upgradable 换新;custom / untracked 只报 diff 并保留(--force <name> 才覆盖,原文留 .bak);缺的补。
|
|
155
155
|
*/
|
|
156
156
|
export async function upgradeTutors(root, opts = {}) {
|
|
157
157
|
const manifest = await readManifest(root);
|
|
@@ -229,7 +229,7 @@ export async function shippedTutorText(name, root) {
|
|
|
229
229
|
return a ? readFile(a.file, 'utf8') : null;
|
|
230
230
|
}
|
|
231
231
|
/**
|
|
232
|
-
* 只把一位出厂老师的文件换回出厂那份(工作台「恢复出厂」,与
|
|
232
|
+
* 只把一位出厂老师的文件换回出厂那份(工作台「恢复出厂」,与 cotutor reset <老师> 同一条路,但不碰别的老师):
|
|
233
233
|
* 现在那份和出厂不一样就先存 .bak。不是出厂的 → UsageError。返回 .bak 的路径(没存就是 null)
|
|
234
234
|
*/
|
|
235
235
|
export async function restoreTutor(root, name) {
|
|
@@ -21,7 +21,7 @@ const nodeTooOld = (have, min) => {
|
|
|
21
21
|
const worthSaying = (out) => out.split('\n').map((l) => l.trimEnd()).filter((l) => l.trim() && !/已是最新|已换新/.test(l));
|
|
22
22
|
async function updateOne(d, s, target) {
|
|
23
23
|
let ok = true;
|
|
24
|
-
const up = await d.cli(['
|
|
24
|
+
const up = await d.cli(['refresh', '--workspace', s.root]);
|
|
25
25
|
for (const l of worthSaying(up.out))
|
|
26
26
|
d.print(` ${l}`);
|
|
27
27
|
if (up.code !== 0) {
|
|
@@ -53,14 +53,14 @@ async function updateOne(d, s, target) {
|
|
|
53
53
|
const checks = JSON.parse(doc.out).checks;
|
|
54
54
|
const migrate = checks.find((c) => c.name === 'config.migrate' && !c.ok);
|
|
55
55
|
if (migrate)
|
|
56
|
-
d.print(` ! ${s.kid} 的配置要迁移:${migrate.cmd ?? 'cotutor
|
|
56
|
+
d.print(` ! ${s.kid} 的配置要迁移:${migrate.cmd ?? 'cotutor refresh --config'}`);
|
|
57
57
|
}
|
|
58
58
|
catch { /* 体检读不了不影响升级 */ }
|
|
59
59
|
return ok;
|
|
60
60
|
}
|
|
61
61
|
export async function runUpdate(d, o = {}) {
|
|
62
62
|
if (d.fromRepo) {
|
|
63
|
-
d.print('这份是从仓库跑的:git pull,再 cotutor
|
|
63
|
+
d.print('这份是从仓库跑的:git pull,再 cotutor refresh、cotutor service restart。cotutor update 只管 npm 装的。');
|
|
64
64
|
return 1;
|
|
65
65
|
}
|
|
66
66
|
const services = await d.services();
|
|
@@ -114,7 +114,7 @@ export async function runUpdate(d, o = {}) {
|
|
|
114
114
|
if (!services.length) {
|
|
115
115
|
const root = d.workspace();
|
|
116
116
|
if (root) {
|
|
117
|
-
const up = await d.cli(['
|
|
117
|
+
const up = await d.cli(['refresh', '--workspace', root]);
|
|
118
118
|
for (const l of worthSaying(up.out))
|
|
119
119
|
d.print(` ${l}`);
|
|
120
120
|
if (up.code !== 0)
|
package/dist/app/cli/usage.d.ts
CHANGED
|
@@ -1,2 +1,26 @@
|
|
|
1
|
-
/**
|
|
2
|
-
export declare const USAGE = "\u7528\u6CD5:\n cotutor init <slug> [--dir <path>] [--name <\u5B69\u5B50\u540D>] [--grade <1-6>] [--port <n>] \u5EFA ~/cotutor/<slug>/ \u9AA8\u67B6(\u5E42\u7B49\u8865\u7F3A;\u9ED8\u8BA4\u4E8C\u5E74\u7EA7\u6559\u5B66\u5305;\u7AEF\u53E3\u5728\u8FD9\u91CC\u9009\u4E00\u6B21\u5199\u8FDB cotutor.json:443 \u4F18\u5148,\u4E0D\u884C\u5C31 8443\u30018445\u2026,\u4EE5\u540E\u4E0D\u53D8)\n cotutor grades [--json] \u5217\u51FA\u672C\u5305\u53EF\u5B89\u88C5\u7684\u5E74\u7EA7\u6559\u5B66\u5305\n cotutor doctor [--workspace <dir>] [--json] [--live] [--fix] \u9010\u9879\u4F53\u68C0;--live \u771F\u8FDE\u4E00\u6B21\u767E\u70BC\u5B9E\u65F6\u6A21\u578B\u3001\u771F\u5408\u6210\u4E00\u53E5\u914D\u97F3(\u82B1\u4E00\u5206\u94B1)\u628A API \u5C42\u7684\u5751\u6446\u51FA\u6765(\u771F\u8DD1\u8001\u5E08\u7528 cotutor send);--json \u91CC\u4E0D\u8FC7\u7684\u9879\u5E26 cmd(\u80FD\u76F4\u63A5\u8DD1)\u6216 human(\u8981\u4EBA\u6765);--fix \u628A\u5E26 cmd \u7684\u4E00\u6761\u6761\u4FEE\u6389,\u8981\u4EBA\u6765\u7684\u7559\u7740\n cotutor report [--workspace <dir>] \u8BCA\u65AD\u4FE1\u606F:\u7248\u672C\u3001\u7CFB\u7EDF\u3001\u670D\u52A1\u3001\u4F53\u68C0\u6CA1\u8FC7\u7684\u3001\u6700\u8FD1\u62A5\u9519\u7684\u539F\u56E0;\u4E0D\u542B\u5B69\u5B50\u7684\u5BF9\u8BDD\u3001\u7167\u7247\u3001\u5F55\u97F3\u3001\u6863\u6848\u548C key,\u540D\u5B57\u548C IP \u5DF2\u62B9\u6389,\u5148\u770B\u518D\u53D1\n cotutor backup [list | restore <\u540D\u5B57> [--yes]] [--workspace <dir>] \u5907\u4EFD\u5230 workspace \u65C1\u8FB9\u7684 .backups/:\u4E0D\u542B\u5F55\u97F3;\u670D\u52A1\u5F00\u7740\u65F6\u6BCF\u5929\u4E00\u4EFD(\u7559 14 \u4EFD),cotutor upgrade \u524D\u4E00\u4EFD(\u7559 5 \u4EFD);\u6CA1\u53D8\u7684\u6587\u4EF6\u786C\u94FE\u63A5,\u4E0D\u5360\u7B2C\u4E8C\u4EFD\u5730\u65B9;restore \u5148\u628A\u73B0\u5728\u7684\u4E5F\u5907\u4E00\u4EFD\u518D\u62F7\u56DE\u53BB,\u4E0D\u52A0 --yes \u53EA\u8BF4\u4F1A\u505A\u4EC0\u4E48\n cotutor update [--anyway] \u5347\u7EA7\u4E00\u6761\u547D\u4EE4\u7BA1\u5230\u5E95:\u95EE npm \u6709\u6CA1\u6709\u65B0\u7248\u672C,\u6362\u7A0B\u5E8F,\u6BCF\u4E2A\u5B69\u5B50\u66F4\u65B0\u51FA\u5382\u6587\u4EF6\u3001\u91CD\u8D77\u670D\u52A1\u548C\u56FE\u6807;\u5B69\u5B50\u5728\u901A\u8BDD\u65F6\u4E0D\u52A8(--anyway \u624D\u52A8),npm \u6CA1\u6210\u670D\u52A1\u4E0D\u52A8\n cotutor upgrade [--workspace <dir>] [--force <\u8001\u5E08>]... \u8001\u5E08\u6587\u4EF6\u3001activity \u4E0E skill \u6362\u65B0\u7248:\u6CA1\u6539\u8FC7\u7684\u76F4\u63A5\u6362,\u6539\u8FC7\u7684\u53EA\u62A5 diff(--force <\u8001\u5E08> \u6216 --force <\u8001\u5E08>/<\u540D> \u624D\u8986\u76D6,\u539F\u6587\u7559 .bak)\n cotutor upgrade --config [--dry-run] [--workspace <dir>] cotutor.json \u8865\u7F3A:\u65B0\u51FA\u5382\u8001\u5E08 / \u8FD0\u884C\u65F6 / \u547D\u4EE4\u6A21\u677F\u65D7\u6807(\u53EA\u52A0\u7F3A\u7684,\u4F60\u6539\u8FC7\u7684\u503C\u4E0D\u52A8)\n cotutor add <\u8001\u5E08\u540D> --display <\u663E\u793A\u540D> [--subject <\u5B66\u79D1>] [--avatar <emoji|\u56FE\u7247\u76F8\u5BF9\u8DEF\u5F84>] [--hidden] \u52A0\u4E00\u4F4D\u81EA\u5BB6\u7684\u8001\u5E08:\u51FA\u6A21\u677F\u6587\u4EF6\u3001\u8FDB cotutor.json\u3001\u5EFA\u76EE\u5F55(\u540D\u5B57\u4EE5 -tutor \u7ED3\u5C3E\u7684\u662F\u8001\u5E08,figshot \u7ED9\u5B83\u505A\u5934\u50CF)\n cotutor add-theme <\u4E3B\u9898\u540D> [--from <\u4E3B\u9898>] [--workspace <dir>] \u52A0\u4E00\u4E2A\u81EA\u5BB6\u7684\u4E3B\u9898:\u62F7\u4E00\u4EFD(\u7F3A\u7701\u51FA\u5382\u7684 default)\u5230 themes/<\u4E3B\u9898\u540D>/,\u6539 cotutor.json \u7684 kid.theme \u6362\u8FC7\u53BB\n cotutor serve [--workspace <dir>] [--port <n>] [--http] [--trace] [--open] [--log-dir <\u76EE\u5F55>] \u5728\u7EC8\u7AEF\u91CC\u8D77\u670D\u52A1(\u4E00 workspace \u4E00\u8FDB\u7A0B;~/.config/cotutor/certs/ \u6709\u8BC1\u4E66\u5C31\u8D70 HTTPS;--trace \u6BCF\u4E00\u8F6E\u7684\u4E8B\u4EF6\u6309\u9053\u6253\u5370;\u53EA\u6253\u5370\u5BB6\u957F\u7AEF\u9996\u9875\u7684\u5730\u5740,\u5B69\u5B50\u7684\u5E73\u677F\u5728\u90A3\u91CC\u626B\u7801;--open \u987A\u624B\u6253\u5F00,\u65E7\u540D --open-qr \u7167\u6837\u8BA4;--log-dir \u8F93\u51FA\u6309\u5929\u843D\u6587\u4EF6,\u540E\u53F0\u670D\u52A1\u7528;\u5173\u4E86\u7EC8\u7AEF\u5C31\u505C,\u4E00\u76F4\u5F00\u7740\u7528 cotutor service)\n cotutor open [--workspace <dir>] [--sandbox] [--print] [--json] \u6253\u5F00\u5BB6\u957F\u7AEF(\u8BFB cotutor.json,\u4E0D\u7528\u8BB0\u7AEF\u53E3);--sandbox \u5F00\u8BD5\u7528\u7684\u90A3\u4E2A(\u7AEF\u53E3\u6C38\u8FDC\u662F\u771F\u7684 +1);--print \u53EA\u6253\u5370\u5730\u5740;\u6CA1\u5728\u8DD1\u5C31\u8BF4\u600E\u4E48\u8D77,\u4EE5 1 \u9000\n cotutor service install | uninstall | start | stop | restart [--workspace <dir>] [--no-tray] [--no-open] \u628A serve \u88C5\u6210\u8FD9\u53F0\u7535\u8111\u7684\u540E\u53F0\u670D\u52A1(macOS launchd\u3001Linux systemd \u7528\u6237\u670D\u52A1\u3001Windows \u7528\u6237\u7684\u767B\u5F55\u9879,\u90FD\u4E0D\u8981\u7BA1\u7406\u5458):\u767B\u5F55\u540E\u81EA\u5DF1\u8D77\u6765\u3001\u5D29\u4E86 10 \u79D2\u540E\u518D\u8D77\u3001\u65E5\u5FD7\u6309\u5929\u843D\u6587\u4EF6\u7559 14 \u5929;\u4E00\u4E2A workspace \u4E00\u4E2A;\u7B2C\u4E00\u6B21 install \u6253\u5F00\u4E00\u6B21\u5BB6\u957F\u7AEF(--no-open \u4E0D\u5F00),\u4EE5\u540E\u7684\u542F\u52A8\u90FD\u4E0D\u5F00;\u6362\u4E86 node \u7248\u672C\u6216\u5305\u632A\u4E86\u5730\u65B9\u518D install \u4E00\u6B21\n cotutor tray on | off | status [--json] \u83DC\u5355\u680F / \u4EFB\u52A1\u680F\u56FE\u6807(macOS\u3001Windows;service install \u65F6\u4E00\u8D77\u88C5,--no-tray \u4E0D\u5E26):\u6B63\u5E38\u65F6\u53EA\u6709 logo,\u6709\u4E8B\u51FA\u6A59\u70B9,\u6CA1\u5728\u8DD1\u65F6\u53D8\u6DE1\u52A0\u7EA2\u70B9\u5E76\u901A\u77E5\u4E00\u6B21;\u70B9\u5B83\u770B\u72B6\u6001\u3001\u6253\u5F00\u5BB6\u957F\u7AEF\u3001\u91CD\u542F\u3001\u770B\u65E5\u5FD7\u3001\u9000\u51FA;off \u5173\u6389\u5E76\u8BB0\u4F4F\n cotutor service status [--json] | logs [--lines <n>] [--follow] \u540E\u53F0\u670D\u52A1\u5728\u4E0D\u5728\u8DD1\u3001\u7AEF\u53E3\u7B54\u4E0D\u7B54\u5E94\u3001\u8DD1\u7684\u54EA\u4E2A\u7248\u672C\u3001vault \u8BFB\u4E0D\u8BFB\u5F97\u5230\u3001\u65E5\u5FD7\u5728\u54EA;--json \u8FD8\u7B54\u5E73\u677F\u5730\u5740\u3001\u8BC1\u4E66\u3001\u767E\u70BC\u914D\u6CA1\u914D\u3001\u56FE\u6807;logs \u770B\u6700\u8FD1\u7684\u65E5\u5FD7\n cotutor pin [off | status] [--pin <\u6570\u5B57>] [--json] \u5BB6\u957F\u7AEF /parent \u4E0E\u5DE5\u4F5C\u53F0 /dev \u7684\u9501:\u673A\u5668\u7EA7 PIN(\u6240\u6709 workspace \u5171\u7528),iPad \u4E0A\u8F93\u4E00\u6B21\u3001\u8FD9\u53F0\u7535\u8111\u514D\u5BC6;\u6CA1\u8BBE\u5C31\u5168\u5F00(\u5BB6\u957F\u5728\u65C1\u8FB9\u53EF\u4EE5\u4E0D\u8BBE);off \u64A4\u6389\n cotutor cert [--host <\u540D\u6216IP>]... \u7528 mkcert \u5EFA\u8FD9\u53F0\u673A\u5668\u7684\u81EA\u7B7E\u8BC1\u4E66\u5230 ~/.config/cotutor/certs/(\u5E73\u677F\u3001\u624B\u673A\u4E0A\u5F55\u97F3\u8981 HTTPS;\u6240\u6709 workspace \u5171\u7528)\n cotutor send <\u8001\u5E08> [<\u6D88\u606F>] [--from kid|system] [--runtime <\u540D>] [--new] [--photo a.jpg,b.png] [--activity <\u540D> [--param '\u540D=\u503C;\u540D=\u503C']] [--lane main,tts] [--quiet] \u7EC8\u7AEF\u91CC\u53D1\u4E00\u6761,\u73B0\u573A\u6309\u9053\u6253\u5370\u6BCF\u9053\u5DE5\u5E8F\u7684\u4E8B\u4EF6,\u8BF4\u5B8C\u6253\u5370\u7ED3\u679C(\u5B69\u5B50\u7684\u8BDD\u7167\u5B9E\u65F6\u5199,\u540C\u5B69\u5B50\u7AEF:\u4E0A\u4E0B\u6587\u5305\u5E26 live:\u3001\u4E0D\u8865\u63D0\u95EE\u5361,\u53EA\u662F\u6CA1\u6709\u5634;--from system \u4E0D\u7B97;--new \u5F00\u65B0\u8BDD\u9898;--photo \u5E26\u4F5C\u4E1A\u7167\u7247,\u62F7\u8FDB captures/,\u6709\u7167\u7247\u65F6\u6D88\u606F\u53EF\u4EE5\u7A7A;--activity \u50CF\u5B69\u5B50\u70B9\u4E86\u9996\u9875\u7684 activity \u6309\u94AE,\u65B0\u5F00\u8BDD\u9898,\u53C2\u6570\u540C\u6309\u94AE\u4E0B\u9762\u90A3\u51E0\u884C;--quiet \u53EA\u8981\u7ED3\u679C)\n cotutor pack <\u8001\u5E08> [<\u6D88\u606F>] [--from kid|system] [--at <ISO\u65F6\u95F4>] [--activity <\u540D> [--param '\u540D=\u503C;\u540D=\u503C']] [--json] \u5E72\u8DD1\u4E0A\u4E0B\u6587\u5305(--activity \u770B activity \u8BDD\u9898\u7B2C\u4E00\u6761\u8001\u5E08\u62FF\u5230\u4EC0\u4E48):\u4E0D\u8D77\u6A21\u578B,\u6253\u5370\u73B0\u5728\u4F1A\u53D1\u7ED9\u8001\u5E08\u7684\u90A3\u4EFD + \u6BCF\u6BB5\u6765\u81EA\u54EA\u4E2A\u6587\u4EF6\u3001\u90A3\u91CC\u4E00\u5171\u51E0\u6761\u3001\u6309\u653F\u7B56\u5E26\u4E86\u51E0\u6761(\u6539\u4E86\u6863\u6848 / \u65E5\u8BB0 / \u8BA1\u5212\u7ACB\u523B\u770B\u6548\u679C)\n cotutor replay <\u8001\u5E08> <job> [<\u65E5\u671F>] [--runtime <\u540D>] [--json] \u56DE\u653E\u4E00\u8F6E:\u540C\u4E00\u95EE\u6309\u73B0\u5728\u7684 vault \u4E0E\u63D0\u793A\u8BCD\u518D\u8DD1\u4E00\u904D(\u843D evals/,\u4E0D\u8FDB\u5B69\u5B50\u7684\u5BF9\u8BDD\u3001\u4E0D\u914D\u97F3),\u8DD1\u5B8C\u5E76\u6392\u6253\u5370\u4E0A\u4E0B\u6587\u5305 / \u8BB2\u7A3F / \u5361 / \u8BFB\u4E86\u4EC0\u4E48\u7684 diff\n cotutor compare <\u8001\u5E08> [<evalJob>] [<\u65E5\u671F>] [--json] \u518D\u770B\u4E00\u6B21\u56DE\u653E\u7684\u5BF9\u7167(\u4E0D\u7ED9 evalJob \u5C31\u5217\u8FD9\u5929\u56DE\u653E\u8FC7\u54EA\u4E9B)\n cotutor show <\u8001\u5E08> <job> [<\u65E5\u671F>] [--json] [--evals] [--workspace <dir>] \u770B\u4E00\u8F6E:\u95EE\u4E86\u4EC0\u4E48\u3001\u4E0A\u4E0B\u6587\u5305\u3001\u5F53\u65F6\u7684\u8001\u5E08\u6587\u4EF6\u4E0E\u6280\u80FD hash\u3001\u8BB2\u7A3F\u4E0E\u5361\u3001\u8BFB\u4E86\u4EC0\u4E48\u3001token \u4E0E\u7528\u65F6\u3001\u7ED9\u5BB6\u957F\u7684\u5C3E\u5DF4;--json \u662F\u5BB6\u957F\u7AEF\u300C\u770B\u539F\u6587\u300D\u540C\u4E00\u4EFD\u6570\u636E,\u7ED9\u7F16\u7A0B\u52A9\u624B\u5206\u6790\u7528\n cotutor trace <\u8001\u5E08> <job> [<\u65E5\u671F>] [--lane \u2026] [--workspace <dir>] \u56DE\u653E\u4E00\u8F6E\u7684\u4E8B\u4EF6(<\u65E5\u671F>.<job>.events.jsonl;\u6392\u67E5\u6628\u5929\u90A3\u8F6E\u7528)\n cotutor rate <\u8001\u5E08> <\u8BDD\u9898> <1-5> [--date <\u65E5\u671F>] \u7ED9\u4E00\u4E2A\u8BDD\u9898\u6253\u661F(\u4E0E\u5BB6\u957F\u7AEF\u540C\u4E00\u6761\u8DEF;\u2265 vault.keepScore \u7684\u8BDD\u9898\u8BB0\u8D26\u65F6\u6458\u8981\u624D\u8FDB\u65E5\u8BB0)\n cotutor bookkeep <\u8001\u5E08> [--date <\u65E5\u671F>] [--thread <\u8BDD\u9898>]... \u8BB0\u8D26:\u8FD9\u5929\u6BCF\u4E2A\u8FD8\u6CA1\u8BB0\u8FC7\u7684\u8BDD\u9898\u5404\u8D77\u4E00\u8F6E\u8BB0\u8D26\u4EFB\u52A1,\u8001\u5E08\u56DE\u300C## \u8BB0\u8D26\u300D,\u5E94\u7528\u5199\u8FDB vault \u7684\u65E5\u8BB0(\u8BDD\u9898\u540D\u3001\u5B69\u5B50\u95EE\u3001\u6458\u8981\u3001\u89C2\u5BDF)\n cotutor home check [--published] [--json] \u68C0\u67E5\u9996\u9875\u8349\u7A3F home/draft.md(\u6216\u5DF2\u53D1\u5E03\u7684\u90A3\u4EFD):\u5B69\u5B50\u4F1A\u770B\u5230\u54EA\u51E0\u5F20\u5361\u3001\u6BCF\u4F4D\u8001\u5E08\u7684\u6309\u94AE\u3001\u8981\u6539\u7684\u4E0E\u63D0\u9192(\u5E26\u884C\u53F7);\u4E0D\u82B1\u94B1\n cotutor home publish [--force] [--from <\u6587\u4EF6>] [--json] \u53D1\u5E03\u9996\u9875:\u68C0\u67E5 \u2192 \u7559\u5386\u53F2 home/history/<id>.md \u2192 \u5199 home/published.json(\u5B69\u5B50\u7AEF\u53EA\u8BFB\u5B83);\u6709\u8981\u6539\u7684\u4E0D\u53D1,--force \u4E22\u6389\u90A3\u51E0\u5F20\u7167\u53D1;--from \u53D1\u53E6\u4E00\u4EFD(\u5982\u5386\u53F2)\n cotutor home show [--json] \u73B0\u5728\u53D1\u5E03\u7684\u662F\u54EA\u4EFD\u3001\u51E0\u5929\u524D\u3001\u6BCF\u4E2A\u6309\u94AE\u88AB\u70B9\u4E86\u51E0\u6B21(\u54EA\u5929\u3001\u54EA\u4E2A\u8BDD\u9898)\n cotutor activity check [<\u8001\u5E08> [<\u540D>]] [--json] \u68C0\u67E5 activity \u6587\u4EF6(agents/<\u8001\u5E08>/activities/<\u540D>.md):\u5BB6\u957F\u586B\u7684\u3001\u5E94\u7528\u7B97\u7684\u3001\u5E94\u7528\u62E6\u7684\u3001\u88C1\u6BB5\u3001\u63D2\u69FD\u3001\u6B63\u6587\u7528\u7684\u5361\u3001\u7B2C\u4E00\u53E5\u4E0E\u6536(\u5E26\u884C\u53F7);\u4E0D\u82B1\u94B1\n cotutor activity eval <\u8001\u5E08> <\u540D> [--runs <n>] [--only <\u4F8B\u5B50>] [--kid-model <\u5343\u95EE\u6A21\u578B>] [--json] \u7167 <\u540D>.\u4F8B\u5B50.md \u8DD1:\u771F\u8001\u5E08 + \u6A21\u62DF\u5B69\u5B50(\u5343\u95EE,\u7F3A\u7701 qwen3.8-flash,\u6709 Token Plan \u8D70\u5B83)\u591A\u8F6E(\u7167\u5B9E\u65F6\u5199,\u540C\u5B69\u5B50\u7AEF),\u5224\u53EA\u770B\u677F\u4E66;\u4E00\u4E2A\u4F8B\u5B50\u8DD1 n \u6B21(\u7F3A\u7701 3)\u6B21\u6B21\u90FD\u8FC7\u624D\u7B97\u8FC7;\u843D evals/,\u753B\u5BB6\u662F\u5047\u7684;\u82B1\u94B1\n cotutor chalk <check|build|bake|snap|dub> <scene.ts|\u8BFE\u5305 id> [...] \u505A\u5C0F\u8BFE\u5802\u7684\u8BFE\u5305:check \u6821\u9A8C\u573A\u666F\u3001build \u51FA\u8BFE\u5305\u5230 bundles/\u3001bake \u70E4\u753B\u9762\u3001snap \u6BCF\u6B65\u622A\u56FE\u3001dub \u914D\u97F3(cotutor chalk \u770B\u5404\u81EA\u7684\u9009\u9879;bake / snap \u8981\u672C\u673A\u7684 Chrome)\n cotutor mock [--port <n>] [--scenario normal|nokey] [--delay <ms>] [--http] \u4E0D\u7ECF\u771F\u5B9E\u8001\u5E08\u4E0E\u767E\u70BC,\u7528\u56FA\u5B9A\u7684\u677F\u4E66 JSON \u8D77\u5B69\u5B50\u7AEF,\u6D4B\u524D\u7AEF\u4EA4\u4E92\u4E0E\u6E32\u67D3(\u4E0D\u9700\u8981 workspace;\u8001\u5E08\u90FD\u8D70\u5B9E\u65F6\u8001\u5E08\u9875,\u5047\u5634\u7167\u811A\u672C\u5FF5\u9759\u97F3\u7684\u58F0\u97F3;nokey = \u6CA1\u914D\u767E\u70BC,\u5B69\u5B50\u7AEF\u53EA\u51FA\u300C\u8001\u5E08\u4EEC\u8FD8\u6CA1\u5230\u300D)\n cotutor --version | --help\nworkspace\u89E3\u6790:--workspace > COTUTOR_WORKSPACE > cwd \u6216\u7956\u5148\u6709 cotutor.json > ~/.config/cotutor/config.json > ~/cotutor/ \u4E0B\u552F\u4E00\u7684\u5B69\u5B50\u76EE\u5F55\n\u8BD5\u7528:\u8981 workspace \u7684\u547D\u4EE4\u52A0 --sandbox,\u6362\u5230\u771F workspace \u65C1\u8FB9\u7684 .sandbox/<\u76EE\u5F55\u540D>/,\u8BD5\u7684\u5BF9\u8BDD\u4E0E vault \u7684\u5199\u5165\u4E0D\u8FDB\u5B69\u5B50\u7684\u8BB0\u5F55(\u7B2C\u4E00\u6B21\u81EA\u52A8\u5206:\u8BBE\u7F6E\u7167\u62F7,\u5BF9\u8BDD\u4E0E\u7167\u7247\u4E0D\u5E26,vault \u62F7\u4E00\u4EFD;\u6807\u9898\u524D\u52A0\u300C\u8BD5\u7528\u300D\u3001\u7AEF\u53E3 +1\u3001\u81EA\u52A8\u8BB0\u8D26\u5173\u6389);--sandbox --fresh \u91CD\u65B0\u5206\n";
|
|
1
|
+
/**
|
|
2
|
+
* 帮助与参数检查,都从命令表(commands.ts)来:顶层帮助只列命令和一句话,参数、例子在 cotutor <命令> --help。
|
|
3
|
+
* 纯函数、不碰 I/O:技能生成(app/skills/*-doc.ts)和测试都 import 它,不能把 CLI 带进去。
|
|
4
|
+
*/
|
|
5
|
+
import { type CommandSpec } from './commands.ts';
|
|
6
|
+
/** 顶层帮助;all 时连开发与调试的命令也列 */
|
|
7
|
+
export declare function topHelp(opts?: {
|
|
8
|
+
all?: boolean;
|
|
9
|
+
}): string;
|
|
10
|
+
/** cotutor <命令> --help;place: false 不列 --workspace / --sandbox(技能参考里统一说一次) */
|
|
11
|
+
export declare function commandHelp(name: string, opts?: {
|
|
12
|
+
place?: boolean;
|
|
13
|
+
}): string;
|
|
14
|
+
/** 技能里的命令参考:这几条命令各自的帮助;--workspace、--sandbox 在开头说一次 */
|
|
15
|
+
export declare function commandsReference(names: readonly string[]): string;
|
|
16
|
+
/** 不认识的命令:一句话,带最像的那个 */
|
|
17
|
+
export declare function unknownCommand(cmd: string): string;
|
|
18
|
+
/**
|
|
19
|
+
* 照命令表检查参数:不认识的旗标、用错子命令的旗标、不认识的子命令、多余的参数。
|
|
20
|
+
* 通过返回 null,不通过返回一句话(调用方补「看 cotutor <命令> --help」)。命令本身认不认识由调用方先判。
|
|
21
|
+
*/
|
|
22
|
+
export declare function checkArgs(c: CommandSpec, positionals: readonly string[], flags: Readonly<Record<string, string | true>>): string | null;
|
|
23
|
+
/** 一行 cotutor 命令(文档、测试里写的)照命令表对不对得上;对得上返回 null */
|
|
24
|
+
export declare function checkCommandLine(line: string): string | null;
|
|
25
|
+
/** 旧名:顶层帮助 */
|
|
26
|
+
export declare const USAGE: string;
|