Repository navigation
1.5.0: optional school mail and attendance - #25
Merged
Merged
Conversation
Replaces the six shared modules with the versions running on the private deployment after real-account testing on 2026-10-31, and adds their tests and the Chinese setup guide. Not yet integrated: two existing tests fail (rollback expectation and optional-dependency policy) and the CLI/MCP glue still targets the earlier module API. See the porting PR for the remaining work. Fixes carried over: Gmail rate-limit retries, per-page sync commits, history label/deletion events without downloads, search result flags, mail to-do, label names and whole-thread actions, rejected state for pre-send checks, 30-day record cleanup, Attendance day selection through the portal's #daySel menu, configurable portal origin and timezone.
- Rewrite the rollback test for per-page sync commits and allow the gmail and attendance extras in the dependency test (core still only pypdf). - cli_gmail: add `gmail todo`, explain resumable and pending syncs. - New `monash attendance login|status|sync`; login turns on attendance_enabled. - student_tools picks the local MCP tools from settings: read-only mail (now with get_gmail_inbox_todo) and attendance_status/overview when enabled; gmail_prepare_action, attendance_prepare_submit and execute_student_action only with gmail_manage_enabled or attendance_submit_enabled. Writes still go through preview tickets. - Server instructions point mail questions at this server; help lists mail and attendance only when on. - remote.py rejects every mail and attendance tool, as before. - Docs: README sections, setup guide on public commands, design notes updated, changelog entry. Lock file now includes the extras; tzdata for Windows attendance.
Background mail sync: while the MCP server runs (local or remote serve), mail syncs every gmail_sync_minutes (30, 0 turns it off) in its own thread. It keeps the last query, comes back about a minute later while the first download is unfinished, indexes up to five attachments after a full round and logs an expired login only once. Remote per-app grants: the pairing page shows a checkbox for each mail and attendance feature the server has turned on (read-only ticked, write unticked). The choice is stored on codes and tokens, kept on refresh, intersected with the server settings on every call and shown by `monash remote clients`. Tokens from before the new column stay monash-only. Remote apps get the student_services catalog plus gmail_inbox_todo and student_job_status; tickets and jobs are keyed by client ID so one app cannot run another's ticket.
- Local MCP with attendance_enabled now also registers attendance_sync, attendance_find_codes and attendance_export as background jobs, plus student_job_status. With gmail_enabled it adds gmail_read_attachment. - gmail_prepare_action checks the saved Google authorization has write access before preparing, so a read-only login no longer ends with a ticket stuck as unknown (local and remote). - monash update keeps every installed extra (gmail, attendance, media); it used to keep only media and would have dropped the others. - monash attendance overview and codes for use without an AI app. - monash status and doctor show mail and attendance when they are on; doctor never prints the mail address. - A missing [gmail] install says what to install instead of looking like a network error. - Agent skill, help menu, README, setup guide, design notes, privacy note and changelog updated, including the measured token cost.
… HTTP read - Background attendance reads follow the timetable: weekday mornings at 8 and 15 minutes after each class not yet checked in to; nothing at night, at weekends or for finished classes (attendance_auto_sync). - Browser reads open Units.aspx once and switch days with #daySel instead of reloading for each day. - attendance_http: optional browser-free read with the saved cookies and a Python port of extract-rows.js (attendance_fast_read, off by default). Falls back to the browser when the menu or a day panel is missing. Parity tests run both parsers on the same pages. - `monash attendance probe` compares both reads on the real portal and prints only counts and match results. - attendance_auto records logins, successful reads and the first expiry; status and doctor show how long the login lasted. Optional HTTP keepalive saves renewed cookies (attendance_keepalive_minutes, off).
- Gmail test messages use a real timestamp. Windows cannot turn a time in the first day after 1970 into local time (OSError 22), which broke three tests there; real mail never has such a time. - The browser-free attendance read verifies HTTPS with the system certificate store through truststore, so a portal that leaves out its intermediate certificate still verifies on macOS and Windows. When it still cannot be verified the read falls back to the browser and probe reports it instead of exiting. Verification is never disabled. - __version__ 1.5.0 for the new features, as the version check requires.
Waldo0926
force-pushed
the
feat/student-services
branch
from
October 31, 2026 04:21
f63eb1a to
4cd0886
Compare
monash attendance probe on the Malaysia portal: all 15 day panels are in the page HTML and the Python and browser reads matched on every day, with the system certificate store. The read still falls back to the browser when the page does not look as expected. Every portal request now counts toward the login lifetime, so a successful probe or read updates it too (it showed 0 hours before).
The portal writes times first and as "4:00 pm". Check the parser and the after-class schedule with that format, as seen on a real read.
monash gmail login now asks for gmail.modify and turns on both Gmail settings; --read-only asks for gmail.readonly and leaves mailbox actions off (--manage is still accepted). monash attendance login turns on both attendance settings. Every action still goes through the preview and confirmation ticket, and each can be switched off with monash config. ADR 0004 records the decision: Moodle and Ed stay read-only, mail and attendance actions are on after login and only run after confirmation. README, setup guide, design notes, privacy policy and changelog updated.
monash gmail login now checks the --client file first and says what the path should be, how to drag the file into Terminal on macOS, and where the setup guide explains creating it.
monash config use_ed false, or answering yes in monash setup after skipping the Ed token, stops sync, the to-do list and monash doctor from reporting a missing token, hides the four Ed tools and the Ed part of the help, and tells the AI app not to suggest Ed. The default is unchanged and monash login ed turns it back on. Everything else already worked without Ed; this removes the nagging.
monash gmail login uses google_client.json from the package when no --client is given, so students only need to click through Google's consent page. --client still uses your own desktop client. A test checks that a bundled file is a desktop client, never a web client. The guide and READMEs now point people who only want to ask about their inbox to the AI apps' built-in Gmail connectors, explain the unverified app warning, and make creating your own Google app optional. The privacy policy says what the bundled client is and that mail never passes through the maintainer.
A separate desktop client in the Monash Student MCP project, so students can run monash gmail login without their own Google Cloud setup. The private deployment keeps its own client.
start_school_service_setup lets a student say "connect my school email" or "connect my attendance" in the AI app. In the background it installs the missing packages into the running install (uv, or pip), downloads the Playwright browser for attendance, opens the sign-in window, turns the features on, syncs once and sends notifications/tools/list_changed. Passwords and codes stay in the student's browser. The tool is local only (not offered remotely) and hidden once both are connected. The catalog limit goes from 18 to 19 tools; the size limit and the pinned contracts of the original 17 tools are unchanged. Default cost is 145 tokens per conversation (3,377 in total). monash gmail sync now downloads one page at a time and prints a line per page, so the first sync no longer looks stuck.
Turn the Unreleased notes into a 1.5.0 section grouped by connecting, school mail, attendance, remote and other changes; it becomes the GitHub release text. Install commands in the READMEs and setup guide now use PyPI, both READMEs get a "What's new in 1.5" section, and the release doc no longer says the smoke test expects 17 tools.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Before:
公开版只有 Moodle 和 Ed。Gmail、考勤和“预览再确认”的写操作只跑在私人部署上。
After:
完整说明见 CHANGELOG 的 1.5.0 一节(发版时会成为 GitHub Release 的内容)。要点:
接入
start_school_service_setup自动装缺的组件,打开登录窗口,接好后同步并通知 AI 软件刷新工具列表。两样都接好后这个工具不再列出。google_client.json,Monash Student MCP 项目里单独为公开版建的客户端),monash gmail login不用自己建 Google Cloud 项目;--client仍可用自己的。monash config关掉;Gmail 可用--read-only。学校邮箱
考勤
login|status|sync|overview|codes|probe,以及本地 AI 里的对应工具。远程 MCP
其他
monash config use_ed false。monash update保留所有已装的可选依赖;status、doctor覆盖邮箱和考勤。__version__1.5.0;核心依赖仍然只有 pypdf。How:
test_student_tools.py、test_service_setup.py、test_attendance_fast.py、test_attendance_parity.py(需要浏览器)、test_without_ed.py,test_remote.py加了按软件授权的 HTTP 流程。测试结果:
PYTHONPATH=src pytest -q:400 passed, 8 skipped(跳过的是需要浏览器的测试;用 playwright 1.63.0 单独跑过,8 passed)uvx ruff@0.6.9 check src tests scripts:All checks passeduv build加scripts/check_dist.py:通过;装进干净的 Python 3.10 venv 跑scripts/smoke_test.py:通过(19 个工具,7 个提示)monash gmail login(用自带的应用)成功,mode: manage;monash gmail sync下载 500 封;monash attendance probe:15 天两种读法全部一致;monash attendance sync --days 14用 HTTP 读到 5 节课,内容正确。尚未验证:
发布:合并后在 main 上打
v1.5.0tag 并推送,release 工作流会检查版本号和 CHANGELOG、跑测试、发 PyPI、建 GitHub Release。uv run pytest -qpassesuvx ruff@0.6.9 check src tests scriptspassessrc/changed:__version__bumped andCHANGELOG.mdupdatedgoogle_client.json是公开发布用的桌面应用客户端,按 Google 的设计不算机密)