Commit Graph
100 Commits
Author SHA1 Message Date
Afonso Coutinho edd5ea36ad Fix _parse_msg_content corrupting JSON-array-like text messages on reload (#2060)
_parse_msg_content deserializes stored multimodal content (image/audio
blocks) back into a list. It treated ANY string starting with '[{' and
containing the substring "type" as serialized content, requiring only
that each element be a dict — never that "type" be a real content-block
kind. So a plain text message whose content happens to be a JSON array
of typed objects (e.g. a user pasting an API schema sample like
[{"type": "object", ...}]) was silently parsed from str into a list on
the next hydration, destroying the original string. This runs on every
session load from the DB (_db_to_session -> get_session). Restrict the
round-trip to non-empty lists whose every element is a dict whose
"type" is a recognized block kind (text/image/image_url/audio/...);
real multimodal content (verified: document_processor emits exactly
these) still round-trips, JSON-looking text is left untouched.
2026-06-27 14:31:51 +01:00
Afonso Coutinho 24ace44888 fix: canvasCoords crashes on empty touch list (mobile race) (#2045) 2026-06-17 10:25:39 +02:00
Afonso Coutinho a36b423a4e Fix odysseus-calendar list dropping in-progress / multi-day events (#2065)
cmd_list filtered on the event START falling inside the window
(dtstart >= start AND dtstart < end). The canonical web route
(routes/calendar_routes.py) and the recurrence contract test use
OVERLAP semantics for non-recurring events: dtstart < end AND
dtend > start. So an event that began before the window but is still
ongoing inside it — e.g. a 09:00-17:00 conference listed at 14:00, or
any multi-day event spanning the window — was silently dropped by the
CLI even though the web UI shows it. Use overlap, matching the route.
dtend is NOT NULL in the schema, so no null-end regression.
2026-06-16 14:04:56 +02:00
Afonso Coutinho 7b09491557 fix: check-in calendar digest leaks every user's events (missing owner scope) (#1925)
* fix: check-in calendar digest leaks every user's events (no owner scope)

* Seed dtend on calendar events in digest test so the NOT NULL column is satisfied
2026-06-16 02:42:41 +01:00
Afonso Coutinho af61b2d4e6 test(research): cover complete status CLI alias
Adds focused regression coverage for the research CLI complete-to-done status alias.
2026-06-11 15:49:12 +03:00
Afonso Coutinho fbed9027b0 fix: backup import dropping a user's skill on cross-tenant title/id collision (#2057)
* Fix backup import dropping a user's skill on cross-tenant title/id collision

The skills block of import_data deduped incoming skills against
skills_manager.load_all(), which returns EVERY tenant's skills. So when
a user imports their own backup, any skill whose id or title collides
with another user's skill was silently skipped — the importing user
lost their own data. This is the same cross-tenant bug already fixed
for the memories block just above (#1743); the skills block was left
with the old pattern. Filter the dedup sets to the importing user's own
skills (owner == user); the full store is still saved back, preserving
other users' skills.

* Restore sys.modules after stubbing so backup test does not break collection of later src.* test modules

* Patch backup_routes auth helpers via monkeypatch instead of sys.modules stubs so the test is import-order robust

* Give FakeSkillsManager an add_skill method matching the disk-backed skills API
2026-06-09 08:04:22 +02:00
afonsopc 9be2862e4e Stub llm_core via monkeypatch.setitem so the cross-tenant test does not leak its fake into later test modules 2026-06-05 00:04:15 +01:00
afonsopc 1801ba9a0d Update degraded-vector dedup test for owner-scoped vector match 2026-06-04 23:45:13 +01:00
afonsopc 28b296a712 Fix auto-memory vector dedup dropping a user's fact on cross-tenant match
extract_and_store dedups each extracted fact against the vector store
before the (owner-scoped) text fallback. The vector store is a single
shared ChromaDB collection storing only {"source": "memory"} — no
owner — and find_similar queries it with no owner filter, so it can
return a memory_id belonging to a different tenant. The old code
continue'd (skipped storing) on any vector hit without checking
ownership, so when ChromaDB is healthy (the common path) a user's
freshly-extracted fact was silently dropped because it was merely
semantically similar to another user's memory — the text fallback that
IS owner-scoped never ran. Gate the skip on the matched memory being
this user's own (or legacy unowned), mirroring the text dedup predicate;
cross-tenant or stale matches fall through. Same bug class as #1743.
2026-06-04 23:45:13 +01:00
Afonso Coutinho baf9179d94 Fix truncate_messages persisting an inflated message_count (#2052)
truncate_messages deletes db_messages[keep_count:] (a no-op when
keep_count >= the real message total) then unconditionally wrote
db_session.message_count = keep_count. When keep_count exceeds the
number of messages that actually exist — e.g. the manage_session AI
tool defaults keep_count to 10, and the HTTP truncate endpoint passes
any client value — the persisted count is set too high (10 on a
3-message session), diverging from the real row count. That column
gates lazy DB-hydration in get_session (message_count > 0) and is
surfaced to the history UI, so it is correctness-relevant. Clamp to
min(keep_count, len(db_messages)); the in-memory slice already caps
naturally.
2026-06-04 21:19:16 +02:00
Afonso Coutinho ed933ac232 fix: renaming a user leaves their API tokens resolving to the old owner (#1932)
* fix: renaming a user leaves their API tokens resolving to the old owner

* Drive rename token-cache test through the real auth resolver instead of patching a closure
2026-06-04 20:37:59 +02:00
Afonso Coutinho abe04436a0 fix: merge-last-assistant deletes tool/system rows from the DB (history desync) (#1929) 2026-06-04 19:47:08 +02:00
Afonso Coutinho 09fe308720 fix(auth): revoke API tokens when deleting users
* fix: revoke API bearer tokens when their owner is deleted

* Re-run CI

* Invalidate bearer-token cache on user delete so warmed cached tokens stop working
2026-06-04 04:44:34 +01:00
Afonso Coutinho 49c14af5c7 fix(calendar): scope CalDAV event lookup by calendar
* fix: CalDAV sync hijacks another user's event sharing a VEVENT uid

* Seed schema-valid dtstart/dtend in caldav uid-scope test fixture
2026-06-04 04:01:21 +01:00
Afonso Coutinho 03dbf976a5 fix: image model ranking crashes on a non-string search filter (#1898) 2026-06-04 03:26:35 +01:00
Afonso Coutinho 5043b2924c fix: image model ranking crashes when system is not a dict (#1900) 2026-06-04 03:23:59 +01:00
Afonso Coutinho eac354629a fix: model cost/info matches first substring key (gpt-4o-mini billed as gpt-4o) (#1439)
* fix: match model name to the longest known key, not the first substring

* test: model key matching prefers the longest specific key
2026-06-04 03:05:37 +01:00
Afonso Coutinho b6607d219d fix(memory): owner-scope memory route session access 2026-06-03 23:13:56 +01:00
Afonso Coutinho fb8a744cae fix: skill retrieval boosts on tag substrings (e.g. 'ai' tag for any 'email' query) (#1406)
* fix: match skill tags as whole tokens, not substrings, in retrieval

* test: skill tag matching uses whole tokens, not substrings

* test: give skill fixtures status=published so they reach the scoring path
2026-06-03 14:24:11 +09:00
Afonso Coutinho f19265742c fix: SMTP envelope recipients split on commas inside display names (#1464) 2026-06-03 14:23:58 +09:00
Afonso Coutinho b55c970ec5 fix: sports-hint ranking penalty fires on 'transport'/'passport' substrings (#1473)
* fix: sports-hint ranking penalty fires on 'transport'/'passport' substrings

* Apply word-boundary sports-hint fix to src/search/ranking.py as well
2026-06-03 14:23:52 +09:00
Afonso Coutinho 0dd67143f1 fix: PDF attach uses lstrip(chars) that eats body text, not the marker helper (#1541) 2026-06-03 14:23:37 +09:00
Afonso Coutinho 6e1df4ddc6 fix: POST /api/contacts/add crashes on JSON null name/email (None.strip()) (#1544) 2026-06-03 14:23:34 +09:00
Afonso Coutinho f93755e7a4 fix: params_b crashes the whole ranking on a malformed parameter_count (#1550) 2026-06-03 14:23:30 +09:00
Afonso Coutinho 9bd11fd6e7 fix: Mixtral and Ministral models render with no provider logo (#1640) 2026-06-03 14:23:21 +09:00
Afonso Coutinho b45611e9c5 fix: _strip_reasoning_prose discards the answer when reasoning trails it (#1643) 2026-06-03 14:23:15 +09:00
Afonso Coutinho 3e33cf6439 Anchor shell-verb intent patterns to imperative or can-you position (#1664) 2026-06-03 14:23:10 +09:00
Afonso Coutinho 8a0b79bc84 fix: deep research runs the prompt's example queries when the model echoes them (#1666) 2026-06-03 14:23:07 +09:00
Afonso Coutinho 26d040d116 fix: gallery records raw instead of display dimensions for EXIF-rotated photos (#1667) 2026-06-03 14:23:04 +09:00
Afonso Coutinho b396252af6 fix: monthly tasks scheduled for day 29-31 skip every short month (#1668) 2026-06-03 14:23:01 +09:00
Afonso Coutinho 7f80d33210 fix: services research lists junk no-content pages as cited sources (#1669) 2026-06-03 14:22:58 +09:00
Afonso Coutinho eae8797e08 fix: web search content blocks numbered by fetch completion order break citations (#1672) 2026-06-03 14:22:55 +09:00
Afonso Coutinho fbb52a73a0 fix: re-importing an ICS file duplicates every tz-aware timed event (#1683) 2026-06-03 14:22:49 +09:00
Afonso Coutinho 1161040efe fix: visual report drops photos whose URL slug contains icon or logo (#1685) 2026-06-03 14:22:45 +09:00
Afonso Coutinho 3d00c85636 fix: hwfit native quant labels miss the cost maps and over-estimate VRAM (#1690) 2026-06-03 14:22:42 +09:00
Afonso Coutinho 96d59d2ff9 fix: _parse_dt does not understand 'tonight' so event start/end breaks (#1488) 2026-06-03 14:14:41 +09:00
Afonso Coutinho 33ae982968 fix: context_compactor token helpers crash on non-string message text (#1634)
* fix: context_compactor token helpers crash on non-string message text

* fix: _truncate_text_to_token_budget returns an empty string for non-string text, not the raw value
2026-06-03 14:12:14 +09:00
Afonso Coutinho 1453458519 fix: is_public_blocked_tool crashes on a truthy non-string tool name (#1620)
* fix: is_public_blocked_tool crashes on a truthy non-string tool name

* fix: is_public_blocked_tool fails closed (blocks) on a malformed non-string tool name
2026-06-03 14:11:14 +09:00
Afonso Coutinho 04f8aa1833 fix: _lookup_bandwidth crashes on a truthy non-string gpu_name (#1641) 2026-06-03 14:11:10 +09:00
Afonso Coutinho 1571d8bba0 fix: agent_tools._truncate crashes on non-string input (#1624)
* fix: agent_tools._truncate crashes on non-string input

* fix: agent_tools._truncate returns a string for non-string input, not the raw value
2026-06-03 14:06:39 +09:00
Afonso Coutinho 3a741edbf1 fix: visual_report markdown helpers crash on a non-string input (#1633) 2026-06-03 14:06:35 +09:00
Afonso Coutinho a54d34149a Parse standard Gmail quote attribution dates
Allow Gmail quote attribution parsing to handle standard US weekday/month/day/year comma patterns while preserving existing formats, with JS regression coverage.
2026-06-03 13:45:56 +09:00
Afonso Coutinho 46999debdb Decode email headers without injected spaces
Use email.header.make_header for MIME header decoding so adjacent encoded/plain header parts preserve RFC spacing, with regression coverage.
2026-06-03 13:45:33 +09:00
Afonso Coutinho f29c827e6e Merge search analytics defaults in services copy
Make services.search.analytics tolerate missing counters in older or partial analytics files by merging loaded data over defaults, with regression coverage.
2026-06-03 13:45:07 +09:00
Afonso Coutinho 10e797a1aa Normalize scheduled email offsets before storage
Normalize scheduled email send_at values with timezone offsets or Z suffixes to naive UTC before storing, matching the poller's lexicographic comparison format and preventing early/late sends.
2026-06-03 13:44:18 +09:00
Afonso Coutinho 28dbd5346c Treat non-string research summaries as low quality
Filter malformed non-string research summaries instead of letting the broad exception path classify them as usable, with regression coverage.
2026-06-03 13:42:24 +09:00
Afonso Coutinho a880b17624 Skip malformed personal keyword index rows
Make personal keyword retrieval tolerate corrupted non-dict index entries and missing chunk lists, with regression coverage.
2026-06-03 13:42:05 +09:00
Afonso Coutinho 13f0171ce8 fix: extract_youtube_id crashes on a non-string url instead of returning None (#1689) 2026-06-03 13:38:11 +09:00
Afonso Coutinho 35b9509da3 fix: memory entry validation crashes on a non-dict row from memory.json (#1691) 2026-06-03 13:38:02 +09:00
Afonso Coutinho f0b172020e fix: require_privilege 500s on a non-dict privileges blob from auth.json (#1693) 2026-06-03 13:37:54 +09:00
Afonso Coutinho 02ff2e3cb0 fix: updating a calendar event ignores user timezone and shifts the time (#1695) 2026-06-03 13:37:39 +09:00
Afonso Coutinho 667b739af4 fix: reply-all Cc builder crashes on a non-string To or Cc field (#1700) 2026-06-03 13:37:22 +09:00
Afonso Coutinho 19e62208d2 fix: streaming drops providers that emit SSE data lines with no space (#1701) 2026-06-03 13:37:14 +09:00
Afonso Coutinho 3da4edb442 fix: token usage dropped when it rides on a non-empty finish delta (#1703) 2026-06-03 13:36:57 +09:00
Afonso Coutinho 9dd9bb8a3f fix: memory recall crashes on a non-dict row from the vector store (#1705) 2026-06-03 13:35:09 +09:00
Afonso Coutinho 86d3af743a fix: docs RAG query crashes on a non-dict row from the index (#1706) 2026-06-03 13:35:01 +09:00
Afonso Coutinho 076607c9b9 fix: archive browser model filter is suffix-only and drops matching models (#1709) 2026-06-03 13:34:54 +09:00
Afonso Coutinho 56123e052b fix: compacting a chat with image attachments destroys the attachment (#1710) 2026-06-03 13:34:47 +09:00
Afonso Coutinho f6f86c4b34 fix: research source extraction crashes on a non-dict finding (#1714) 2026-06-03 13:34:40 +09:00
Afonso Coutinho 29e19f326a fix: _resolve_user_upload_path crashes on a non-dict resolve_upload result (#1715) 2026-06-03 13:34:33 +09:00
Afonso Coutinho 55c7a4a546 fix: computeSnap throws when ctx.otherLayers is not an array (#1716) 2026-06-03 13:34:25 +09:00
Afonso Coutinho ada30aa039 fix: evaluate_turn_regex crashes on a non-string agent_reply (#1723) 2026-06-03 13:31:26 +09:00
Afonso Coutinho 290d398900 fix: rewriting a message is lost on reload due to a non-existent DB column (#1729) 2026-06-03 13:31:19 +09:00
Afonso Coutinho d9e6071528 fix: odysseus-mail read crashes on an empty IMAP fetch payload (#1730) 2026-06-03 13:31:10 +09:00
Afonso Coutinho c5bc39de88 fix: _extract_entities crashes on a non-string query (#1724) 2026-06-03 13:30:28 +09:00
Afonso Coutinho 0c37943267 fix: search service crashes on a non-dict result row (#1725) 2026-06-03 13:30:19 +09:00
Afonso Coutinho 96a874c604 fix: a non-dict finding silently drops all raw research findings (#1739) 2026-06-03 13:29:29 +09:00
Afonso Coutinho 7f94c43a45 fix: langIcon throws on an explicit null opts argument (#1740) 2026-06-03 13:29:21 +09:00
Afonso Coutinho fc8efca49d fix: backup import drops a user's memory when its text matches another user's (#1743) 2026-06-03 13:29:14 +09:00
Afonso Coutinho 063e7114e3 fix: youtube transcript formatter crashes on a non-dict segment (#1745) 2026-06-03 13:29:08 +09:00
Afonso Coutinho 6e38d3f2ef fix: youtube (services) comment formatter crashes on a non-dict comment (#1746) 2026-06-03 13:29:01 +09:00
Afonso Coutinho 133948cc78 fix: uploads with _ or - in the extension become permanently unreadable (#1756) 2026-06-03 13:28:45 +09:00
Afonso Coutinho 992866e167 fix: document library language facet undercounts text documents (#1758) 2026-06-03 13:28:38 +09:00
Afonso Coutinho 51857c9008 fix: chat memory extraction crashes on a non-dict message (#1749) 2026-06-03 13:25:48 +09:00
Afonso Coutinho a714915afe fix: _derive_title crashes on non-string content instead of returning Untitled (#1751) 2026-06-03 13:25:41 +09:00
Afonso Coutinho 2fa4d50115 fix: is_youtube_url crashes on a non-string url (#1752) 2026-06-03 13:24:33 +09:00
Afonso Coutinho d2f6e8068d fix: is_youtube_url (services) crashes on a non-string url (#1753) 2026-06-03 13:24:24 +09:00
Afonso Coutinho b3da01efd5 fix: ui_control rejects the advertised rag toggle (#1763) 2026-06-03 13:24:00 +09:00
Afonso Coutinho c4fcebd9c7 fix: disabling auth wipes all users' preferences on next pref save (#1764) 2026-06-03 13:23:50 +09:00
Afonso Coutinho bde5f6adb3 fix: gallery tag filters and tag-cleanup are empty in single-user mode (#1771) 2026-06-03 13:23:08 +09:00
Afonso Coutinho d25a860f71 fix: document tidy crashes on a duplicate with NULL timestamps (#1772) 2026-06-03 13:23:01 +09:00
Afonso Coutinho db1596f3b4 fix: signature learning never skips support@/info@/admin@ senders (#1773) 2026-06-03 13:22:52 +09:00
Afonso Coutinho 694647375c fix: signature delimiter fold misses self-closing <br/> breaks (#1774) 2026-06-03 13:22:46 +09:00
Afonso Coutinho aa5e3f6884 fix: is_markitdown_format crashes on a non-string path (#1618) 2026-06-03 09:00:10 +09:00
Afonso Coutinho fc220f760f fix: inside_base_dir raises TypeError on a non-string path instead of failing closed (#1619) 2026-06-03 09:00:04 +09:00
Afonso Coutinho 2d94e38d23 fix: document_actions title/content helpers crash on non-string input (#1621) 2026-06-03 08:59:55 +09:00
Afonso Coutinho 03ddc5d2c4 fix: check_outbound_url crashes on a truthy non-string URL (#1623) 2026-06-03 08:59:49 +09:00
Afonso Coutinho 3175d7ca21 fix: tool-block parsing crashes on a non-string input (#1628) 2026-06-03 08:59:42 +09:00
Afonso Coutinho d818117d4c fix: _extract_skill_json crashes on a truthy non-string teacher response (#1630) 2026-06-03 08:59:36 +09:00
Afonso Coutinho 6b2618dab4 fix: logs CLI _resolve crashes on a non-string name (#1631) 2026-06-03 08:59:30 +09:00
Afonso Coutinho 0051023056 fix: skill test-task / precision helpers crash on a non-dict skill (#1638) 2026-06-03 08:59:24 +09:00
Afonso Coutinho 8783f12c4c fix: builtin_actions heuristics crash on a truthy non-string input (#1639) 2026-06-03 08:59:16 +09:00
Afonso Coutinho 82c09dd768 fix: split_chunks emits a duplicate trailing chunk for text over size-overlap (#1573) 2026-06-03 08:57:54 +09:00
Afonso Coutinho c3bf32d1b1 fix: monthly schedule label shows 21th/22th/31th (ordinal suffix for days >20) (#1577) 2026-06-03 08:57:47 +09:00
Afonso Coutinho 19b6cbac12 fix: skills CLI summary crashes on a non-string description (#1595) 2026-06-03 08:37:05 +09:00
Afonso Coutinho 258fe455eb fix: research CLI summary crashes on a non-string query (#1596) 2026-06-03 08:36:57 +09:00
Afonso Coutinho 667c663668 fix: gallery CLI image serialization crashes on a non-string prompt (#1598) 2026-06-03 08:36:51 +09:00
Afonso Coutinho 0283216e67 fix: rag_server add/remove_directory crashes on a non-string directory arg (#1614) 2026-06-03 08:36:45 +09:00
Afonso Coutinho 77313170c6 fix: search query helpers crash on a non-string query (#1604) 2026-06-03 08:36:01 +09:00
Afonso Coutinho 0d25dfb5f4 fix: shared MCP truncate() crashes on None/non-string tool output (#1605) 2026-06-03 08:35:54 +09:00