Commit Graph

420 Commits

Author SHA1 Message Date
Afonso Coutinho 2cedb02428 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
lekt8 dbff1853ba Disable pip cache for Cookbook dependency installs (off the home disk) (#1477)
Cookbook dependency installs (vLLM and friends) build large wheels; pip's
default cache lives under $HOME/.cache/pip, so on a small home filesystem the
build dies mid-way with "[Errno 28] No space left on device" (issue #1219) and
the dependency ends up "installed" but unusable (issue #1459).

Add `--no-cache-dir` to the dependency pip-install command (the maintainer's
suggested PIP_CACHE_DIR= workaround, made the default) via a small
_pip_install_no_cache() helper applied at the install chokepoint. Consistent
with the existing --no-cache-dir on the llama-cpp-python build. Idempotent;
non-pip-install serve commands are untouched.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 14:23:49 +09:00
ghreprimand ed1a2d79bb Cap inline attachment context across files (#1498)
Co-authored-by: ghreprimand <203024559+ghreprimand@users.noreply.github.com>
2026-06-03 14:23:43 +09:00
Ernest Hysa 69420327c2 Scope core.* module stubs to the test, not the module (#1513)
Three test files (test_auth_regressions, test_auth_event_loop,
test_null_owner_gates) install stubs for core.database / core.auth /
src.endpoint_resolver at module-import time, so they outlive the
file and are still present in sys.modules when later-collected test
files try to import the real modules. The stubs are minimal (a
handful of MagicMock attrs) so the import chain that follows fails
with ImportError on the very next real import.

test_companion_pairing also leaks, with a twist: its _DBStub
subclass returns a MagicMock for *any* attribute including dunders,
so the next test that does `from core.database import *` reads
`__all__` as a MagicMock and dies with 'Item in __all__ must be
str, not MagicMock'.

Move the stub installation into an autouse fixture per file and
register each stub with monkeypatch.setitem so sys.modules is
restored to its pre-test state on teardown. Tighten _DBStub to
refuse dunder names so __all__ stays undefined. _CAPTURED is
cleared per test so the mint-token assertions see a fresh dict.

Before: 3 test files fail at collection time (test_chat_image_routing,
test_context_compactor, test_webhook_ssrf_resilience). After: 0
collection errors. 1365/1370 pass, 1 skip, 4 unrelated pre-existing
failures (verified against origin/main baseline).

Out of scope: test_task_scheduler_session_delivery::
test_session_delivery_survives_empty_database also fails in the
full suite due to order-dependent state from a different test
file. That's a separate leak with a different root cause.
2026-06-03 14:23:40 +09:00
Afonso Coutinho 817205d60e 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 67244cc055 fix: POST /api/contacts/add crashes on JSON null name/email (None.strip()) (#1544) 2026-06-03 14:23:34 +09:00
Afonso Coutinho a50c9e0c73 fix: params_b crashes the whole ranking on a malformed parameter_count (#1550) 2026-06-03 14:23:30 +09:00
Lucas Daniel 1a58e79716 fix(settings): catch PermissionError in load_settings + error-path tests (#1570)
PermissionError was not in the except tuple so an unreadable settings.json
would crash the app instead of falling back to defaults. Added alongside the
existing FileNotFoundError/JSONDecodeError/ValueError catches.

Also adds test_settings_error_paths.py covering all four failure modes:
missing file, corrupted JSON, wrong type, and permission denied.
2026-06-03 14:23:27 +09:00
Afonso Coutinho 98a5559ccb fix: Mixtral and Ministral models render with no provider logo (#1640) 2026-06-03 14:23:21 +09:00
Afonso Coutinho 3e14e20d08 fix: _strip_reasoning_prose discards the answer when reasoning trails it (#1643) 2026-06-03 14:23:15 +09:00
Afonso Coutinho 59b27f2afb Anchor shell-verb intent patterns to imperative or can-you position (#1664) 2026-06-03 14:23:10 +09:00
Afonso Coutinho 0223064e99 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 084e73aaf3 fix: gallery records raw instead of display dimensions for EXIF-rotated photos (#1667) 2026-06-03 14:23:04 +09:00
Afonso Coutinho e3245d0c29 fix: monthly tasks scheduled for day 29-31 skip every short month (#1668) 2026-06-03 14:23:01 +09:00
Afonso Coutinho 98b2065798 fix: services research lists junk no-content pages as cited sources (#1669) 2026-06-03 14:22:58 +09:00
Afonso Coutinho 2c73078290 fix: web search content blocks numbered by fetch completion order break citations (#1672) 2026-06-03 14:22:55 +09:00
Ethan 94ca6e547c Fix HTTP 500 in history routes: order ChatMessage by timestamp, not created_at (#1673)
The mark-stopped, update-last-meta, and merge-last-assistant handlers in
routes/history_routes.py ordered ChatMessage queries by
DbChatMessage.created_at. ChatMessage does not inherit TimestampMixin and
has only a `timestamp` column, so SQLAlchemy raised AttributeError at
query-build time -> HTTP 500 on Stop, last-message metadata updates, and
Continue/merge. Each handler mutates in-memory history before the failing
query, so a failed request also silently diverged the in-memory view from
the database.

Order by DbChatMessage.timestamp (already used elsewhere in the file and
covered by the ix_messages_session_time index). Add a regression test
pinning the model column reality, the corrected query, and a guard against
re-introducing created_at.

Fixes #1659

Co-authored-by: Ethan <23321960+0xLeathery@users.noreply.github.com>
2026-06-03 14:22:51 +09:00
Afonso Coutinho c8133be9db fix: re-importing an ICS file duplicates every tz-aware timed event (#1683) 2026-06-03 14:22:49 +09:00
Afonso Coutinho 117154d6fe fix: visual report drops photos whose URL slug contains icon or logo (#1685) 2026-06-03 14:22:45 +09:00
Afonso Coutinho 2b327769df fix: hwfit native quant labels miss the cost maps and over-estimate VRAM (#1690) 2026-06-03 14:22:42 +09:00
red person a24c51e419 Ignore non-string markdown table rows (#1648) 2026-06-03 14:17:02 +09:00
red person 58a9d06e65 Ignore non-string calendar date inputs (#1649) 2026-06-03 14:16:58 +09:00
red person 1c63569c82 Ignore censor preference storage errors (#1652) 2026-06-03 14:16:55 +09:00
red person cfe933e26f Ignore invalid model sort inputs (#1653) 2026-06-03 14:16:52 +09:00
red person 906da91f4a Ignore non-string signature fold metadata (#1655) 2026-06-03 14:16:48 +09:00
Afonso Coutinho 5a82f60d2d fix: _parse_dt does not understand 'tonight' so event start/end breaks (#1488) 2026-06-03 14:14:41 +09:00
Shaw d6ff144e2f fix(agent): coerce non-object tool-call arguments instead of crashing (#1370)
A native function/tool call whose `arguments` field is valid JSON but not an
object — a bare array like ["ls -la"], or a string/number/bool/null — parsed
fine in function_call_to_tool_block and then every branch called args.get(...),
raising AttributeError ('list'/'str' object has no attribute 'get'). That
propagated out of the streamed agent loop (no surrounding try/except at the
call site in stream_agent_loop) and aborted the user's entire turn. Weaker and
local models routinely emit malformed args like this.

Coerce non-dict parsed arguments to {} (mirrors the existing empty-arguments
behavior), so the tool runs with empty args instead of killing the stream.

Adds tests/test_function_call_non_object_args.py covering array/string/number/
bool/null arguments — they fail before this change and pass after.
2026-06-03 14:14:37 +09:00
Denis Kutuzov (Rybak27) d1ae4c1a93 fix: auto-naming for 24h time format (#1374)
* fix: auto-naming for 24h time format

needs_auto_name() required AM/PM suffix for default
frontend-generated names like 'deepseek-v4-flash 17:46:02'.
Frontend uses toLocaleTimeString() which outputs 24h
format in most locales — so the regex never matched and
auto-naming silently skipped.

Made AM/PM optional and added re.IGNORECASE for 'am'/'pm'.

* test: add regression tests for needs_auto_name (24h + 12h + custom)

---------

Co-authored-by: Calculator Dev <dev@calculator.local>
2026-06-03 14:14:34 +09:00
ghreprimand db50178dec Replace task scheduler utcnow calls (#1456)
Co-authored-by: ghreprimand <203024559+ghreprimand@users.noreply.github.com>
2026-06-03 14:14:30 +09:00
Marius Oppedal Ringsby 874bbf967b Replace cleanup service datetime.utcnow calls (#1494)
datetime.utcnow() is deprecated in Python 3.12 and removed in 3.14.
Swap the five calls in src/cleanup_service.py for a local _utcnow()
helper returning naive UTC, matching the naive DateTime columns the
archive/delete cutoffs compare against (same approach as the
task-scheduler and core-database slices). Add a regression test
asserting the helper stays naive so the cutoff math can't hit a
naive/aware TypeError.

Part of #1116
2026-06-03 14:14:27 +09:00
ghreprimand 04d393b8d2 Replace webhook manager datetime.utcnow calls (#1499)
Co-authored-by: ghreprimand <203024559+ghreprimand@users.noreply.github.com>
2026-06-03 14:14:23 +09:00
Alexandre Teixeira d210da49e2 Add companion pairing route response tests (#920) 2026-06-03 14:14:20 +09:00
Alexandre Teixeira 0b4bc71dfc Add atomic IO durability tests (#1622) 2026-06-03 14:14:16 +09:00
red person e6f1e8fe71 Ignore non-object prefs JSON (#1257) 2026-06-03 14:12:45 +09:00
red person 7bb710338c Ignore non-object embedding endpoint config (#1260) 2026-06-03 14:12:41 +09:00
red person 3c73b4fe32 Skip invalid research CLI records (#1394) 2026-06-03 14:12:38 +09:00
red person 395edc5126 Reject invalid theme CLI prefs (#1396) 2026-06-03 14:12:35 +09:00
red person 989d066e0b Fall back from invalid preset stores (#1402) 2026-06-03 14:12:31 +09:00
Wes Huber d5e73f1c84 fix(tests): align broken test assertions with current behavior (#1791)
* fix(tests): align broken test assertions with current behavior

- test_readme_native_quickstart_uses_loopback: README warning text
  moved from --host prefix to bind-to phrasing; update assertion
- test_sanitize_merges_consecutive_user_messages: consecutive user
  messages ARE merged and orphan tool messages ARE dropped by the
  adjacency repair pass; update expected counts and values

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(tests): update cookbook status poll assertion for stopped state

The cookbookRunning.js ternary now handles a 'stopped' status
alongside 'error', so the exact string match in the test no longer
holds. Relax the assertion to check for the error branch presence
instead of the full ternary expression.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-03 14:12:17 +09:00
Afonso Coutinho 083d311da4 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
Shaw 89145b6260 fix(scheduler): fail closed on malformed scheduled_time instead of 500 (#1410)
compute_next_run parsed scheduled_time as "HH:MM" with int(parts[0]),
int(parts[1]) and no validation, so "9", "9am", "25:00", "9:" or ":30" raised
IndexError/ValueError. The POST /tasks create route passes the user/LLM-supplied
scheduled_time before its try block (and only validates the cron field), so a
bad value surfaced as an unhandled 500 rather than the clean 400 used for other
invalid fields — and the same crash could fire inside the scheduler loop when
recomputing next_run for an already-stored bad row.

Guard the parse and fail closed (warn + return None), matching the existing
invalid-cron handling in the same function.

Adds tests/test_scheduler_scheduled_time_validation.py — malformed values return
None (fail before with IndexError/ValueError), valid HH:MM still computes.
2026-06-03 14:12:07 +09:00
Shaw 2cdacb952e fix(tts): tolerate a malformed tts_speed instead of 500-ing (#1450)
synthesize() and get_stats() parsed the stored tts_speed with a bare
float(settings.get("tts_speed", "1")). The manage_settings agent tool maps
"speech speed"/"voice speed" to tts_speed and, because the setting's default is
a string, writes the value through unvalidated — so an agent (or a hand-edited
settings.json) can store "fast" or "". After that, GET /api/tts/stats and POST
/api/tts/synthesize both 500 with ValueError until the JSON is corrected by hand.

Parse defensively via a _safe_speed() helper (non-numeric/empty/<=0 -> 1.0),
mirroring the settings layer's tolerance of corrupt config.

Adds tests/test_tts_speed_malformed.py (stats + synthesize) — both raise
ValueError before this change and pass after.
2026-06-03 14:12:03 +09:00
red person 74a6b54e33 Reject invalid cookbook CLI state (#1531) 2026-06-03 14:11:56 +09:00
red person 082e556975 Ignore invalid note CLI items (#1539) 2026-06-03 14:11:53 +09:00
red person 9b37461279 Skip invalid FAISS migration JSON (#1547) 2026-06-03 14:11:49 +09:00
red person d0c4f7da4f Ignore non-string background stream deltas (#1549) 2026-06-03 14:11:45 +09:00
red person c570673751 Skip invalid memory CLI rows (#1552) 2026-06-03 14:11:42 +09:00
red person 94f8833176 Skip invalid skills CLI rows (#1553) 2026-06-03 14:11:38 +09:00
red person e265a4447a Normalize stored MCP CLI JSON (#1554) 2026-06-03 14:11:35 +09:00
red person 6a46c21143 Reject invalid Tailscale discovery JSON (#1556)
* Reject invalid Tailscale discovery JSON

* Guard nested Tailscale IP shapes
2026-06-03 14:11:31 +09:00