Default desktop text files to Writer

Set LibreOffice Writer as the Desktop MIME default for Markdown and plain text while keeping Agent Zero Editor as the secondary Open With association. Update the Desktop DOX contract and extend the routing regression test to pin the Writer-first association order.

Alessandro committed Jul 3, 2026 at 01:08 UTC 306012eb00dd90108de7a3ceeb87e7c776b63933
3 files changed +15 -4
plugins/_desktop/AGENTS.md
+1 -1
@@ -17,7 +17,7 @@
17 - Keep desktop state injected into prompts accurate and bounded.
18 - Do not expose desktop routes without the expected auth protections.
19 - Keep Desktop host visibility tied to an attached modal or canvas host; modal cleanup may preserve the iframe in keepalive, but must not leave stale modal mode behind.
20 -- Keep Markdown and plain text file open-with handling routed to the Editor surface through the desktop intent bridge; Desktop owns the Xfce launcher/MIME setup, while Editor owns `.md` and `.txt` editing.
20 +- Keep LibreOffice Writer as the default handler for Markdown and plain text files; keep Agent Zero Editor available as a secondary Open With target through the desktop intent bridge.
21
22 ## Work Guidance
23
plugins/_desktop/helpers/desktop_session.py
+8 -3
@@ -79,6 +79,7 @@ URL_INTENT_MAX_ITEMS = 50
79 URL_INTENT_MAX_LENGTH = 8192
80 URL_HANDLER_DESKTOP_ID = "agent-zero-browser.desktop"
81 EDITOR_HANDLER_DESKTOP_ID = "agent-zero-editor.desktop"
82 +WRITER_HANDLER_DESKTOP_ID = "libreoffice-writer.desktop"
83 SHUTDOWN_HANDLER_DESKTOP_ID = "agent-zero-shutdown.desktop"
84 SHUTDOWN_PANEL_LAUNCHER_ID = SHUTDOWN_HANDLER_DESKTOP_ID
85 SHUTDOWN_CONFIRM_SECONDS = 8
@@ -2197,15 +2198,19 @@ def _editor_text_handler_mime_types() -> tuple[str, ...]:
2198
2199 def _write_mimeapps_defaults(path: Path, url_desktop_id: str, editor_desktop_id: str) -> None:
2200 url_associations = ";".join([url_desktop_id, ""])
2200 - editor_associations = ";".join([editor_desktop_id, ""])
2201 + # LibreOffice Writer stays the default so double-clicks keep the user (and
2202 + # agents) inside the Desktop; the Agent Zero Editor remains an "Open With"
2203 + # option. When Writer's desktop entry is missing, xdg falls back through
2204 + # the added associations to the editor.
2205 + text_associations = ";".join([WRITER_HANDLER_DESKTOP_ID, editor_desktop_id, ""])
2206 lines = [
2207 "[Default Applications]",
2208 *(f"{mime_type}={url_desktop_id}" for mime_type in _url_handler_mime_types()),
2204 - *(f"{mime_type}={editor_desktop_id}" for mime_type in _editor_text_handler_mime_types()),
2209 + *(f"{mime_type}={WRITER_HANDLER_DESKTOP_ID}" for mime_type in _editor_text_handler_mime_types()),
2210 "",
2211 "[Added Associations]",
2212 *(f"{mime_type}={url_associations}" for mime_type in _url_handler_mime_types()),
2208 - *(f"{mime_type}={editor_associations}" for mime_type in _editor_text_handler_mime_types()),
2213 + *(f"{mime_type}={text_associations}" for mime_type in _editor_text_handler_mime_types()),
2214 "",
2215 ]
2216 path.parent.mkdir(parents=True, exist_ok=True)
tests/test_office_canvas_setup.py
+6
@@ -608,6 +608,12 @@ def test_desktop_text_open_with_routes_to_editor_surface():
608 assert "handleEditorUrlIntent" in editor_store
609 assert 'openLatestSurface("editor"' in editor_store
610
611 + # Text files default to LibreOffice Writer inside the Desktop; the Agent
612 + # Zero Editor stays available as a secondary "Open With" association.
613 + assert 'WRITER_HANDLER_DESKTOP_ID = "libreoffice-writer.desktop"' in desktop_session
614 + assert "{mime_type}={WRITER_HANDLER_DESKTOP_ID}" in desktop_session
615 + assert "[WRITER_HANDLER_DESKTOP_ID, editor_desktop_id, " in desktop_session
616 +
617 # The browser surface must not claim a0-editor: intents, otherwise the
618 # editor "Open With" handler lands on an unloadable about:blank page.
619 assert "function isWebUrlIntent" in browser_store