Releases: Kaiji-Z/LookatStudy
Release list
v0.26.0
v0.26.0 gives the companion a home in the title bar, retires the mind map view, and hardens the drawers for phone widths.
The title bar is now living space. When the left map pane is off screen, on a phone in single-pane mode, before a course is picked, or with the rail collapsed, the companion used to hover at the left screen edge. It now shrinks to fit the title bar and drifts along it, crossing the full width over roughly forty seconds. When it drifts over a button it turns translucent and lets clicks pass through. You can drag it anywhere along the bar, or drag it out. Released outside the bar, it grows back to normal size and stays near where you dropped it, wandering a small radius. When the map pane returns, the placement clears and it goes home as usual.
Streaming answers summon it. While the AI is composing a reply, the companion flies to the spot above the input box, the same place it goes when you focus typing, and thinks along with the stream. When the reply finishes it returns to wherever it should be.
Note-taking no longer lingers. Marking a selection and adding a note brings the companion beside the line you drew for the writing gesture, as before. What changed is the exit. It used to pause at the top-right shoulder of the reading pane for a few seconds before heading home. It now leaves directly. Switching to the notes tab no longer summons it either.
The mind map view is gone. The Brain button and the markmap rendering have been removed. The reasoning is plain. When a lesson's markdown has headings, that structure is already visible on the page and a second rendering adds nothing. When the lesson has no headings, the previous release tried synthesizing nodes from first sentences, and the result was a map you could not actually read. Meanwhile the concept map artifact, generated by the AI from the lesson's meaning, already produces a real structure diagram on demand. One dependable tool beats two shaky ones. The markmap libraries are out of the package, which shaves the install size.
Drawers are designed to the phone floor. Both the settings and the review drawers follow the viewport width, full-width on a phone with the desktop caps unchanged. Their interiors are now checked at a 420-pixel phone viewport, where the old fixed five-column form grid and an unbreakable test-result row would have been squeezed past breaking. The form picker now wraps, result text folds, and the test suite opens each drawer at that width and asserts zero horizontal overflow.
v0.26.0 给伴学在标题栏安了家,撤下了思维导图,并把抽屉按手机宽度重新校准。
标题栏成了居住空间。 左栏不在场时,手机单栏、未选课程或收起左栏,伴学以前贴在屏幕左缘。现在他缩到标题栏的高度,沿栏缓缓游动,大约四十秒横穿一个来回。飘到按钮上会变半透明,点击直接穿过去。可以随手拖到栏内任意位置,也可以拖出去,松手后恢复原来的体型,留在放置处附近小范围徘徊。左栏回来时自动清掉手放落点,照常回家。
流式回答会召他来。 AI 组织回复期间,伴学飞到输入框上空,和聚焦打字时同一位置,托腮跟着思考。回复结束再回该去的地方。
加笔记不再多停留。 划线加笔记时他照旧飞到你画的那条线旁做记录动作,变的是退场。原先要在讲解面板右上角停几秒才回家,现在直接走。切到笔记标签页也不再召唤他。
思维导图撤了。 讲解区的 Brain 按钮和 markmap 渲染整体移除。理由很朴素。正文分了标题,结构本来就在页面上,再画一遍没有增量。正文没分标题,上一版试着取首句拼节点,拼出来的图看不懂。而对话产物里的 AI 概念图按内容语义出真正的结构图,已经覆盖这个场景。一个趁手的工具好过两个勉强的。markmap 两个库从依赖里删掉,安装体积小了一点。
抽屉按手机宽度校准。 设置和复习两个抽屉的宽度跟随视口,手机上全宽,桌面端上限不变。内部布局这次按 420 像素的手机视口做了核对,固定五列的形态选择和不可换行的测试结果行,在这种宽度下会被挤破。现在形态选择自动换行,结果文案允许折行。测试会在这个宽度下分别打开两个抽屉,断言零水平溢出。
v0.25.0
v0.25.0 gives the desk companion a recall system. It stops wandering into your reading and comes only when called.
Free roaming now stays in the map rail. The companion used to drift through all three panes, and when it settled over the middle or right pane it sat on top of the text you were reading. The new contract inverts that default. Unsupervised flight happens only over the left map, among the lesson balls. The other two panes are visited on summons. Focusing the input box calls it over to keep you company while typing, voice-mode dictation does the same for hold-to-talk, lesson read-aloud brings it to point at the sentence being spoken, and marking a note calls it beside the line you drew. When the work ends it waits out a three-and-a-half-second debounce and flies home. On a phone, where the map pane is usually off screen, home is the left screen edge with half of it peeking in from outside, so the same rules work unchanged.
Dragging no longer snaps back. Grabbing the companion and throwing it was always possible. What was broken was the landing. Release set its glide target to the old physics coordinate from before the drag, so it visibly slid back to where it started. The physics body now syncs to the drop point at release, and the onward journey, to whatever duty called or back home, is a rate-limited glide with a dedicated homing cruise tier. Slower than rushing to duty, faster than idling. It reads as flight with a pace, without the teleport feel.
Correct answers and unlocks summon it too. Answer a quiz card right, rate yourself as remembering in review, or unlock a map node, and the companion flies to the source and celebrates beside it for about three seconds before heading home. Wrong answers keep their local soft red flash and summon nothing. During an exam it holds its quiet perch next to the timer, undisturbed by any of this.
Bad coordinates no longer bait it off screen. Testing exposed two holes. An unlock event sometimes fired before the lesson ball had a real position on screen, and the companion would dash toward a negative coordinate near the screen edge for three seconds. An anchor is now carried only when the ball is genuinely inside the viewport. And when a celebration's position cannot be attributed to any pane, the companion does not guess a destination. It simply does not come.
v0.25.0 给桌宠装上了召回制。它不再游进你的阅读,有事才来。
自由游走只发生在左栏地图。 伴学以前在三栏之间乱逛,停在中栏或右栏时就趴在你正在读的文字上。新契约把这个默认翻了过来。无人召唤的飞行只在左侧地图的课程球之间发生,另外两栏都要召唤才到。聚焦输入框,它飞来陪你打字。听写的语音模式同样算召唤,它就悬在按住说话的卡片旁。整课朗读时它跟句指向正在读的那一句,划线记笔记则落到你画的那条线旁边。事情做完,它等三秒半的防抖再飞回家。手机上地图栏通常不在屏内,家就设在屏幕左缘,半个身子从外面探进来,同一套规则不用改。
拖拽不再弹回原点。 抓起来扔出去一直可以,坏的是落点。松手后滑翔目标还是拖拽前的旧物理坐标,眼看着滑回出发的地方。现在松手瞬间物理刚体同步到落点,接下来的飞行,无论是赶去职责锚还是回家,都是限速滑翔,回家专设一档巡航速度,比赶场慢,比闲逛快。全程看得出飞行轨迹,没有瞬移感。
答对和解锁也会召它来。 题卡答对、复习自评里点了记得或很熟、地图节点解锁,伴学都会飞到事件源旁边庆祝三秒左右,然后回家。答错只有原地的一下柔红,不召唤。考试答题期间它守在计时条旁边的静栖位,这些庆祝都不会打扰它。
坏坐标不会再把它骗出屏幕。 测试里暴露出两个洞。解锁事件有时在课程球还没有真实屏幕位置时就发出,伴学会朝一个负坐标冲三秒。现在球真正进了视口才携带锚点。庆祝的落点归属不到任何一栏时,它也不猜,干脆不来。
v0.24.0
v0.24.0 fixes a class of broken e-book imports and puts the version number where you can always find it.
Publisher-style e-books now import whole. A reader handed us a real commercial EPUB, a Chinese translation of Marcus Aurelius from a Shanghai publisher, and the course it produced was broken in three ways. Chapters without titles received invented names like Chapter 5, numbers that appear nowhere in a book organized into twelve parts. Each part had been split by the publisher into a short title page carrying the part name and a separate body file with no heading at all. And the copyright page plus a link-only table of contents had become lessons of their own.
The vanishing bodies deserve the explanation. A lesson's content is sliced from a single file, anchored at a heading. The AI that structures the course anchored each part to the titled file, which held only a hundred characters of epigraph. The untitled body file, wearing a fabricated name that matched nothing in the book, read as noise and was dropped. Twelve parts of Marcus Aurelius went into the course as epigraphs, and the actual text of the book never arrived. The repair works at the parsing layer, where the lies were born. Title pages now pair with the body file that follows them, epigraph and full text becoming one chapter. Files without titles are labeled honestly as unnamed, and the structuring AI names them from their content instead of trusting a number the parser made up. Copyright pages are caught by their catalogue-field fingerprint, runs of lines starting with book-title, author, ISBN fields, and link-heavy tables of contents by link density. A publisher's promo page carries no high-confidence signal, so it is left for the AI to judge rather than guessed at by rules. The sample book went from 27 broken chapters to 13 correct ones, every part carrying its epigraph and complete body, verified end to end through the real AI.
Old imports clean up safely. Re-importing the same file on the new version cannot read the old snapshot even if it survives, because the import identity is a hash of what the parser produces, and the new parser produces something different. Deleting the old course removes its snapshot outright.
The version number lives in Settings now. An About group at the bottom of the settings page shows the exact build you are running, taken from the build itself, and clicking it opens the releases page to see what changed.
v0.24.0 修复了一类坏掉的电子书导入,并让版本号随时找得到。
出版社式电子书现在能完整导入。 一位读者给了我们一本真实的商业 EPUB,上海译文版的《沉思录》,它生成的课程坏在三处。没有标题的章被安上了"第 5 章"这样的发明名,而这本书的体系是十二卷,书中任何地方都找不到这些编号。出版社把每一卷拆成两个文件,短的扉页带着卷名,随后的正文文件完全没有标题。版权页和一个纯链接的目录页也各自成了一课。
正文为什么会消失,值得讲清楚。 每课的正文从单个文件按标题切片。负责结构化的 AI 把每卷的课锚在带标题的扉页文件上,而那个文件只有一百来字的格言。没有标题的正文文件顶着一个与书毫无关系的假名,在 AI 眼里像噪声,就被丢掉了。于是十二卷沉思录进课程的全是格言,这本书真正的正文从未到达。修复做在解析层,谎话出生的地方。扉页现在与紧随的正文文件配对,格言和全文合成一章。无标题的文件诚实地标注为未命名,由结构化 AI 按内容命名,而不是去相信解析器编出的编号。版权页按著录字段指纹识别,连续多行以书名、作者、ISBN 这类字段开头的版式,链接密集的目录页按链接占比识别。出版社宣传页没有高置信信号,留给 AI 判断,不用规则去猜。样本书从 27 个坏章变成 13 个正确的章,每一卷带着格言和完整正文,经真实 AI 端到端验证。
旧导入可以放心清理。 新版本上重导同一文件,即使旧快照还在也不会被读到,因为导入身份是解析产物的哈希,新解析器的产物已经不同。删除旧课程则会连快照一起清掉。
版本号现在就在设置页里。 设置页底部新增"关于"分组,显示正在运行的确切构建版本,点一下打开 releases 页,看这一版改了什么。
v0.23.1
v0.23.1 is about trusting what you import. Five parsing paths got hardened this round, and every fix came from feeding real documents, real books, real subtitles and real slide decks through the pipeline and measuring what fell out.
E-book chapters land where they belong. The e-book parser assumed one spine file equals one chapter. Eight real Gutenberg books said otherwise, five of them packed many chapters into single files, and chapter numbers were often plain text lines rather than headings. Titles came from a stray table-of-contents label, content started at the first real chapter, and the AI invented numbering like "Chapter 3" for books that never had any. Chapters now split on real marks with sequence checks, a Pride and Prejudice import of 61 chapters across 15 files comes out as lessons that match their headings one to one, and the structuring AI is told plainly that a book without numbered chapters must not get numbers invented for it.
Chinese PDFs stop speaking in radicals. The PDF engine emitted Kangxi radical block codepoints for Chinese text, so 手 turned into ⼿ and search, highlighting and read-aloud could not match a single word. One real machine-learning textbook carried 23,559 of these characters. Extracted text now normalizes character by character at both engine exits, and scanned PDFs without a text layer return an honest empty result instead of garbage.
Web articles lose the furniture and keep the author. Scraped articles used to drag site templates into the course, a return-home line here, sidebar headings there, bare image paths at the end. The rules now delete only cross-article machine fingerprints. Whether a trailing promotional paragraph belongs to the author is a semantic question, and it goes to the AI that designs the course. That boundary was learned the hard way, an early rule ate a CSDN author's own closing paragraph and a reverse-guard test now keeps that from coming back.
Subtitles stop stuttering. YouTube auto-captions repeat each line across a rolling window of cues, the old adjacent-only dedup missed the pattern, and every sentence came out twice. Chinese transcripts were joined with a space between every line, 78 and 262 hits in two real transcripts. And when yt-dlp saved several languages, alphabetical order meant English always won over Chinese. All three are fixed, along with entity decoding and machine markers like [Music].
PowerPoint tables come back. The parser walked paragraphs, images and notes, then silently dropped table nodes whole, so a real three-slide deck full of tables yielded three bare headings and nothing else. Tables now render as proper markdown tables with pipes escaped, and placeholder tables that were never filled in are skipped instead of littering the course with empty rows.
The tests grew teeth. Real arXiv papers and web articles now flow through the entire pipeline into the database inside CI, behind flags that degrade honestly when no API key or network is present. Four new corpus suites replay six to twelve real samples per format, from Chinese textbooks to subtitled courses to pathological PowerPoint files, and every fix in this release carries a recorded break-test, break the code on purpose, watch the test go red, restore, watch it go green again.
The seed course also got a content pass, six lessons whose wording had drifted behind the product were rewritten in both languages.
v0.23.1 讲的是让你敢信导入进来的东西。五条解析路径这轮全部加固,每个修法都来自把真实的文档、真书、真字幕、真课件灌进管线,量出哪里掉了东西。
电子书的章节回到自己的位置上。 解析器过去假设一个 spine 文件等于一章。八本 Gutenberg 真书说事情没有这么整齐,其中五本把许多章塞在单个文件里,章号还常常是裸文本行而非标题。于是标题取自歪掉的目录标签,内容从真正的第一章开始,而对没有编号体系的书,AI 会编造「第 3 章」这样的序号。现在章节按真实标记切分并做序列校验,傲慢与偏见 15 个文件里的 61 章导入后课课与标题对齐,负责结构化的 AI 也被明确告知,原书没有编号就不许发明编号。
中文 PDF 不再满纸部首。 PDF 引擎对中文文本输出康熙部首区的码点,「手」变成「⼿」,检索、画线、朗读一个字都配不上。一本真实的机器学习教材里数出 23,559 个这样的字符。现在提取文本在两个引擎出口逐字符归一,没有文本层的扫描件则诚实返回空,不再产出垃圾。
网页文章去掉家具,留住作者。 抓取的文章过去会把站点模板拖进课程,这边一条返回首页,那边几行侧栏标题,结尾挂着裸图路径。规则现在只删跨文章稳定的机器指纹。尾部那段推广是不是作者自己写的,这是语义问题,交给设计课程的 AI 判断。这条边界是付了学费才学会的,早期一条规则吃掉过 CSDN 作者亲手写的收尾段,现在有一个反向守卫测试锁住,不许它回来。
字幕不再口吃。 YouTube 自动字幕会在滚动窗口里逐条复述,旧的相邻去重挡不住这个结构,成文里每句话出现两遍。中文转写逐句拼接时每行之间塞一个空格,两份真实转写稿里数出 78 处和 262 处。yt-dlp 落下多种语言时,字母序让英文永远压过中文。三处都已修好,顺带把实体解码和 [Music] 这类机器标记处理干净。
PPT 表格起死回生。 解析器会走段落、图片和备注,然后把表格节点整个丢掉,一份装满表格的三页真课件只产出三个光秃秃的标题。表格现在渲染成规范的 markdown 表格,竖线做转义,从未填过内容的占位空表则整张跳过,不给课程留一地空行。
测试长出了牙。 真实的 arXiv 论文和网页文章现在会在 CI 里走完整管线一路落库,无 key 或无网络时按档位诚实降级。四个新的语料套件按格式各回放六到十二个真样本,从中文教材到带字幕的课程再到病理课件。本版每个修复都带着录在提交记录里的破坏验证,故意改坏代码,看测试变红,还原,再看它变绿。
种子课程也做了一遍内容核对,六课落在产品后面的过时表述用两种语言重写了。
v0.23.0
v0.23.0 turns conversations into async sessions. While the AI is still thinking, you can jump to another node, start a fresh conversation there, and come back later to find the first answer finished and sitting in its own place. Phone users found the crash first, but the same wound bled on desktop too.
Streaming now belongs to the thread, not the screen. The streaming events used to carry no thread identity, and a single global flag said an answer was in progress. Switch nodes mid-answer and the two conversations bled into each other, the finish event rewrote message ids in the wrong thread, and the composer in the new node stayed locked until you reloaded. Each thread now keeps its own bucket of streaming state, events route by thread id, and buckets holding answers still in flight are never evicted from the cache, so coming back restores the half-written answer exactly as it was.
The old switch lock is gone because the disease is cured. Blocking node switches during streaming was a bandage over a routing bug. Now you can switch nodes, threads, or create new conversations while an answer is running. The same thread still refuses a second send until its current answer finishes, which keeps the stop button honest. Across threads, send freely; two nodes can stream at the same time.
You can watch it happen. A spinner sits on the tab of any thread that is still answering, the map node it belongs to wears a small spinner at its corner, and the map banner now says the AI is answering in the background and you are free to move around.
The phone menus are readable again. On touch screens, opening the effort or model picker squeezed every menu item into a forty-four pixel sliver, because the touch stylesheet written for toolbar icons also hit the menu items that live inside the toolbar. The rule now steps around menu items on purpose, and the model and context popovers learned to respect narrow viewports as well.
v0.23.0 把对话改成了异步会话。AI 还在想的时候,你可以跳去别的节点,在那里开一段新对话,晚点回来,第一个回答已经写完,待在它自己的位置上。这个问题是手机用户先撞见的,桌面端其实同病。
流式输出现在记在会话名下,视图只是观察窗口。 过去流式事件不携带会话身份,一个全局开关声明「有回答正在进行」。回答中途切节点,两段对话就互相渗血,收尾事件把消息 id 换错线程,新节点的输入框一直锁到刷新为止。现在每个会话各持一只流式状态桶,事件按会话 id 分流,装着未完成回答的桶永不淘汰,回到原会话时,写了一半的回答原样恢复。
切换锁拆掉了,因为病根治好了。 流式期间禁止切节点,原本是盖在路由错误上的创可贴。现在回答进行中,切节点、切会话、新建会话都随意。同一段会话在一个回答跑完之前仍拒绝第二条发送,停止按钮因此保持诚实。跨会话随便发,两个节点可以同时流式。
看得见它在跑。 还在回答的会话,标签上有一颗转圈;它所属的地图球,右上角挂一颗小转圈;地图提示条也改成「AI 正在后台回答,可随意切换节点」。
手机上的菜单恢复正常了。 触屏上打开思考强度或模型菜单,每个菜单项被挤成四十四像素的窄条,因为给工具栏图标写的触屏样式,同样打在了住在工具栏里的菜单项上。这条规则现在明确绕开菜单项,模型菜单和上下文弹层也学会了尊重窄视口。
v0.22.1
v0.22.1 is a polish and hardening round. The companion gets a clearer thinking pose, formula fonts render with the right typeface again, startup loads noticeably less, and every high-severity dependency advisory in the production tree is cleared.
The companion now rests its chin when thinking. While the AI is writing a streaming answer, the companion used to tilt its whole body by a few degrees, and floating in mid-air that tilt read like it had drifted off course. It now props its chin on one hand with a slow, small head sway, body level, hover animation untouched. The "right here" gesture it makes at your friction spots uses the same pose. The banking lean it does while flying keeps its old meaning, so the two no longer mix.
Formula fonts are back to the math typeface. A missing font-src entry in the content security policy was quietly blocking the fonts KaTeX bundles into its CSS. Formulas still rendered, but in a system serif instead, on desktop and in phone web mode alike. The policy now allows those inline fonts, and a regression test locks this together with the older inline-image rule.
Startup loads about 30% less. The renderer entry chunk went from 397KB to 276KB gzipped. Screens you will not open at launch, such as settings, exams, course search, mind maps, and the blackboard canvas, now load the first time you open them. The math rendering stack, the single heaviest library in the entry, only loads for content that actually contains formulas. The always-on companion, the interface dictionary, and the base markdown pipeline stay resident as before, and the phone web mode benefits from the same diet.
Dependency advisories cleared. All four high-severity findings in the production dependency tree are fixed without a single breaking upgrade, covering drizzle-orm, undici, and the PDF engine bundled inside the document parser. A handful of low-severity findings remain upstream in the AI SDK line this project is locked to, and they will follow once upstream ships the fix.
v0.22.1 是一轮打磨与加固。伴学想事情的样子更清楚了,公式的字形修好了,启动少加载三成,生产依赖里的高危通告全部清零。
思考改托腮。 AI 流式回答期间,伴学原来是整机歪头五度,悬浮在半空时这个角度看着像飞歪了。现在换成一只手托住下巴,头部缓缓小幅摆动,身体保持水平,悬浮浮动照旧。它指着卡点说「就是这里」时也用同一个姿势。飞行动作的倾侧保留原义,两种姿态不再混在一起。
公式字体恢复原样。 安全策略里缺了 font-src 一项,KaTeX 随 CSS 打包的内联字体一直被静默拦下。公式照常显示,只是字形退成了系统衬线体,桌面和手机网页模式都一样。现在放行了这些内联字体,回归测试把这条和更早的内联图片规则一起锁死。
启动少加载三成。 渲染层入口从 gzip 397KB 降到 276KB。设置、考试、课程搜索、脑图、黑板画布这些启动时还用不到的界面,改成第一次打开时才加载。数学渲染那套库是入口里最重的一件,现在只有内容里真有公式才会去拉。常驻的伴学、界面词典和基础 markdown 管线照旧不动,手机网页模式同样受益。
依赖通告清零。 生产依赖树的四条 high 全部修掉,没有一次破坏性升级,涉及 drizzle-orm、undici 和文档解析器内嵌的 PDF 引擎。剩下的几条 low 都在项目锁定的 AI SDK 上游,等上游修复后跟进。
v0.22.0
Two things ship in v0.22.0. The study companion gets a new face, and a small but stubborn text-selection problem finally gets a proper fix.
Vertical-line eyes. Every companion form now wears EVE-style vertical bar eyes across all expressions. Emotion is drawn by the bars themselves. Normal is a pair of steady lines, surprise stretches them long and thin, thinking goes asymmetric with a short left and a long right, listening shortens them a little, and sleeping leaves two faint dots. The two transformations you would expect are here too. Happy bends the bars into ^^ arcs, and the sulking huff rotates them flat into --. The eyes also follow your mouse now, with the whole eye sliding rather than a tiny pupil, and a blink squashes the bars into dots. Blink, mouth shapes, and the typing animation all kept working unchanged. The old rounded-rectangle eyes are retired.
Selection buttons wait for you to let go. While you were still dragging a selection, the ask-about-this-text and add-note buttons used to pop up beside it, and the pointer could run straight into them, which broke or jumped the selection mid-drag. They now stay hidden through the whole drag. On desktop the button lands beside the last character the moment you release the mouse. On phones, where a selection is usually adjusted by dragging the handles, the button waits for the handles to stop moving, and it anchors below the selection, away from both handles and away from the native copy and share menu. The button group is locked to a single line, grows to a 44px touch target on phones, and stays compact on desktop.
这次发两样东西。伴学伙伴换了新眼睛,一个拖选的老毛病也终于修利索了。
竖线眼。 五个形态的全部表情统一成竖线眼,走 EVE 那种冷萌路线。情绪直接画在两根棒上。常态是两根安静的竖线,惊讶拉长收细,思考左短右长不对称,聆听微微收短,睡觉剩两粒淡淡的点。该变的两种也都在,开心时竖棒弯成 ^^,鼓脸余怒时旋横成 --。眼睛还会跟着鼠标走,整只眼平移,不再只是小瞳孔挪动,眨眼时竖棒压扁成小点。眨眼、口型、打字反馈这些既有动画全部照常,旧的圆角矩形眼睛退役。
拖选按钮等你松手。 以前选字的途中按钮就浮出来,指针向右多拖几个字容易撞上它,选区会被卡断或者跳位。现在拖选和调整选区的整个过程按钮一律隐藏。桌面端鼠标一松,按钮立刻落在最后一个字旁边。手机上通常要拖手柄调整选区,按钮等手柄停稳才出现,而且锚在选区下方,避开两端手柄,也避开系统自带的复制菜单。按钮固定单行不换行,触屏端放大到 44px 手指好按,桌面端维持紧凑。
v0.21.0
v0.21.0 · Clearer study artifacts
This release changes how things look when you learn. Concept maps get a real layout engine, code gets syntax colors everywhere, AI flowcharts get cleaner routing, and every lesson can fold into a mind map.
Concept maps, rebuilt
The concept map artifact now runs on elkjs, the same Eclipse Layout Kernel family draw.io uses, loaded on demand. The AI can declare groups, and each group draws as a titled container box. Edges route orthogonally, right-angle lines that bend around boxes. The palette follows the draw.io convention, light fill with deep stroke in five hues, and the dark theme keeps the hue while inverting brightness. When the AI sends no groups, adjacency clustering draws them anyway, so a dense map still comes out gathered. The layout is deterministic, nodes never overlap, and the test suite asserts every edge endpoint lands on a node border.
Code, highlighted everywhere
Lesson text, chat messages and code walkthroughs all render with shiki now. Thirty-five common languages ship, with alias handling so js, py, sh and yml all resolve. The engine is pure JavaScript with no WASM, everything loads lazily, and the main bundle did not grow. Both themes are written into the same HTML as CSS variables in one pass. Switching theme flips the variables, no re-highlight, no flicker. An unknown language falls back to plain text.
Flowcharts on ELK
AI-drawn flowcharts lay out with ELK too. The rewrite happens only at render time, so the AI prompts and the syntax repair loop keep speaking plain flowchart. Sequence and state diagrams are untouched. One cost deserves mention. The official mermaid ELK adapter inlines its own copy of elkjs 0.9, which cannot be deduped with the 0.12 the concept map uses. Both copies sit in lazy chunks that load once, and a new build-manifest suite asserts neither ever reaches the entry bundle.
Mind maps
A brain button sits next to the read-aloud button in every lesson. One click folds the lesson's headings and lists into a collapsible mind map, on the same canvas engine the blackboard uses. Drag to pan, scroll or pinch to zoom, double-click to fit. Code blocks fold into a placeholder node, because a structure overview has no use for their content. Another click returns to the full text.
Diagram syntax repair
When the AI slips a syntax error into a mermaid diagram, the app sends the parse error back for one targeted repair pass and re-renders on success. A failed repair keeps the source-code fallback, so a broken diagram never turns into a blank card. The drawing prompt also gained a diagram-type guide and a label quoting rule, which prevents most of these errors before they happen.
All 106 deterministic suites, both typechecks, lint, the new build-manifest assertions and the real-GUI regression pass are green.
v0.21.0 · 看得清
这个版本改的是产物的长相。概念图换了真正的布局引擎,代码到处有语法配色,AI 画的流程图连线更守规矩,每节课还能一键折成思维导图。
概念图重做
概念图改用 elkjs 布局,和 draw.io 新版同一个内核家族,按需加载。AI 可以声明分组,每组画成带标题栏的容器盒。连线走正交路由,直角折线绕开盒子。配色沿用 draw.io 的习惯,浅填充配深描边共五色,暗色主题保持色相只反转明度。AI 没给分组时,按邻接关系兜底聚类,密集的关系图也能收拢成型。布局是确定性的,节点两两不重叠,测试套件连边端点必须落在节点边界上都逐条断言过。
代码到处高亮
讲解、对话、代码逐段讲解都接了 shiki,精选 35 门常用语言,别名归一,js、py、sh、yml 这些写法都认。引擎是纯 JavaScript,没有 WASM,全部懒加载,主束体积没有增加。暗亮两套颜色一次性写进同一份 HTML,切主题只翻转 CSS 变量,不重跑高亮,也就没有闪烁。不认识的语言老老实实退回纯文本。
流程图换 ELK
AI 画的流程图同样换 ELK 布局。改写只发生在渲染层,出题提示词和语法修复回路继续说原版 flowchart 方言,时序图状态图一概不动。有一处代价要交代。mermaid 官方的 ELK 适配包发布时把 elkjs 0.9 整个内联了,和概念图用的 0.12 无法去重。两份都待在懒 chunk 里,首次用到才加载一次,新增的构建清单套件断言它们永远不会进主束。
思维导图
每节课的朗读按钮旁边多了一个脑图按钮。点一下,这节课的标题和列表折成可收拢的思维导图,画布和黑板同款,拖拽平移,滚轮或双指缩放,双击适屏。代码块折成一个代码块占位节点,结构概览用不着它的内容。再点一下回到全文。
图的语法自愈
AI 偶尔把 mermaid 语法写滑丝。现在渲染失败会把解析错误带回去定点修一轮,只修语法不重画,修好自动重渲,修不好保留源码兜底,不会白屏。出题侧同时加了图类型选型指南和标签引号规则,防患在修复之前。
106 套确定性测试、两套类型检查、lint、新增的构建清单断言和真界面回归全绿。
v0.20.0
This version gives formula-heavy PDFs a way in.
Math formulas already render, speak, and quiz fine since v0.19. What was still broken was the source. A math PDF imported through the text layer arrives with mangled formulas, because the text layer of a PDF never had the formula in readable form to begin with.
This version adds an experimental switch. When it's on, importing a PDF scans each page's text for math signals, renders the math-dense pages to images, and has your vision model transcribe them into LaTeX. Those pages enter the course as real formulas, and the rest of the book keeps the fast text path. Folder imports and arXiv links both go through it.
The switch is off by default and needs a vision model configured in settings. Transcription spends that model's quota page by page, so it only touches pages where math is actually dense. Any failure, a page that won't render, a model that won't answer, a platform without the canvas binary such as Termux, falls back to the plain text layer with a note in the progress log, never a silent drop. Re-importing the same PDF doesn't call the model again, since results are cached per page.
The page renderer is a prebuilt native canvas module, so there is nothing new to compile. A new deterministic test suite guards the chain, and a live test runs a real vision model through it end to end.
这个版本解决的是公式密集 PDF 的入口问题。
数学公式从 v0.19 起显示、朗读、做题都顺了,卡住的是源头。数学 PDF 走文本层导入,公式进来就是乱的,因为 PDF 的文本层里本来就没有可读的公式。
这版加了一个实验开关。打开后,导入 PDF 会逐页扫文本层的数学信号,把公式密集的页整页渲染成图,交给你的视觉模型转写成 LaTeX。这些页以真公式的样子进课程,其余页面继续走快的文本路径。文件夹导入和 arXiv 链接都接了这条路。
开关默认关,要在设置里配好视觉模型才生效。转写按页消耗模型额度,所以只碰公式真正密集的页。任何一步失败,某一页渲染不出来,模型不回答,平台没有 canvas 预编译比如 Termux,都会退回纯文本层,进度日志里写明原因,不悄悄丢页。同一个 PDF 重复导入不再调模型,结果按页缓存。
整页渲染用的是预编译的原生 canvas 模块,没有新的编译负担。从检测到转写的每一步都有新的确定性测试套件守着,还有一个跑真视觉模型的 live 测试从端到端验证过。
v0.19.0
Highlights
Math formulas, end to end. LaTeX in lessons, tutor replies, and quiz questions now renders as typeset math (KaTeX). Read-aloud speaks formulas in words instead of backslash commands, so $\frac{a}{b}$ is heard as "a 分之 b". The exercise and exam generators are told they may use LaTeX freely. Underlining and sentence highlighting keep working on formula-heavy lessons, and math that KaTeX can't parse falls back to plain text instead of breaking the page. Saved webpages whose formulas were rendered by KaTeX or MathJax get their TeX recovered on import.
The bot sits quietly by the timer during exams. Start a chapter exam and the companion parks itself beside the countdown, no roaming, no physics, celebration moves silenced, just a small nod when you get one right. It leaves you alone and comes back when you hand in.
Per-question time limits are now dynamic and generous. The old 60/90 seconds flat is gone. The timer is computed from the question itself, reading pace plus options plus extra for code blocks and formulas, between 1 and 5 minutes. A 300-character question gets about 137 seconds, an 800-character one with code about 270.
Added
- Math rendering in the lesson pane and tutor chat (remark-math + rehype-katex, sanitized before rendering, literal fallback on parse errors).
- Spoken math for read-aloud across all four TTS engines and the system tier; a rule table covers fractions, roots, scripts, Greek letters, and common operators, unknown macros degrade letter by letter.
- Webpage import recovers KaTeX/MathJax formulas into
$..$notation instead of garbled text. - Exercise and exam prompts may emit LaTeX.
- Exam quiet perch for the companion, with celebrations, ball taps, whistles, and typing squashes muted during answering.
- Dynamic per-question exam time limit, clamped to 60-300 seconds; historical attempts are untouched.
亮点
数学公式从显示到朗读到做题都顺了。 课文、导师回答、题目里的 LaTeX 渲染成排版公式(KaTeX);朗读把公式念成人话,$\frac{a}{b}$ 听到的是"a 分之 b";出题与考试也放开了 LaTeX。画线和朗读跟句在公式密集的课文上照常工作,解析不了的公式退回原文显示,不炸整页。网页存档课里被 KaTeX/MathJax 渲染过的公式,导入时会把 TeX 原文回收回来。
考试时伴学安静地守在计时条旁。 开考后它钉在倒计时旁边,不漫游、不进物理世界,庆祝动作全部静默,答对只轻轻点个头。交卷即恢复日常。
每题限时改成动态计算,而且宽松了。 60/90 秒一刀切退役,按题干内容算,阅读速度加选项数,代码块和公式各加 25 秒,上下限 1 到 5 分钟。300 字的题约 137 秒,800 字带代码约 270 秒。
新增
- 讲解区与对话流的数学渲染(先消毒后渲染,解析失败退原文)。
- 四档朗读引擎加系统档的公式口语化,规则表覆盖分式、根号、上下标、希腊字母与常见算符,未覆盖记号逐字母降级。
- 网页导入回收 KaTeX/MathJax 公式。
- 出题提示词放开 LaTeX。
- 考试伴学静栖计时区,答题期间庆祝、点球、吹哨、击键压缩全静默。
- 每题限时动态计算,clamp(60,300) 秒,历史 attempt 零迁移。