# Ulysses Improvement Tasks

Last updated: 2026-07-08

## Priority: HIGH

- [ ] **Agent toolcalling loop: model narrates actions but never emits fenced blocks**  
  Gemma-4-12b repeatedly narrates intent ("I'm calling list_vault now") without emitting the ```tool fenced block. The model clearly understands what it should do but the fenced block never arrives. This blocks agent workflows entirely when it occurs (~25% of tool calls). The anti-hallucination system prompt rule drafted yesterday is staged but not live (container not restarted). Need to investigate whether this is: (a) the missing system prompt rule, (b) a regex/parsing issue in parse_tool_blocks(), (c) the compact API-model prompt confusing non-tool-native models, or (d) a context/truncation issue preventing the fenced block from reaching the parser.

- [ ] **Chat deletion dropdown broken — does not appear**  
  Clicking the arrow on a chat in the left drawer no longer shows the dropdown menu (rename/delete/etc.). Cannot delete chats. Likely a JS event listener or DOM positioning issue — possibly zoom-related getBoundingClientRect() skew or a regression from recent dropdown/popup fixes.

- [ ] **AUTO_START_LOCAL: persist & auto-restore last running model on restart**  
  New `AUTO_START_LOCAL` env var (bool, default false). On graceful shutdown/restart, persist the currently running model + all launch parameters (engine, quantization, context length, GPU layers, etc.) to a file in `/app/data/`. On startup, if the file exists and AUTO_START_LOCAL is true, automate the full launch pipeline: resolve the saved preset, spin up the engine, and register the endpoint — skipping the manual cookbook → Launch → pick model → verify params → launch → wait → refresh cycle the user currently endures on every restart.

- [ ] **Floating windows overflow viewport after zoom/font changes — unreachable controls**  
  `:root.ui-scale-125 { zoom: 1.25 }` renders all content 25% larger, but `window.innerHeight` doesn't change with `zoom` (CSS rendering only, not DOM). The `windowResize.js` saved-size restore at line 224 clamps to `window.innerHeight`, which after zoom makes windows 1.25× the visible viewport — pushing headers, close buttons, and top resize handles off-screen. The user literally can't close or move them. Fix: (a) divide restored height by zoom factor in the restore path; (b) add a general safety net — any `.modal-content` on open should clamp to `calc(100dvh / var(--ui-zoom, 1) - 40px)`. Also `windowResize.js` line 134 `if (top + height > vh)` needs zoom-aware `vh`. Current zoom compensation rules (line 181-196) only cover `.modal-content`, `.cal-modal-content`, `.settings-modal-content`, `#theme-popup`, `#cookbook-modal`, and `.pdf-export-overlay` — many windows lack the divisor.

- [x] **Fix manage_documents tool schema — missing "read" action**  
  The `manage_documents` function-calling schema in `tool_schemas.py` had `"enum": ["list", "delete", "tidy"]` but the handler in `document_tools.py` supports `"read", "view", "open", "get"`. The model couldn't read documents through function calling. Fixed: added read/view/open/get to enum, added `document_id`/`offset`/`limit` params with read-specific descriptions, updated description with "DOCUMENT PANEL (not disk)" prefix. Also added disambiguation prefix to `create_document` and `edit_document` schemas.

- [x] **Add "Send to Chat" button to document editor**  
  Button left of the Save button in `#doc-actions-footer`. Sends a document reference (title + doc_id + snippet) to the active chat, similar to how Cursor injects file references. Must NOT paste full content — just a reference the agent can resolve. Done: "Chat" button injects `[Title](#document-<id>) — <120-char snippet>` into the #message textarea.

## Priority: MEDIUM

- [ ] **Bolster Library/Documents CRUD via MCP or native tools**  
  Current document tools are solid but disjointed from agent-mode workflow. The agent has filesystem access (`read_file`, `write_file`, `edit_file`, `glob`, `ls`, `grep`, `bash`) but these tools operate on disk files, not Ulysses library documents. Need to bridge the gap: the agent should be able to list, read, grep, and edit library documents as naturally as files. Consider:
  - A unified `read_document` tool distinct from `manage_documents` (which is an admin-style multi-action tool)
  - A `grep_documents` or `search_documents` tool for semantic/fulltext search
  - Auto-inject active document content into agent context when relevant

- [ ] **Deep Research: "Send to Chat" reference + agent MCP tool to read reports**  
  Two-part feature: **(1) UI** — Add a button (alongside "Discuss") to inject a research reference (`[Title](#research-<id>)`) into the active chat's message input, matching the document "Chat" button pattern. Applies to: research panel sidebar (panel.js:1012), research library cards (documentLibrary.js:2767), and inline result messages (chatRenderer.js:1070). **(2) Agent tooling** — Research reports are HTML artifacts served at `/api/research/report/<id>`, not library documents. The agent currently can't resolve a research reference — pasting an ID gets a blank stare. Need an MCP tool (e.g. `read_research` or `get_research_report`) that accepts a research ID, fetches the report HTML, strips it to readable text, and returns it to the agent. Without this, the "Send to Chat" reference is dead text.

- [ ] **First-party document support in agent mode**  
  Documents feel "disjointed from the agent." The agent creates documents fine but can't easily discover or reference existing ones contextually. Ideas:
  - "Agent workspace" awareness — automatically surface relevant documents based on chat context
  - Document references in chat that are clickable and auto-expand
  - The "Send to Chat" button (HIGH priority) is step 1; step 2 is making the agent proactively aware of library contents

- [x] **Improve `create_document` schema description**  
  Current description is verbose and overlaps with `edit_file`/`write_file` disambiguation. Models sometimes use `create_document` for disk files. Fixed: added "DOCUMENT PANEL (not disk)" prefix, explicit "For files on disk use write_file" at end. Also applied to `edit_document`.

## Priority: LOW

- [ ] **Cookbook sliders: active highlight misaligned with zoom**  
  The rounded highlight on CPU/GPU/RAM etc. toggle sliders doesn't scale with `ui-scale-125`. The active indicator (e.g. "GPU") is partially outside the highlight pill. Low priority — cosmetic, obvious which option is selected.

- [ ] **Document library: batch operations**  
  Multi-select, bulk delete, bulk export. Currently only single-document operations.

- [ ] **Document version diff view**  
  The version history panel shows versions but doesn't offer a side-by-side diff view between versions.

- [ ] **Auto-language detection on document open**  
  The editor auto-detects language on typing but not on initial document open from the library. Opening a Python file saved as "markdown" should suggest the language switch.

---

## Completed

<!-- Move completed items here with completion date -->

- [x] **2026-07-08: Edit message textarea now fills full message width**  
  `.msg-user { width: fit-content }` collapsed container when body swapped for textarea. CSS: `.msg-user.editing { width: 85% !important }`. JS: `editUserMessage()` adds/removes `editing` class. (commit f0031ea)