e3cli 1.0.2__tar.gz → 1.0.4__tar.gz
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.
- {e3cli-1.0.2 → e3cli-1.0.4}/.github/workflows/release.yml +36 -22
- {e3cli-1.0.2 → e3cli-1.0.4}/CLAUDE.md +9 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/PKG-INFO +40 -7
- {e3cli-1.0.2 → e3cli-1.0.4}/README.md +39 -6
- {e3cli-1.0.2 → e3cli-1.0.4}/README_zh-TW.md +39 -6
- {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/__init__.py +1 -1
- {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/agent_prompt.md +6 -2
- {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/cli.py +4 -3
- {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/commands/setup.py +59 -5
- {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/commands/skill.py +19 -1
- {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/skills/e3cli/SKILL.md +5 -3
- {e3cli-1.0.2 → e3cli-1.0.4}/pyproject.toml +1 -1
- {e3cli-1.0.2 → e3cli-1.0.4}/.github/workflows/ci.yml +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/.gitignore +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/COMMIT_EDITMSG +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/Formula/e3cli.rb +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/HEAD +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/LICENSE +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/Makefile +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/config +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/description +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/__main__.py +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/ai/__init__.py +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/api/__init__.py +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/api/assignments.py +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/api/client.py +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/api/courses.py +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/api/files.py +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/api/forums.py +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/api/members.py +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/api/messages.py +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/api/site.py +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/auth.py +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/commands/__init__.py +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/commands/_common.py +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/commands/announcements.py +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/commands/assignments.py +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/commands/courses.py +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/commands/download.py +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/commands/interactive.py +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/commands/login.py +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/commands/logout.py +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/commands/members.py +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/commands/message.py +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/commands/profile.py +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/commands/schedule.py +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/commands/submit.py +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/commands/sync.py +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/config.py +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/course_name.py +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/credential.py +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/formatting.py +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/http.py +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/i18n.py +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/scheduler/__init__.py +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/scheduler/cron.py +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/semester.py +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/storage/__init__.py +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/storage/db.py +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/storage/models.py +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/storage/tracking.py +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/tui_menu.py +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/gk/config +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/hooks/applypatch-msg.sample +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/hooks/commit-msg.sample +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/hooks/fsmonitor-watchman.sample +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/hooks/post-update.sample +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/hooks/pre-applypatch.sample +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/hooks/pre-commit.sample +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/hooks/pre-merge-commit.sample +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/hooks/pre-push.sample +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/hooks/pre-rebase.sample +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/hooks/pre-receive.sample +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/hooks/prepare-commit-msg.sample +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/hooks/push-to-checkout.sample +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/hooks/sendemail-validate.sample +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/hooks/update.sample +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/index +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/info/exclude +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/logs/HEAD +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/logs/refs/heads/main +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/logs/refs/remotes/origin/main +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/00/12f54a62a13459820d72b63eee8781d5cc0fae +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/00/373e054c653e54b45cacae42d71dff863626bf +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/04/9ee8e5968a9a80f0f1ac53d12141c61e7298ba +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/04/e0353337b6bb0c0ba43625456e9aaf13090a90 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/05/0fec5da6aa35de1058b11671dfd6255b4d6b50 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/06/5c820fc3efcd99754c56197a9c4e7142da710d +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/07/01890044580c4644114b781d474012b2fade80 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/07/fb70ff1c509aad1f137a9255b9cb98733472a3 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/0e/89da06e2d2273057dfa03705c42bbc57af1a6a +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/13/ad53a74b643378a7aebfe32d672b256ab73bef +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/13/fb66226ef7de52c039b1030460c5bb9ad1d576 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/14/f44dcbbf53914d2d2b5b5a43453932fb0c6dd6 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/15/6da5879f795abd72f645bbcadf18a4928a7502 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/19/f9906c2882926f53e77b4be8be579906954a69 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/1a/3f91d11c7c9c764fcd1ed01a4a0c3f13b68fee +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/1c/1765c4b372bd085c6224472de72f66e8d9fbe9 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/22/e1020c805f3235c5c85d711a45d70d42883de0 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/24/7f60ac43c8a065926f3228575a34d0ecd6f93d +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/25/4d6ec800e32759015479a68a3afd096ee12680 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/27/1aee134d84254ba525ce728b3ecbbcbd73fe97 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/27/41f5e19bf92e37c983e7d4d307ec09726b95ed +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/28/265727a791db9daef09c85ab159ef799908dc4 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/2d/4c64fc2752b1356569f24e6f3d53cfd8ff3236 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/31/61734dcf7d8b86372753c2552746641969ca7a +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/33/3da47d4f7d08fc2836374614b902a27f1a7638 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/35/25cb5144ca2d643d918824df0f08042f8f1f19 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/35/faf439f5e7e6730398397e0988c874ec74c15e +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/37/2acc5a62b5a8a7cd97d3eb07614d2a71d65c34 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/37/f0c29518b9df6cde4d0cd7857d95b425fcaec9 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/38/8bc96a53da22ddf8d3684c10480a9ed89274a6 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/38/d062de47938882cc8c951cfcd18266bfa834d0 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/39/bbbcd0ade10f3066a853cca53ad5159ac78e30 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/3c/dd09e594d5716969279d6e3fcf99fca00f8504 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/3e/71c91d71be5667a313ecfae444718750b2bf55 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/3e/7febbe12d705885c2503c3e0d785e488f60966 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/3f/0235e32813f74985f0363e64a110093d979e2f +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/40/9ded4237099e6e52de508dd46ebe74cf769e79 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/41/88bc8a7a0569fd47efb215aad2e3f4a7b7e188 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/42/53425dbc4368909b4b782fd53360537d3d9033 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/42/925cbdfef5b97f5ae199323a5545810207af09 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/42/b238ab6f9c3c74cd23a14c094ad8eb1c66d52b +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/43/49874ad2cdacc9d50d6ba06df25765d077248a +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/43/cead7a00c7ef98e1d5c9c86e50a3ccde712277 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/43/e88c1a0a115fc72390e7bcef8ce0a8328a4e05 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/45/9c23839b54e81c741fd2b5241c2b164079fcc1 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/47/d9fe1a890a3d711662f4f414aee1ea6ae92261 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/49/da3d511c413f21dca0f072ad52b0aca2d3c167 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/4f/1897fc4248a024fc88e51f53f9028f531318cc +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/50/f89469bbe802dad848dcfeb2a8e447d4cd5787 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/51/7ac4b389a310399e096baab0af89f1e5de7b3b +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/52/61e3b09b4722a7003c53a643085ca69e0c7bbd +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/53/7671d097d835bda94f0460295ce1cf49eda99a +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/54/8d12b92b82f95dc93b4f069086d8214651593d +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/55/2cd273856516fd1a5e026ef23c9ffeb5a33876 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/56/52f31ea165a3ace62d1394af754a8aac78aa9f +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/57/9c69b0b67ebff094514cec01f692e21ca5e965 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/57/ddc6c8820bd8ec98845e7f5a29bf3302f0f481 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/58/2fba780a9cb7a9f312bd21cf97f16bc5b347c3 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/5c/6b70ca4f2f822429a97a84428580966d84ab3a +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/5e/c686a09ef712b11372e38d25c958b027b3f21f +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/5f/96e4a89ab06b40be8c45cd0d975bdc2f957064 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/60/c9053920fd6a8cd64eb28d8df99bcc2d176d59 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/62/1ab88d46df0f1b1015e250f4c8174729629400 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/62/5d72f7372bae8ab3ccc056e829c277c0705d1b +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/64/1ee83ac5a80cc7ae2e5f036db6329eacd03deb +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/65/011e04aeddd4c893a7a64b7ef745e9ad1af3c3 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/66/b5f21689d122c08ee3b98d35f3de096addcfcc +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/69/89864c6313789a85608f01eda8976e1215bd31 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/69/db255149b01f9ab01b48138fbb0f2d9b8b1acd +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/6a/597477c08142472e4a0559811e459ae7b127fc +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/6a/5e5e8ca97f2dec142b2ba15ed97a8493c16a54 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/6b/d7a53ed2c5cd4c0e97267b70fff1dd461b60b7 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/6d/05c5aaad4ff44578bbc46b5f7fc96f0d114e04 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/6d/5c36f68694ad597a4deeba39e56e561ba72f2f +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/6e/3f7883a133ec8310cf8ad07cba6aead4583ff9 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/6f/15710e7621abc864dabb788c5dfcab181e4551 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/71/6894eaf5165344374d82dda25e82eff5fce119 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/71/ca2fc16d0959c7465d57077a260156674274ba +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/74/0db02cd55f69b9f21f49a359fc14c15ad7f8ce +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/76/37fd54a47bfbdf2eed4827b78dff6019b87e57 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/79/15535a493620715580f5d0ce8c2481172d44bd +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/7b/ad63d2dd7dab6c33f73a31bd359129523ac5ce +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/7c/95c6bec18763286e0100ebc4fbef71df48b0ae +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/7f/a3240ccd3661f7786bd269a0b0875cd9037b4b +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/82/8511321c72b509d8b39d3a392014e2748036ad +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/84/3e8bf8d7bf26780eb4c44f0e1733dae7df37da +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/84/45dbe199e0d8e83aa85b04f68c4b4e97764c46 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/85/58de1a164b671ae0c5e9867140f4d105b26c71 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/85/bfef5de75cdd3313dea22060cd9f22bf6f611c +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/87/075d1b2ca01520a54b6e2053d2b07e30ff550e +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/8a/2f2b74b3a7f9b0f2969ff455d1b5a149189522 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/8b/da82680cf77bd85ef26d162f09df5b555c4817 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/8b/f368e49da5649603590fd2ad157fb423f91240 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/8c/988f80dcde632bee9389cb52d7c2639e358676 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/8d/9cc78f614e082762dfd1af4d90b83e97509ba4 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/91/b7e6699fcf2d3d87bc9209c30743851b95937e +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/97/6c6c60bcbbfe1b2ea7dc08631420753e2a2c55 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/98/414112321df2d4fef51640978555b7b0a10740 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/98/5dbb79e4f3157ba4a5b967ca1f045087fe718c +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/9b/8451b0fde38dfc5250c52aab3ef3fd30ef616d +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/9d/04ed7e9c2fdc16eadb72867c45c682d0661d8e +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/9d/1dcfdaf1a6857c5f83dc27019c7600e1ffaff8 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/9e/9190183a3e710fd6a3caabafda0395aacc4907 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/a4/9ab06df8e92e9921f006c4687a8119a41f140c +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/a4/9e182d79178f30917cb9d5d007bf4ad4354efc +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/a5/374e27f1f437b7b8d795bdbba9990e1b33ac4a +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/a9/621b26eb6fcf44e82b8f40fe15a08db273ea94 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/a9/958ca6bbbce4793eb63dfc75053f6f2c468f7d +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/ab/8112dc0e039a6764e18515bc8b9d25bf8cba72 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/ad/86572a7a3d9c41b39f68c1509f45eeb3c47145 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/ae/7c0c0693884ee9968bd46c7e3c1c4801c93f07 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/af/66d7ee37e22b5b4ffcb43392bcd6fe58b7189b +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/b0/1eb7d29ce867088dcfec990e3a118ee7d3a3b2 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/b0/6bfa35440cb0bf33a698db8b116077b885dade +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/b2/30e20e02ded29d01eb93f89b62ab47fb378e1f +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/b2/e68381120a59886f7999876775e9b3dfeaa550 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/b3/a239ea6bac51a6315988af95d83e86323aa461 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/b4/1e24e40f90ad6c12b6f840ecdb133b2749ca7e +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/b9/4bb6724a0646fb1636a66de603cec15e7dfa3e +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/bb/8fccf2b545f4ba46149fb07bd1f700ae7bcc87 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/be/9fc276a620ea29d87e2001489e436f6e714a34 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/bf/a019fa30db2df7e7732d119032e84391c3b6ce +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/c0/2beae1cbe94f20d2a4ef88b46bd8ade684f911 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/c6/1651ba7a27cd0ff5c726c4ce79751facc64f39 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/c7/f3f6ba90a1ec28fdef6ec7b10d82f4ad144969 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/cb/b097bc0ed0f65614e13f563a22624f0ce078e6 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/cd/3c462e6a24c9757a0fffd7c42abce926e1adf5 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/ce/f38215c9c7dc239421d85ca93221ad7beb63cb +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/cf/286c5bf7cffc4bf93b51554d4299845172df84 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/d0/aa218f92135250fa46b8490c68f4e77846b1b1 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/d1/70d82f10fffbce5936fc1d0f5e1f051c354413 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/d1/eccedbd9604b59bcc247b6f8a177df5486ce57 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/d4/1a891e54bfd7ddd745555624ce9142a47e5fdd +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/d8/2d02db21187a83d77a71c8665e1b4699e481fb +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/d8/76cc79a2f25f4e8616805811110f700e277af2 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/db/3bb89cba087a88feb4075b467732846a1d0118 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/db/dc7e591f97aab4da5d2acb29194355c277acf6 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/df/8c39b5b6cfcf19f8f27d5913830cb0a8fcd4c8 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/df/a8267b7bcb40cc3c4524934d386516e27dd5db +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/e0/87a95e8c14f5d090c04d19d3a9f91a208b7841 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/e0/e63743c9660300f76483d3ad27ecd85241cdc5 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/e2/2ab51073af126f1b602884b02dad11f9027942 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/e4/1b4051ac3bac5364f7a5ce048ecc41147857d6 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/e4/1dbd057baa81d4e660a52d2486ee700f8c7b60 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/e4/fba2702e9b6e30902b10ef946b8e05ee14b3d6 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/e5/23965887274b5a3060bca39ec005e6fe99883b +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/e6/3334965c2117237f22708d1c4681be5d77574b +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/e8/a732d4490c14cf239dd7081c8c1d15b44c495b +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/eb/22d1e687a8a2dd36474c7add9535ebe9682d3b +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/eb/7320ad4e2f7d18b503c64b2a983c2a41fc8eb1 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/ec/2badeec80e4ddc66a5168d8c3aec878a30f813 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/ec/d43841d2e6e7268caf4a1bb03c3f549ca75f49 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/f0/c3d899d1d7578174419e3d21fbb43d469ea0df +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/f2/d740d8021553398f98f1302398006e988697ef +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/f3/505619e9502b8a75ce04cf75ccb61e54f16cf5 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/f3/681d2437d363e9865aec3eb4e3e8f5aff46ca6 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/f3/b1f01d9f8fab935f87bee101fa0f1f944c30d8 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/f3/e2082feab4cb9a889f623d8fe7b58628f82da9 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/f4/21fa018addaacd7f59e11603b182b38207abca +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/f5/9e7ad7dad379a9752969e3443d3ed60a82cdf1 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/f6/d28255ddf6cd98d69342c282663771093ad834 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/f7/c7da26bbfca63ed8af08f9b7b1ace4930dad44 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/f9/aece29cc134fc99f629129d46c712f015b00c0 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/fb/4fbcdf3b0da9864651c5d50322b27c21f26fed +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/fb/ba70de6b161e2918d9d9e62d734abd85d01ae1 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/fb/bc2db563e1d0b7a0745a04fd0a0c5b5ef7e6aa +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/fc/03924609632d9a9f820119bdf5a9ddf5a4c90a +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/fd/3fb430f4e9190752eb58cef5019660e9aa92ef +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/fd/d0e4feee582591e85b9d488dd4fa1794364abb +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/objects/fe/092d97fe5a0e2a3d7b807e1a9f44735281a286 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/refs/heads/main +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/refs/remotes/origin/main +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/refs/tags/v0.1.0 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/refs/tags/v0.2.0 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/refs/tags/v0.3.0 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/refs/tags/v0.3.1 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/refs/tags/v0.3.2 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/refs/tags/v0.4.0 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/refs/tags/v0.4.1 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/refs/tags/v0.4.3 +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/tests/__init__.py +0 -0
- {e3cli-1.0.2 → e3cli-1.0.4}/tests/test_basic.py +0 -0
|
@@ -41,16 +41,6 @@ jobs:
|
|
|
41
41
|
steps:
|
|
42
42
|
- uses: actions/checkout@v4
|
|
43
43
|
|
|
44
|
-
- name: Calculate tarball sha256
|
|
45
|
-
id: sha
|
|
46
|
-
run: |
|
|
47
|
-
TARBALL_URL="https://github.com/${{ github.repository }}/archive/refs/tags/${{ github.ref_name }}.tar.gz"
|
|
48
|
-
echo "url=${TARBALL_URL}" >> "$GITHUB_OUTPUT"
|
|
49
|
-
SHA=$(curl -sL "${TARBALL_URL}" | sha256sum | cut -d' ' -f1)
|
|
50
|
-
echo "sha256=${SHA}" >> "$GITHUB_OUTPUT"
|
|
51
|
-
echo "Tarball: ${TARBALL_URL}"
|
|
52
|
-
echo "SHA256: ${SHA}"
|
|
53
|
-
|
|
54
44
|
- name: Clone homebrew tap
|
|
55
45
|
uses: actions/checkout@v4
|
|
56
46
|
with:
|
|
@@ -64,29 +54,32 @@ jobs:
|
|
|
64
54
|
|
|
65
55
|
- name: Generate formula with all transitive dependencies
|
|
66
56
|
run: |
|
|
67
|
-
python3 - "${{ github.repository }}" "${{
|
|
68
|
-
import json, re, sys, urllib.request
|
|
57
|
+
python3 - "${{ github.repository }}" "${{ github.ref_name }}" << 'PYSCRIPT'
|
|
58
|
+
import json, re, sys, time, urllib.request
|
|
69
59
|
|
|
70
|
-
repo,
|
|
60
|
+
repo, ref_name = sys.argv[1], sys.argv[2]
|
|
61
|
+
e3cli_version = ref_name.lstrip("v")
|
|
71
62
|
|
|
72
|
-
def get_info(pkg):
|
|
63
|
+
def get_info(pkg, version=None):
|
|
64
|
+
"""Fetch package info from PyPI. If version is given, look up that specific
|
|
65
|
+
release's files; otherwise use the latest. Returns None if the version is
|
|
66
|
+
not yet indexed or no installable file exists."""
|
|
73
67
|
pkg_normalized = re.sub(r'[-_.]+', '-', pkg).lower()
|
|
74
68
|
try:
|
|
75
69
|
data = json.loads(urllib.request.urlopen(f"https://pypi.org/pypi/{pkg_normalized}/json").read())
|
|
76
70
|
except Exception:
|
|
77
71
|
return None
|
|
78
|
-
ver = data["info"]["version"]
|
|
72
|
+
ver = version or data["info"]["version"]
|
|
79
73
|
requires = data["info"].get("requires_dist") or []
|
|
80
74
|
deps = []
|
|
81
75
|
for r in requires:
|
|
82
76
|
if "extra ==" in r:
|
|
83
77
|
continue
|
|
84
|
-
# Extract package name (before any version specifier or marker)
|
|
85
78
|
m = re.match(r'^([A-Za-z0-9]([A-Za-z0-9._-]*[A-Za-z0-9])?)', r)
|
|
86
79
|
if m:
|
|
87
80
|
deps.append(m.group(1).lower())
|
|
88
|
-
# Prefer pure-Python wheel (py3-none-any) → no compile,
|
|
89
|
-
# Fall back to sdist
|
|
81
|
+
# Prefer pure-Python wheel (py3-none-any) → no compile, no build-isolation,
|
|
82
|
+
# much faster brew install. Fall back to sdist if no universal wheel exists.
|
|
90
83
|
wheel_url = wheel_sha = sdist_url = sdist_sha = ""
|
|
91
84
|
for f in data["releases"].get(ver, []):
|
|
92
85
|
if f["packagetype"] == "bdist_wheel" and "py3-none-any" in f["filename"]:
|
|
@@ -95,7 +88,27 @@ jobs:
|
|
|
95
88
|
sdist_url, sdist_sha = f["url"], f["digests"]["sha256"]
|
|
96
89
|
url = wheel_url or sdist_url
|
|
97
90
|
sha = wheel_sha or sdist_sha
|
|
98
|
-
|
|
91
|
+
if not url:
|
|
92
|
+
return None
|
|
93
|
+
return {
|
|
94
|
+
"name": pkg_normalized, "deps": deps,
|
|
95
|
+
"url": url, "sha256": sha,
|
|
96
|
+
"has_wheel": bool(wheel_url),
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
# Resolve e3cli itself from PyPI (the just-uploaded version). Retry until the
|
|
100
|
+
# wheel appears — PyPI's JSON API may lag a few seconds after twine upload.
|
|
101
|
+
self_info = None
|
|
102
|
+
for attempt in range(12): # 12 × 5s = 60s budget
|
|
103
|
+
self_info = get_info("e3cli", version=e3cli_version)
|
|
104
|
+
if self_info and self_info["has_wheel"]:
|
|
105
|
+
break
|
|
106
|
+
print(f"PyPI wheel for e3cli {e3cli_version} not ready (attempt {attempt + 1}/12)…", file=sys.stderr)
|
|
107
|
+
time.sleep(5)
|
|
108
|
+
if not self_info:
|
|
109
|
+
sys.exit(f"FATAL: e3cli {e3cli_version} not found on PyPI after retries")
|
|
110
|
+
if not self_info["has_wheel"]:
|
|
111
|
+
print(f"WARNING: no wheel for e3cli {e3cli_version}; formula will use sdist and be slow", file=sys.stderr)
|
|
99
112
|
|
|
100
113
|
# Resolve ALL transitive dependencies
|
|
101
114
|
seen = set()
|
|
@@ -119,15 +132,16 @@ jobs:
|
|
|
119
132
|
if dk not in seen:
|
|
120
133
|
queue.append(d)
|
|
121
134
|
|
|
122
|
-
# Build formula
|
|
135
|
+
# Build formula — main package URL points to PyPI wheel (NOT GitHub source
|
|
136
|
+
# tarball). This avoids brew triggering pip's build-isolation flow on install.
|
|
123
137
|
lines = [
|
|
124
138
|
'class E3cli < Formula',
|
|
125
139
|
' include Language::Python::Virtualenv',
|
|
126
140
|
'',
|
|
127
141
|
' desc "NYCU E3 Moodle automation CLI — sync courses, download materials, submit assignments"',
|
|
128
142
|
f' homepage "https://github.com/{repo}"',
|
|
129
|
-
f' url "{
|
|
130
|
-
f' sha256 "{
|
|
143
|
+
f' url "{self_info["url"]}"',
|
|
144
|
+
f' sha256 "{self_info["sha256"]}"',
|
|
131
145
|
' license "MIT"',
|
|
132
146
|
'',
|
|
133
147
|
' depends_on "python@3.12"',
|
|
@@ -54,8 +54,16 @@ e3cli i
|
|
|
54
54
|
|
|
55
55
|
# Token expired?
|
|
56
56
|
e3cli login --refresh
|
|
57
|
+
|
|
58
|
+
# AI agent skill (install SKILL.md into Claude Code / Codex / Gemini / Antigravity CLI)
|
|
59
|
+
e3cli skill status # check what's detected / installed
|
|
60
|
+
e3cli skill install # auto-install for detected agents
|
|
61
|
+
e3cli skill install -t claude # specific target (claude/codex/gemini/antigravity)
|
|
62
|
+
e3cli skill uninstall # remove
|
|
57
63
|
```
|
|
58
64
|
|
|
65
|
+
> **First run:** if `~/.e3cli/config.toml` doesn't exist, ANY `e3cli <cmd>` launches the interactive setup wizard. The wizard is 6 steps (Moodle URL → semester format → download dir → alias → login → AI agent skill install). After completion, re-run the original command.
|
|
66
|
+
|
|
59
67
|
## Workflow: When a New Assignment is Detected
|
|
60
68
|
|
|
61
69
|
1. `e3cli sync` — pull latest materials and assignment status
|
|
@@ -99,6 +107,7 @@ e3cli download --course "artificial intelligence"
|
|
|
99
107
|
3. **Check deadlines first** — prioritize urgent assignments
|
|
100
108
|
4. **Token expiry** — if commands fail with auth errors, run `e3cli login --refresh`
|
|
101
109
|
5. **Don't read credential files** — use CLI commands, not direct file access
|
|
110
|
+
6. **First-run wizard hangs the agent** — if a command opens an interactive setup wizard (config missing) or `login --refresh` prompt, STOP and tell the user to run `e3cli setup` / `e3cli login --refresh` themselves in their terminal. Both are interactive and will hang an agent session.
|
|
102
111
|
|
|
103
112
|
## Data Locations
|
|
104
113
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: e3cli
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.4
|
|
4
4
|
Summary: NYCU E3 Moodle automation CLI — sync courses, download materials, submit assignments.
|
|
5
5
|
Project-URL: Homepage, https://github.com/junlinwk/e3cli
|
|
6
6
|
Project-URL: Repository, https://github.com/junlinwk/e3cli
|
|
@@ -52,7 +52,7 @@ Description-Content-Type: text/markdown
|
|
|
52
52
|
<a href="#commands">Commands</a> •
|
|
53
53
|
<a href="#interactive-mode">Interactive</a> •
|
|
54
54
|
<a href="#security">Security</a> •
|
|
55
|
-
<a href="#
|
|
55
|
+
<a href="#ai-agent-integration">AI Agents</a> •
|
|
56
56
|
<a href="./README_zh-TW.md">繁體中文</a>
|
|
57
57
|
</p>
|
|
58
58
|
|
|
@@ -78,6 +78,7 @@ Description-Content-Type: text/markdown
|
|
|
78
78
|
- **Interactive TUI** — Full arrow-key interactive interface (`e3cli i`)
|
|
79
79
|
- **Bilingual** — Full Chinese/English support
|
|
80
80
|
- **Multi-school** — Works with any Moodle instance (configurable semester format)
|
|
81
|
+
- **AI Agent Skill** — Bundled SKILL.md installable into Claude Code / Codex CLI / Gemini CLI / Antigravity CLI (`agy`) (`e3cli skill install`)
|
|
81
82
|
|
|
82
83
|
## Supported Platforms
|
|
83
84
|
|
|
@@ -136,6 +137,8 @@ pip install -e ".[dev]"
|
|
|
136
137
|
|
|
137
138
|
## Quick Start
|
|
138
139
|
|
|
140
|
+
> On first run, **any** `e3cli <something>` command will launch the interactive setup wizard (language, Moodle URL, semester format, alias, login, AI agent skill). After setup, re-run your original command.
|
|
141
|
+
|
|
139
142
|
```bash
|
|
140
143
|
# 1. Login (first time — interactive setup wizard will guide you)
|
|
141
144
|
e3cli login --save
|
|
@@ -297,12 +300,29 @@ e3cli profile use ntu # → connects to NTU COOL
|
|
|
297
300
|
|
|
298
301
|
### `e3cli setup`
|
|
299
302
|
|
|
300
|
-
Re-run the interactive setup wizard
|
|
303
|
+
Re-run the interactive setup wizard. Six steps: Moodle URL → semester format → download directory → command alias → login → AI agent skill install.
|
|
301
304
|
|
|
302
305
|
```bash
|
|
303
306
|
e3cli setup
|
|
304
307
|
```
|
|
305
308
|
|
|
309
|
+
> The setup wizard runs automatically the first time any `e3cli` command is invoked (config file missing).
|
|
310
|
+
|
|
311
|
+
### `e3cli skill`
|
|
312
|
+
|
|
313
|
+
Install the bundled SKILL.md so AI coding agents (Claude Code / Codex CLI / Gemini CLI / Antigravity CLI (`agy`)) know how to use e3cli — when to sync, how to read full assignment details, when to ask before submitting.
|
|
314
|
+
|
|
315
|
+
```bash
|
|
316
|
+
e3cli skill status # show which agents are detected + installed
|
|
317
|
+
e3cli skill install # auto-detect ~/.claude / ~/.codex / ~/.gemini / antigravity-cli
|
|
318
|
+
e3cli skill install -t claude # install for a specific target (claude/codex/gemini/antigravity)
|
|
319
|
+
e3cli skill install -t all # install for all known agents (even if undetected)
|
|
320
|
+
e3cli skill install --force # overwrite existing
|
|
321
|
+
e3cli skill uninstall # remove from all agent dirs
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
The setup wizard offers this as Step 6; running `e3cli skill install` later is the same operation.
|
|
325
|
+
|
|
306
326
|
### `e3cli version`
|
|
307
327
|
|
|
308
328
|
```bash
|
|
@@ -451,18 +471,31 @@ e3cli uses **PBKDF2-HMAC-SHA256** key derivation with integrity verification to
|
|
|
451
471
|
|
|
452
472
|
---
|
|
453
473
|
|
|
454
|
-
##
|
|
474
|
+
## AI Agent Integration
|
|
475
|
+
|
|
476
|
+
e3cli ships with a `SKILL.md` that teaches AI coding agents — [Claude Code](https://claude.ai/code), OpenAI Codex CLI, Google Gemini CLI, and Google Antigravity CLI (`agy`, Gemini CLI's successor) — how to use it correctly: sync first, read full assignment details before working, ask before submitting, never read credential files, etc.
|
|
477
|
+
|
|
478
|
+
### Install the skill
|
|
479
|
+
|
|
480
|
+
The setup wizard's Step 6 offers this automatically. To install manually:
|
|
481
|
+
|
|
482
|
+
```bash
|
|
483
|
+
e3cli skill install # auto-detects ~/.claude / ~/.codex / ~/.gemini / ~/.gemini/antigravity-cli
|
|
484
|
+
e3cli skill status # see what's detected and installed
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
Once installed, the agent recognises Moodle-related requests ("Moodle", "NYCU", "E3", "assignment", "作業", "繳交", …) and follows the bundled workflow.
|
|
455
488
|
|
|
456
|
-
|
|
489
|
+
### What the agent can do
|
|
457
490
|
|
|
458
491
|
- Sync and check for new assignments (`e3cli sync`)
|
|
459
492
|
- Read assignment descriptions and downloaded materials
|
|
460
493
|
- Help complete assignments (with human oversight)
|
|
461
494
|
- Submit completed work (`e3cli submit`)
|
|
462
495
|
|
|
463
|
-
See [`CLAUDE.md`](./CLAUDE.md) and [`e3cli/agent_prompt.md`](./e3cli/agent_prompt.md) for the full agent automation guide.
|
|
496
|
+
See [`e3cli/skills/e3cli/SKILL.md`](./e3cli/skills/e3cli/SKILL.md), [`CLAUDE.md`](./CLAUDE.md), and [`e3cli/agent_prompt.md`](./e3cli/agent_prompt.md) for the full agent automation guide.
|
|
464
497
|
|
|
465
|
-
> **Note:**
|
|
498
|
+
> **Note:** AI agents will always ask for confirmation before submitting assignments.
|
|
466
499
|
|
|
467
500
|
---
|
|
468
501
|
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
<a href="#commands">Commands</a> •
|
|
19
19
|
<a href="#interactive-mode">Interactive</a> •
|
|
20
20
|
<a href="#security">Security</a> •
|
|
21
|
-
<a href="#
|
|
21
|
+
<a href="#ai-agent-integration">AI Agents</a> •
|
|
22
22
|
<a href="./README_zh-TW.md">繁體中文</a>
|
|
23
23
|
</p>
|
|
24
24
|
|
|
@@ -44,6 +44,7 @@
|
|
|
44
44
|
- **Interactive TUI** — Full arrow-key interactive interface (`e3cli i`)
|
|
45
45
|
- **Bilingual** — Full Chinese/English support
|
|
46
46
|
- **Multi-school** — Works with any Moodle instance (configurable semester format)
|
|
47
|
+
- **AI Agent Skill** — Bundled SKILL.md installable into Claude Code / Codex CLI / Gemini CLI / Antigravity CLI (`agy`) (`e3cli skill install`)
|
|
47
48
|
|
|
48
49
|
## Supported Platforms
|
|
49
50
|
|
|
@@ -102,6 +103,8 @@ pip install -e ".[dev]"
|
|
|
102
103
|
|
|
103
104
|
## Quick Start
|
|
104
105
|
|
|
106
|
+
> On first run, **any** `e3cli <something>` command will launch the interactive setup wizard (language, Moodle URL, semester format, alias, login, AI agent skill). After setup, re-run your original command.
|
|
107
|
+
|
|
105
108
|
```bash
|
|
106
109
|
# 1. Login (first time — interactive setup wizard will guide you)
|
|
107
110
|
e3cli login --save
|
|
@@ -263,12 +266,29 @@ e3cli profile use ntu # → connects to NTU COOL
|
|
|
263
266
|
|
|
264
267
|
### `e3cli setup`
|
|
265
268
|
|
|
266
|
-
Re-run the interactive setup wizard
|
|
269
|
+
Re-run the interactive setup wizard. Six steps: Moodle URL → semester format → download directory → command alias → login → AI agent skill install.
|
|
267
270
|
|
|
268
271
|
```bash
|
|
269
272
|
e3cli setup
|
|
270
273
|
```
|
|
271
274
|
|
|
275
|
+
> The setup wizard runs automatically the first time any `e3cli` command is invoked (config file missing).
|
|
276
|
+
|
|
277
|
+
### `e3cli skill`
|
|
278
|
+
|
|
279
|
+
Install the bundled SKILL.md so AI coding agents (Claude Code / Codex CLI / Gemini CLI / Antigravity CLI (`agy`)) know how to use e3cli — when to sync, how to read full assignment details, when to ask before submitting.
|
|
280
|
+
|
|
281
|
+
```bash
|
|
282
|
+
e3cli skill status # show which agents are detected + installed
|
|
283
|
+
e3cli skill install # auto-detect ~/.claude / ~/.codex / ~/.gemini / antigravity-cli
|
|
284
|
+
e3cli skill install -t claude # install for a specific target (claude/codex/gemini/antigravity)
|
|
285
|
+
e3cli skill install -t all # install for all known agents (even if undetected)
|
|
286
|
+
e3cli skill install --force # overwrite existing
|
|
287
|
+
e3cli skill uninstall # remove from all agent dirs
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
The setup wizard offers this as Step 6; running `e3cli skill install` later is the same operation.
|
|
291
|
+
|
|
272
292
|
### `e3cli version`
|
|
273
293
|
|
|
274
294
|
```bash
|
|
@@ -417,18 +437,31 @@ e3cli uses **PBKDF2-HMAC-SHA256** key derivation with integrity verification to
|
|
|
417
437
|
|
|
418
438
|
---
|
|
419
439
|
|
|
420
|
-
##
|
|
440
|
+
## AI Agent Integration
|
|
441
|
+
|
|
442
|
+
e3cli ships with a `SKILL.md` that teaches AI coding agents — [Claude Code](https://claude.ai/code), OpenAI Codex CLI, Google Gemini CLI, and Google Antigravity CLI (`agy`, Gemini CLI's successor) — how to use it correctly: sync first, read full assignment details before working, ask before submitting, never read credential files, etc.
|
|
443
|
+
|
|
444
|
+
### Install the skill
|
|
445
|
+
|
|
446
|
+
The setup wizard's Step 6 offers this automatically. To install manually:
|
|
447
|
+
|
|
448
|
+
```bash
|
|
449
|
+
e3cli skill install # auto-detects ~/.claude / ~/.codex / ~/.gemini / ~/.gemini/antigravity-cli
|
|
450
|
+
e3cli skill status # see what's detected and installed
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
Once installed, the agent recognises Moodle-related requests ("Moodle", "NYCU", "E3", "assignment", "作業", "繳交", …) and follows the bundled workflow.
|
|
421
454
|
|
|
422
|
-
|
|
455
|
+
### What the agent can do
|
|
423
456
|
|
|
424
457
|
- Sync and check for new assignments (`e3cli sync`)
|
|
425
458
|
- Read assignment descriptions and downloaded materials
|
|
426
459
|
- Help complete assignments (with human oversight)
|
|
427
460
|
- Submit completed work (`e3cli submit`)
|
|
428
461
|
|
|
429
|
-
See [`CLAUDE.md`](./CLAUDE.md) and [`e3cli/agent_prompt.md`](./e3cli/agent_prompt.md) for the full agent automation guide.
|
|
462
|
+
See [`e3cli/skills/e3cli/SKILL.md`](./e3cli/skills/e3cli/SKILL.md), [`CLAUDE.md`](./CLAUDE.md), and [`e3cli/agent_prompt.md`](./e3cli/agent_prompt.md) for the full agent automation guide.
|
|
430
463
|
|
|
431
|
-
> **Note:**
|
|
464
|
+
> **Note:** AI agents will always ask for confirmation before submitting assignments.
|
|
432
465
|
|
|
433
466
|
---
|
|
434
467
|
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
<a href="#指令說明">指令</a> •
|
|
19
19
|
<a href="#互動模式">互動模式</a> •
|
|
20
20
|
<a href="#安全性">安全性</a> •
|
|
21
|
-
<a href="#
|
|
21
|
+
<a href="#ai-agent-整合">AI Agent</a> •
|
|
22
22
|
<a href="./README.md">English</a>
|
|
23
23
|
</p>
|
|
24
24
|
|
|
@@ -44,6 +44,7 @@
|
|
|
44
44
|
- **互動介面** — 完整方向鍵互動介面 (`e3cli i`)
|
|
45
45
|
- **雙語** — 完整中文/英文支援
|
|
46
46
|
- **多校支援** — 支援任何 Moodle 平台(可設定學期格式)
|
|
47
|
+
- **AI Agent Skill** — 內建 SKILL.md,可一鍵安裝到 Claude Code / Codex CLI / Gemini CLI / Antigravity CLI (`agy`)(`e3cli skill install`)
|
|
47
48
|
|
|
48
49
|
## 支援平台
|
|
49
50
|
|
|
@@ -102,6 +103,8 @@ pip install -e ".[dev]"
|
|
|
102
103
|
|
|
103
104
|
## 快速開始
|
|
104
105
|
|
|
106
|
+
> 首次執行時,**任何** `e3cli <指令>` 都會自動啟動互動式設定引導(語言、Moodle 網址、學期格式、別名、登入、AI agent skill)。設定完後請再執行一次原本的指令。
|
|
107
|
+
|
|
105
108
|
```bash
|
|
106
109
|
# 1. 登入(首次使用會啟動互動式引導)
|
|
107
110
|
e3cli login --save
|
|
@@ -263,12 +266,29 @@ e3cli profile use ntu # → 連線 NTU COOL
|
|
|
263
266
|
|
|
264
267
|
### `e3cli setup`
|
|
265
268
|
|
|
266
|
-
|
|
269
|
+
重新執行互動式設定引導。共 6 步驟:Moodle 網址 → 學期格式 → 下載目錄 → 指令別名 → 登入 → AI agent skill 安裝。
|
|
267
270
|
|
|
268
271
|
```bash
|
|
269
272
|
e3cli setup
|
|
270
273
|
```
|
|
271
274
|
|
|
275
|
+
> 首次執行任何 `e3cli` 指令時(找不到 config 檔),會自動跑這個 wizard。
|
|
276
|
+
|
|
277
|
+
### `e3cli skill`
|
|
278
|
+
|
|
279
|
+
安裝內建的 SKILL.md,讓 AI 編程助手(Claude Code / Codex CLI / Gemini CLI / Antigravity CLI `agy`)知道如何正確使用 e3cli — 何時 sync、如何讀取作業完整描述、提交前必先詢問等。
|
|
280
|
+
|
|
281
|
+
```bash
|
|
282
|
+
e3cli skill status # 列出偵測到 / 已安裝的 agent
|
|
283
|
+
e3cli skill install # 自動偵測 ~/.claude / ~/.codex / ~/.gemini / antigravity-cli
|
|
284
|
+
e3cli skill install -t claude # 安裝到特定目標 (claude/codex/gemini/antigravity)
|
|
285
|
+
e3cli skill install -t all # 安裝到所有已知 agent(即使未偵測到)
|
|
286
|
+
e3cli skill install --force # 覆寫既有的
|
|
287
|
+
e3cli skill uninstall # 從所有 agent 目錄移除
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
setup wizard 的 Step 6 會自動詢問是否安裝;事後跑 `e3cli skill install` 效果相同。
|
|
291
|
+
|
|
272
292
|
### `e3cli version`
|
|
273
293
|
|
|
274
294
|
```bash
|
|
@@ -417,18 +437,31 @@ e3cli 使用 **PBKDF2-HMAC-SHA256** 金鑰衍生搭配完整性驗證來保護
|
|
|
417
437
|
|
|
418
438
|
---
|
|
419
439
|
|
|
420
|
-
##
|
|
440
|
+
## AI Agent 整合
|
|
441
|
+
|
|
442
|
+
e3cli 內建一份 `SKILL.md`,教 AI 編程助手 — [Claude Code](https://claude.ai/code)、OpenAI Codex CLI、Google Gemini CLI、以及 Google Antigravity CLI (`agy`,Gemini CLI 的繼任者) — 如何正確使用:先 sync、開工前先讀完整作業描述、提交前必先詢問、不讀帳密檔等。
|
|
443
|
+
|
|
444
|
+
### 安裝 skill
|
|
445
|
+
|
|
446
|
+
setup wizard 的 Step 6 會自動詢問。事後手動安裝:
|
|
447
|
+
|
|
448
|
+
```bash
|
|
449
|
+
e3cli skill install # 自動偵測 ~/.claude / ~/.codex / ~/.gemini / antigravity-cli
|
|
450
|
+
e3cli skill status # 查看偵測 / 安裝狀態
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
裝好後,agent 偵測到 Moodle 相關需求("Moodle"、"NYCU"、"E3"、"作業"、"繳交" …)就會自動依照內建流程操作。
|
|
421
454
|
|
|
422
|
-
|
|
455
|
+
### Agent 能做的事
|
|
423
456
|
|
|
424
457
|
- 同步並檢查新作業 (`e3cli sync`)
|
|
425
458
|
- 讀取作業描述與已下載的教材
|
|
426
459
|
- 協助完成作業(需人工審查)
|
|
427
460
|
- 提交完成的作業 (`e3cli submit`)
|
|
428
461
|
|
|
429
|
-
詳見 [`CLAUDE.md`](./CLAUDE.md)
|
|
462
|
+
詳見 [`e3cli/skills/e3cli/SKILL.md`](./e3cli/skills/e3cli/SKILL.md)、[`CLAUDE.md`](./CLAUDE.md) 與 [`e3cli/agent_prompt.md`](./e3cli/agent_prompt.md)。
|
|
430
463
|
|
|
431
|
-
> **注意:**
|
|
464
|
+
> **注意:** AI agent 在提交作業前一定會先詢問確認。
|
|
432
465
|
|
|
433
466
|
---
|
|
434
467
|
|
|
@@ -14,6 +14,7 @@ e3cli is a CLI tool for interacting with NYCU's E3 Moodle platform. The agent ca
|
|
|
14
14
|
|
|
15
15
|
- e3cli must be installed and logged in (`e3cli login --save`)
|
|
16
16
|
- The agent must have shell access to run `e3cli` commands
|
|
17
|
+
- **First-run safety:** if `~/.e3cli/config.toml` does not exist, any `e3cli <cmd>` will launch an interactive setup wizard that **will hang an agent session**. Probe via `test -f ~/.e3cli/config.toml` before running real commands; if missing, tell the user to run `e3cli setup` themselves in their own terminal.
|
|
17
18
|
|
|
18
19
|
## Workflow
|
|
19
20
|
|
|
@@ -120,8 +121,11 @@ e3cli sync --quiet
|
|
|
120
121
|
| `e3cli download --course "X"` | Download course X materials |
|
|
121
122
|
| `e3cli download --all` | Download all materials |
|
|
122
123
|
| `e3cli submit ID file.pdf` | Submit assignment |
|
|
123
|
-
| `e3cli i` | Interactive mode |
|
|
124
|
-
| `e3cli login --refresh` | Refresh expired token |
|
|
124
|
+
| `e3cli i` | Interactive mode (DO NOT run from agent — TUI hangs) |
|
|
125
|
+
| `e3cli login --refresh` | Refresh expired token (interactive — instruct user) |
|
|
126
|
+
| `e3cli setup` | First-run wizard (interactive — instruct user) |
|
|
127
|
+
| `e3cli skill install` | Install bundled SKILL.md into Claude / Codex / Gemini / Antigravity (`agy`) |
|
|
128
|
+
| `e3cli skill status` | List which AI agent dirs are detected + installed |
|
|
125
129
|
|
|
126
130
|
## Data Locations
|
|
127
131
|
|
|
@@ -58,15 +58,16 @@ _original_app_call = app.__call__
|
|
|
58
58
|
|
|
59
59
|
|
|
60
60
|
def _app_with_first_run(*args, **kwargs):
|
|
61
|
-
|
|
61
|
+
# 只保留 shell completion 相關 — 這兩個是 shell 啟動時 typer 自動呼叫的,
|
|
62
|
+
# 若擋住會在開新 terminal 時 hang 在互動式 wizard。
|
|
63
|
+
skip_keywords = {"--show-completion", "--install-completion"}
|
|
62
64
|
if (
|
|
63
65
|
is_first_run()
|
|
64
66
|
and sys.stdin.isatty()
|
|
65
67
|
and not any(arg in skip_keywords for arg in sys.argv[1:])
|
|
66
68
|
):
|
|
67
69
|
run_setup_wizard()
|
|
68
|
-
|
|
69
|
-
return
|
|
70
|
+
return
|
|
70
71
|
return _original_app_call(*args, **kwargs)
|
|
71
72
|
|
|
72
73
|
|
|
@@ -176,7 +176,7 @@ def run_setup_wizard() -> None:
|
|
|
176
176
|
console.print()
|
|
177
177
|
|
|
178
178
|
# Step 1: Moodle URL
|
|
179
|
-
console.print(f"[bold cyan]Step 1/
|
|
179
|
+
console.print(f"[bold cyan]Step 1/6[/bold cyan] — {t('setup.step_url')}")
|
|
180
180
|
if lang == "zh":
|
|
181
181
|
console.print("[dim]輸入你的 Moodle 網址。支援任何學校的 Moodle 平台。[/dim]")
|
|
182
182
|
else:
|
|
@@ -212,12 +212,12 @@ def run_setup_wizard() -> None:
|
|
|
212
212
|
console.print()
|
|
213
213
|
|
|
214
214
|
# Step 2: Semester format
|
|
215
|
-
console.print("[bold cyan]Step 2/
|
|
215
|
+
console.print("[bold cyan]Step 2/6[/bold cyan] — ", end="")
|
|
216
216
|
sem_format = _choose_semester_format(lang)
|
|
217
217
|
console.print()
|
|
218
218
|
|
|
219
219
|
# Step 3: Download directory
|
|
220
|
-
console.print(f"[bold cyan]Step 3/
|
|
220
|
+
console.print(f"[bold cyan]Step 3/6[/bold cyan] — {t('setup.step_dir')}")
|
|
221
221
|
console.print(f"[dim]{t('setup.step_dir_hint')}[/dim]")
|
|
222
222
|
default_dir = os.path.expanduser("~/e3-downloads")
|
|
223
223
|
download_dir = typer.prompt(
|
|
@@ -228,7 +228,7 @@ def run_setup_wizard() -> None:
|
|
|
228
228
|
console.print()
|
|
229
229
|
|
|
230
230
|
# Step 4: Alias
|
|
231
|
-
console.print("[bold cyan]Step 4/
|
|
231
|
+
console.print("[bold cyan]Step 4/6[/bold cyan] — ", end="")
|
|
232
232
|
alias = _setup_alias(lang)
|
|
233
233
|
console.print()
|
|
234
234
|
|
|
@@ -255,7 +255,7 @@ alias = "{alias}"
|
|
|
255
255
|
console.print()
|
|
256
256
|
|
|
257
257
|
# Step 5: Login
|
|
258
|
-
console.print(f"[bold cyan]Step 5/
|
|
258
|
+
console.print(f"[bold cyan]Step 5/6[/bold cyan] — {t('setup.step_login')}")
|
|
259
259
|
want_login = typer.confirm(t("setup.want_login"), default=True)
|
|
260
260
|
|
|
261
261
|
if want_login:
|
|
@@ -296,6 +296,11 @@ alias = "{alias}"
|
|
|
296
296
|
console.print(f"[dim] {t('setup.login_fail_hint')}[/dim]")
|
|
297
297
|
console.print()
|
|
298
298
|
|
|
299
|
+
# Step 6: AI agent skill
|
|
300
|
+
console.print("[bold cyan]Step 6/6[/bold cyan] — ", end="")
|
|
301
|
+
_offer_skill_install(lang)
|
|
302
|
+
console.print()
|
|
303
|
+
|
|
299
304
|
# Done
|
|
300
305
|
console.print(Panel(
|
|
301
306
|
f"[bold green]{t('setup.done_title')}[/bold green]\n\n{t('setup.done_body')}",
|
|
@@ -304,6 +309,55 @@ alias = "{alias}"
|
|
|
304
309
|
))
|
|
305
310
|
|
|
306
311
|
|
|
312
|
+
def _offer_skill_install(lang: str) -> None:
|
|
313
|
+
"""偵測 ~/.claude / ~/.codex / ~/.gemini,有的話問要不要安裝 e3cli skill。"""
|
|
314
|
+
from e3cli.commands.skill import (
|
|
315
|
+
_bundled_skill_text,
|
|
316
|
+
_detected,
|
|
317
|
+
_install_one,
|
|
318
|
+
_targets,
|
|
319
|
+
)
|
|
320
|
+
|
|
321
|
+
if lang == "zh":
|
|
322
|
+
console.print("[bold cyan]AI Agent Skill[/bold cyan]")
|
|
323
|
+
console.print(
|
|
324
|
+
"[dim]安裝 SKILL.md 讓 Claude Code / Codex / Gemini CLI 知道如何使用 e3cli[/dim]"
|
|
325
|
+
)
|
|
326
|
+
else:
|
|
327
|
+
console.print("[bold cyan]AI Agent Skill[/bold cyan]")
|
|
328
|
+
console.print(
|
|
329
|
+
"[dim]Install SKILL.md so Claude Code / Codex / Gemini CLI know how to use e3cli[/dim]"
|
|
330
|
+
)
|
|
331
|
+
|
|
332
|
+
detected = _detected(_targets())
|
|
333
|
+
if not detected:
|
|
334
|
+
if lang == "zh":
|
|
335
|
+
console.print("[dim] 未偵測到 ~/.claude、~/.codex、~/.gemini — 跳過[/dim]")
|
|
336
|
+
console.print(
|
|
337
|
+
"[dim] 日後可執行 [cyan]e3cli skill install[/cyan] 安裝[/dim]"
|
|
338
|
+
)
|
|
339
|
+
else:
|
|
340
|
+
console.print("[dim] No ~/.claude, ~/.codex, ~/.gemini detected — skipping[/dim]")
|
|
341
|
+
console.print(
|
|
342
|
+
"[dim] Later run [cyan]e3cli skill install[/cyan] to install[/dim]"
|
|
343
|
+
)
|
|
344
|
+
return
|
|
345
|
+
|
|
346
|
+
names = ", ".join(tg.name for tg in detected)
|
|
347
|
+
if lang == "zh":
|
|
348
|
+
prompt = f" 偵測到 {names},要安裝 e3cli skill 嗎?"
|
|
349
|
+
else:
|
|
350
|
+
prompt = f" Detected: {names}. Install e3cli skill?"
|
|
351
|
+
if not typer.confirm(prompt, default=True):
|
|
352
|
+
return
|
|
353
|
+
|
|
354
|
+
content = _bundled_skill_text()
|
|
355
|
+
for tg in detected:
|
|
356
|
+
ok, msg = _install_one(tg, content, force=False)
|
|
357
|
+
marker = "[green] ✓[/green]" if ok else "[yellow] ·[/yellow]"
|
|
358
|
+
console.print(f"{marker} [bold]{tg.name}[/bold]: {msg}")
|
|
359
|
+
|
|
360
|
+
|
|
307
361
|
@app.callback(invoke_without_command=True)
|
|
308
362
|
def setup():
|
|
309
363
|
"""Re-run interactive setup wizard."""
|
|
@@ -39,6 +39,17 @@ def _targets() -> list[Target]:
|
|
|
39
39
|
detect_dir=home / ".codex",
|
|
40
40
|
skill_path=home / ".codex" / "skills" / SKILL_NAME / "SKILL.md",
|
|
41
41
|
),
|
|
42
|
+
# Antigravity CLI (`agy`) — Gemini CLI's successor. Reads skills from
|
|
43
|
+
# ~/.gemini/antigravity-cli/skills/. Standard SKILL.md format (our
|
|
44
|
+
# bundled file already has the YAML frontmatter agy expects).
|
|
45
|
+
Target(
|
|
46
|
+
name="antigravity",
|
|
47
|
+
detect_dir=home / ".gemini" / "antigravity-cli",
|
|
48
|
+
skill_path=home / ".gemini" / "antigravity-cli" / "skills" / SKILL_NAME / "SKILL.md",
|
|
49
|
+
),
|
|
50
|
+
# Legacy Gemini CLI extension format (kept for backward compat with
|
|
51
|
+
# users still on the pre-agy Gemini CLI). Uses ~/.gemini/extensions/
|
|
52
|
+
# with a gemini-extension.json descriptor.
|
|
42
53
|
Target(
|
|
43
54
|
name="gemini",
|
|
44
55
|
detect_dir=home / ".gemini",
|
|
@@ -68,7 +79,14 @@ def _bundled_skill_text() -> str:
|
|
|
68
79
|
|
|
69
80
|
|
|
70
81
|
def _detected(targets: list[Target]) -> list[Target]:
|
|
71
|
-
|
|
82
|
+
found = [t for t in targets if t.detect_dir.is_dir()]
|
|
83
|
+
# 若同時偵測到 antigravity (agy) 和 legacy gemini,自動跳過 legacy gemini。
|
|
84
|
+
# antigravity 的 detect_dir (~/.gemini/antigravity-cli) 是 gemini 的子目錄,
|
|
85
|
+
# 沒這個排除的話會在新 agy 用戶機器上重複裝。
|
|
86
|
+
names = {t.name for t in found}
|
|
87
|
+
if "antigravity" in names and "gemini" in names:
|
|
88
|
+
found = [t for t in found if t.name != "gemini"]
|
|
89
|
+
return found
|
|
72
90
|
|
|
73
91
|
|
|
74
92
|
def _install_one(target: Target, content: str, force: bool) -> tuple[bool, str]:
|
|
@@ -11,14 +11,16 @@ The same `e3cli` binary is invoked from the shell — this skill only tells you
|
|
|
11
11
|
|
|
12
12
|
## Prerequisites — verify first
|
|
13
13
|
|
|
14
|
-
Before doing real work, confirm the tool is installed and authenticated:
|
|
14
|
+
Before doing real work, confirm the tool is installed, configured, and authenticated:
|
|
15
15
|
|
|
16
16
|
```bash
|
|
17
|
+
test -f ~/.e3cli/config.toml && echo "configured" || echo "needs setup"
|
|
17
18
|
e3cli --version # is it installed?
|
|
18
19
|
e3cli courses # if this errors with "auth"/"token" → user must run: e3cli login --refresh
|
|
19
20
|
```
|
|
20
21
|
|
|
21
|
-
If
|
|
22
|
+
- If config is missing → **STOP**. Any `e3cli <cmd>` will launch an interactive first-run setup wizard that hangs the agent. Tell the user to run `e3cli setup` themselves in their terminal.
|
|
23
|
+
- If auth fails → **tell the user to run the login command themselves** — it is interactive and will hang if you run it. Do not attempt to read `~/.e3cli/credentials.enc`, `~/.e3cli/key`, or `~/.e3cli/token`.
|
|
22
24
|
|
|
23
25
|
## Core workflow
|
|
24
26
|
|
|
@@ -80,7 +82,7 @@ e3cli login --profile <name> --url <moodle-url> --save # add a new schoo
|
|
|
80
82
|
3. **Prioritize by deadline.** When the user vaguely asks "what should I do", run `e3cli assignments --due-soon 7` first.
|
|
81
83
|
4. **Never read credential files.** `~/.e3cli/credentials.enc`, `~/.e3cli/key`, `~/.e3cli/token` are encrypted/sensitive. Use CLI commands instead.
|
|
82
84
|
5. **Don't run `e3cli i`** (interactive TUI). It needs a real terminal and will hang the agent.
|
|
83
|
-
6. **Don't run `e3cli login
|
|
85
|
+
6. **Don't run `e3cli login`, `e3cli login --refresh`, or `e3cli setup` yourself.** They are interactive — instruct the user to run them.
|
|
84
86
|
|
|
85
87
|
## Data locations (reference)
|
|
86
88
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|