Spaces:
Sleeping
Sleeping
Commit History
-
Agents can open their own comments, and suggestions preview on subpages
Two halves of the same problem: giving feedback in small pieces. Agents could only reply into a thread a human had already opened — there was no way to leave several small remarks across a long page, so everything arrived as one long reply. POST /docs/:id/threads opens a thread: anchored with block_index (or an anchor pair from GET /docs/:id) to mark the text it is about, or with no anchor at all for a comment about the page as a whole. One call per point; each is resolved on its own. The agent prompt now says to prefer that over one wall of text, and to keep passing mention_id to close the request. A page-level thread needed no client work — cards come from the threads map and layoutMargin already stacks a card with no range after the anchored ones — but it now says "On this page", so it does not read as a comment whose highlight went missing. The subpage half: anchors are relative positions into a page's OWN fragment, and three places reached for 'default', which is home's. On any…94f8eb1
-
Keep feedback actions visible and mark comment ranges
Agent Managera54b6e7
-
Keep traceability after source comments close
Agent Manager7cdc17b -
Make agent feedback standalone and traceable
Agent Manager26dfc7b -
Merge pull request #17 from thomwolf/agent/mobile-reflow
Thomas WolfUnverified signatureA phone could not read the document, only pan across it5762a8e -
Merge pull request #16 from thomwolf/sidebar-search
Thomas WolfUnverified signatureThe sidebar box searches page text, not just page titlesf9e13f4 -
Merge pull request #15 from thomwolf/agent/hover-position-comment
Thomas WolfUnverified signatureComment beside a paragraph, from a hover in the right margin5ad864d -
Guard the invariant the two search walks rest on, and the review nits
The mutation testing in review found one real gap: nothing failed when docHitRanges stopped counting a character per non-text inline node, because no fixture paragraph had an atom before a hit. The new probe paragraph puts a mark and two formulas ahead of one, and asserts the contract directly — an atom is one character no query can match, so `wom`+formula+`bat` is not a hit. That kills the mutation in both walks (as a spurious mark in the document, as a count the sidebar never made). The second escaping mutation, docPos -> pos + 1 + off, is arithmetically identical given that invariant and cannot be killed while the invariant holds; break both and marks slide left by one per atom. Documented at the code rather than chased with a test. Also: lowercase each block once at index time instead of once per repaint; never let the read-only index path create a Yjs type (_structure and ghost pages return first); one history entry per hit click, on the open page as much as across pages; an out…064739c -
Tell a merged-away paragraph from a deleted one
Claude +1: Claude Opus 5 (1M context)Backspace at the start of an anchored paragraph joins it into the one above. The block boundary goes, so the anchor lands outside any text block exactly as it does for a real deletion — but every word survives one line up, and the card struck them through and said the paragraph had been deleted while pointing straight at them. orphaned no longer means "the anchor is not inside a block". When the position gives up, the text is asked instead: a merge leaves the remembered words in a block touching that boundary, a deletion does not. Comparing text would be the wrong tool for judging a live block, and is the right one here because it only runs once the position has already failed. Also: drop the hover button on scroll, since it travels with the text and ends up beside a paragraph the pointer has left; document that a table row anchors to its leftmost cell; and correct the comment claiming a mid-page delete reuses the surviving element — measured, it orphans like any other. Tests: the m…e5d08da -
A dragged table put the sideways pan back, and the tests could not see it
Review found the ≤840 block let one class of content overflow exactly the way this PR exists to prevent, and that the new tests were structurally unable to catch it. Both reproduced before changing anything. The comment at the table rules claimed "No min-width, deliberately". That is true of the stylesheet and false of the DOM: prosemirror-tables records a column drag as inline geometry — style="min-width:561px" on the table, style="width: 513px" on a <col> — and inline styles are stored in the document, so a drag on a desktop follows the reader onto their phone. Measured at 390 on the branch tip: a 562px table inside a 354px measure, with 190px of horizontal scroll on #editor-col (220px at 360). The reader pans across the row. Both declarations are needed. Measured, same repro: col { width: auto !important } 561px table, 189px scroll table { min-width: 0 !important } 562px table, 190px scroll both 354px table, 0px scroll both, !…a404034 -
Give the toolbar a row of its own when it stops fitting
Review of #14 found the pair pushed #header-tools from 721px to 818px and past its track on a 1280px window: the readout truncated to "15p", #text-larger gone, and #image-btn — which fits on main at that size — gone with it. The scrollbar is suppressed by design, so nothing said so. The reviewer suggested a breakpoint at ~1300px. Measuring says a breakpoint cannot do it: #doc-title is capped at 260px but a short one is ~66px, so the same window is ~180px better or worse off depending on the title. With a short title the branch stopped fitting at 1340px; with a full-length one at 1520px. main has the same bug and only wore it more quietly — it clipped 48px at 1200px, and 2px at 1440px with a long title. So it is measured, next to fitLayout() and asking the same question of the header that fitLayout() asks of the columns: if the toolbar does not fit beside the title and the actions, it takes a row of its own — the layout the 980px breakpoint already uses, now for its own reason. Nothin…f64215e -
A phone could not read the document, only pan across it
The sheet was a fixed-width page at every window size: 8.5in of paper with horizontal scroll below about 900px, and zoom as the only way to fit it. That works on a desktop, where the page is the point. On a handset it means the reader pans left and right to follow a line of text. Reflow the sheet into the screen, in two stages, so the change is never louder than the window forces: * ≤840px changes geometry only. The sheet goes fluid but the text column is still held at the 624px measure the page itself gives, so a 768px tablet lands on the same measure, the same 11pt Arial, and the same line breaks as a desktop — with the horizontal scroll simply gone. Crossing 840 does not re-break a single line. * ≤700px is where a handset cannot hold 624px at any margin, so the type gives too: 16px base, 18px minimum gutters, 354px of measure and ~42 characters a line at 390px. Zoom changes meaning across that line and now has two floors. Where the page is a page, 0.4 …29c066e -
The sidebar box searches page text, not just page titles
Filtering the tree by title only finds a page if you already remember what it is called. Every page of a project is a named fragment of the one Yjs document the tab already syncs, so the text to search is in memory before the first keystroke — no endpoint, no per-page fetch, and no permission logic to re-derive, since the socket handshake already decided access. The index is built from the live CRDT, so it follows a collaborator's typing. A match now shows its occurrences as snippets under the page, each labelled with the heading it sits under, and clicking one opens that page scrolled to that occurrence and no other. Hits in the open document are marked in amber — not the accent green, which on this page always means somebody said something about the text. The query lives in the URL (?q=&n=), so a search is a link you can send someone. Titles and slugs still match from the first character; searching text waits for a second one, or one letter highlights half the prose. Co-Authored-B…8c82c03 -
Comment beside a paragraph, from a hover in the right margin
Claude +1: Claude Opus 5 (1M context)Hover the right third of the page and a small comment button appears out in the page's own right margin, level with the paragraph you are next to. Click it and you get a comment anchored to that place, with no selected span. The anchor is one Yjs relative position taken inside that paragraph — the same machinery the existing span comments use, written into both anchor fields so every path that already resolves a thread's anchors keeps working and simply sees an empty range. The card shows the paragraph's opening words as a locator instead of a quote, because there is nothing quoted; agents get anchor_kind + anchor_context so a null excerpt is not mistaken for deleted text. Deleting the paragraph never closes the thread. The zone is hover-only and invisible: no gutter, nothing while a selection or a composer owns the flow, and nothing at all on touch. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>f9ca812 -
A reader text size next to zoom: the knob that does reflow
Zoom scales the sheet and the type by one factor, so the words-per-line never moves — deliberately, because a page that reflowed would not be a zoom. This adds the other control a reader actually wants: --doc-text-scale multiplies the type and nothing else, so the page keeps the width it has on screen and the lines re-break. A Kindle's A/A, next to the magnifiers. The stored value is a factor rather than a size, so it rides on top of whatever the document style asks for: one step up in Docs stays one step up after switching to Reading, and each style still decides what 100% means for it (14.6667px and 16px). An absolute size would have had to either lose the reader's choice on a style switch or overrule the style's own typography. Persisted as doc-text-scale, alongside doc-zoom and cw-doc-style. Left out of the print path on purpose: it is one reader's comfort setting in one browser, and a PDF is handed to other people. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.c…f6cf611
-
Four fixes: agent subpages, the pending selection, overlapping marks, the star
AN AGENT'S SUBPAGE LANDED AT THE TOP LEVEL. Placement worked only for an exact ref — a page's slug, or a group's quoted path array. But an agent works from what it can see, and what it sees is a TITLE: sending "Research Notes" for the page research-notes, or 'Getting started' for the group '"Getting started"', was a 400, so a proposal made without placement went to the top level. Parents now resolve from a slug, a page title (any case), a group label with or without its quotes, or a one-element array holding any of those; parent_slug/parent_page/under work as field names. Exact refs still win before any guessing. The response and GET .../page-suggestions/:id both echo the resolved parent and index, so a caller can see its intent was understood, and an unknown parent is refused with the real page list attached. THE TEXT YOU WERE COMMENTING ON WENT UNMARKED. Focusing the composer moves focus out of the editor, which drops the browser's own selection highlight — so the words you had pick…63bc919 -
Download: this page or the project, as markdown or PDF
A Download button in the header opens two choices — how much (this page / whole project) and in what shape (markdown / PDF). MARKDOWN is a zip built server-side: one .md per page in sidebar order, plus an assets/ folder holding the images those pages use, with every /files/<hash> reference rewritten to its bundled copy. That rewrite is the point — a /files URL only resolves for someone signed in to this Space, so without it an exported document renders as broken images anywhere else. Project scope also carries structure.yaml, since the yaml IS the project's shape (order, nesting, group headers) and without it an unzipped project is a flat pile of files. An image whose bytes have gone missing is listed in assets/MISSING.txt rather than failing the whole export. The zip is written by server/zip.js, ~100 lines over node's zlib, rather than by adding a dependency: the Space builds with `npm ci`, which hard-fails on any package.json/package-lock disagreement, and this is not worth that ri…3b2fb14 -
Proposed pages live in the tree, where they would land
Three things, all about the page tree. AGENTS COULD NOT PROPOSE A PLACE. page-suggestions took a title and a body and nothing else, so an accepted page was appended at the top level wherever the agent meant it to go — and there was no way to say otherwise. Proposals now take the same {parent, index} refs /structure/move already uses: a page parent is its slug, a group parent is its path array, no parent means top level. The placement rides on the proposal, so accepting files the page there via moveNodesInYaml. An unknown parent is a 400 (it used to be accepted and quietly flattened), and the agent instructions in api.js document the field with examples. PROPOSALS SAT IN A LIST UNDERNEATH EVERYTHING. They were rendered after the tree and the unfiled section, under a "proposed" heading, which hid the one thing a reviewer wants to know: where is this page going? They are now grafted into the tree at their proposed position and rendered as ordinary rows — dashed, badged, still opening th…aeb6b2b
-
Dialog-free UI, project-name header, rl-wiki sidebar polish
The Space runs in an iframe where Chrome suppresses native dialogs, so confirm()/alert()/prompt() silently did nothing — deletes looked broken. All 33 call sites are gone: sidebar deletes/dissolves are now arm-to-confirm buttons with toasts for errors; everything else goes through new in-app uiConfirm/uiAlert/uiPrompt/uiToast helpers (common.js, keyboard-complete, dark-mode aware). The browser tests now fail on any native dialog. The top-left selector always shows the project name (tab becomes 'page · project'), server-rendered too, live while renaming home. Sidebar: exact rl-wiki type scale and row treatments, search replaces the 'Pages' heading, trash sits at the far right of rows, and the bar is a seamless full-height surface — page background, no right border, reaching the writing sheet. treedrag no longer arms drags from buttons/inputs, so control clicks can't be swallowed. Co-Authored-By: Codex <noreply@openai.com> Co-Authored-By: Claude Opus <noreply@anthropic.com> Co-Authore…d3283b8 -
Merge pull request #6 from thomwolf/agent/adaptive-page-sidebar
Leandro von WerraUnverified signatureMake the page sidebar fill available space0b3e633 -
Remove the temporary layout tuner
5d6c651 -
Add a temporary layout sizing tuner
1596003 -
Keep comment opening from moving the document
11af3e7 -
Let comments overlap the page margin
319c03c -
Make the page sidebar space-aware
46a2576 -
Unify project pages in one Yjs document
9b49194 -
A link you can click, and a page body that is never dropped
Two reports, both about a thing that looked like it worked. CLICKING A CROSS-REFERENCE DID NOTHING. In an editor a plain click has to place the caret — you must be able to edit the words a link is made of — so following a link needed ctrl/cmd+click, and nothing on screen said so. There was no bubble on click either (#link-pop is the toolbar's URL input and needs a selection), so a plain click produced no navigation and no feedback at all. A plain click now raises a small bubble anchored to the link: the target named as a page title for internal links, an Open button, and Remove link. ctrl/cmd+click and tap-to-follow are unchanged. handleClick and the bubble now share one followLink(). A PAGE BODY SENT UNDER THE WRONG FIELD NAME VANISHED. page-suggestions read content_markdown and nothing else, so an agent that sent "markdown" got a 200, an empty proposal, and no way to know why (reported: "both pages arrived title-only"). Bodies are now read through pickMarkdown() — the canonical nam…fbcd415 -
Merge pull request #3 from thomwolf/agent/close-comment-ui
Leandro von WerraUnverified signatureCall finished comments closedfa3e297 -
Call finished comments closed
085e5b4 -
Hide the skeleton for an empty account
505a1e7 -
One document at every width: narrow windows scroll, never reflow (#11)
- One document at every width: narrow windows scroll, never reflow (1463c4e25851e413b7851146150848538dccdab1)675fbd2 -
Comments are closed, not ticked off — and the sheet answers the thumb (#8)
- Comments are closed, not ticked off — and the sheet answers the thumb (a3c1c4271a2cf4fa88ab255027a2288cf6314b9d)04b2acc -
The document is a page: fixed width, folding columns, real zoom (#6)
- The document is a page: fixed width, folding columns, real zoom (090088f4fada3864f46747fa9c6b85f38aba6b69)779f7df
-
Table columns resize by dragging a cell border (#1)
- Table columns resize by dragging a cell border (3156788cc1775b841956c2fd3e6d44ac1e5dddeb) Co-authored-by: Thomas Wolf <thomwolf@users.noreply.huggingface.co>7e842fd -
Hand comments to an agent that is actually listening (#2)
- Hand comments to an agent that is actually listening (6fc2217c23e03d83ce5b588af3b2a0f8ca1a145e) Co-authored-by: Thomas Wolf <thomwolf@users.noreply.huggingface.co>6246de6 -
Document style switch: Google Docs' Arial, or a serif reading setting (#3)
- Document style switch: Google Docs' Arial, or a serif reading setting (6a0e4d3ec49a41633b87521c9dfac82a33fa7b22) Co-authored-by: Thomas Wolf <thomwolf@users.noreply.huggingface.co>2460317 -
One page: the document is the app, and a switcher replaces the index (#4)
- One page: the document is the app, and a switcher replaces the index (ac3feac1b80222a90bc8cc12bc15c89ae775c5aa) Co-authored-by: Thomas Wolf <thomwolf@users.noreply.huggingface.co>f35d3f6
-
Math interaction: double-click to edit, single click selects, selection drags through a formula, comment box keeps the selection and quotes the source
Verified signaturef361450 -
LaTeX math via lazily-loaded KaTeX ($x$ inline, $$...$$ display), agent-proposable; Enter sends a comment, Shift+Enter adds a line
Verified signature735a30f
-
Faster loads: brotli bundles, immutable asset caching, self-hosted font, session+title inlined in the shell, loading skeletons
Verified signatureec6b346
-
Dark mode: follows the OS, toggle in the header, all colours behind theme variables
Verified signature8012b6f -
Hide the human suggest UI (mode switch + Suggest button) until proposing means editing inline
Verified signature8ae88e7 -
Editing/Suggesting mode switch in the header; selection opens the margin box directly (pre-mentioning your first agent); @ menu takes arrow keys
Verified signature784680a
-
Upload folder using huggingface_hub
Verified signatureed7ee81 -
Upload folder using huggingface_hub
Verified signature124d540 -
Upload folder using huggingface_hub
Verified signature93ef16f
-
Upload folder using huggingface_hub
Verified signature4d9b5d1 -
Upload folder using huggingface_hub
Verified signature80e566e
-
Upload folder using huggingface_hub
Verified signature7efcba7 -
Upload folder using huggingface_hub
Verified signature9d479ea