Commit Graph
1707 Commits
Author SHA1 Message Date
39303f19cd fix(editor): stabilize image generation, layer editing and controls (#6992)
* fix(editor): stabilize image workflows and editing controls

* docs(editor): add desktop and mobile visual validation evidence

* fix(editor): synchronize quick edit model events and register imagePreferences in test coordinator

* fix(settings): enforce authoritative global image-gen policy and non-admin preference persistence

- Enforce authoritative administrator global image_gen_enabled disable in get_user_setting, do_generate_image, and image_editing_provider_available, preventing non-admin user preference overrides while preserving user-disabled opt-outs and can_generate_images privilege checks across direct, gallery, and editor paths.
- Filter non-admin preference persistence in saveImagePreferences to user preference keys only (image_model, image_edit_model, image_quality), preventing global policy toggles from leaking into user preferences.
- Return accurate 200 OK Response from saveImagePreferences after fallback persistence succeeds so settings UI displays 'Saved' instead of false 403 error, while retaining visibility of real errors.
- Load per-user preferences via readImagePreferences in initImageSettings so non-admin selections persist and display correctly after page reload.
- Clear per-user model preferences on successful admin save (POST /api/auth/settings) via PUT /api/prefs/{key} with value: null to prevent stale per-user preferences from shadowing updated global settings.
- Support clearing keys in PUT /api/prefs/{key} when value is null.
- Add comprehensive Python regression tests for global-disabled/user-enabled, global-enabled/user-disabled, and authorized generation, plus Node and browser regression tests for non-admin persistence, toggle isolation, reload, and admin clearing.

* fix(settings): invalidate shared appConfig cache near auth settings write

* fix(test): isolate test_tool_policy unit suite from external model endpoint state

* fix(test): isolate web_fetch failure regression from contextual follow-up heuristics

* fix(test): isolate test_tool_policy from cross-test approval gate state

Ensure _patch_loop_basics disables TOOL_APPROVAL_GATE_ENABLED so routing tests in test_tool_policy run in the intended opt-out posture even when prior tests populate DATA_DIR with skills or untrusted context. Remove unnecessary forced_tools and contextual web mock workarounds.

* fix(settings): isolate non-admin image toggle and surface preference cleanup errors

- Restrict image generation availability toggle to admin users in imageModels.js, disabling the switch for non-admins and reverting unauthorized changes with an explicit message.
- Separate non-admin image model preference saves from global toggle updates.
- Track preference cleanup results on admin save in imagePreferences.js, propagating cleanup failures instead of ignoring them.
- Require valid preference keys on 403 fallback so toggle-only attempts reject cleanly.
- Add /api/prefs route mock to test_image_model_settings_sync_both_directions_and_survive_reopening.
- Add regression coverage for admin cleanup failures and non-admin toggle rejection.

* fix(settings): reconcile admin toggle on partial cleanup failure and report errors

- In imagePreferences.js, distinguish pre-persistence failures from post-save cleanup failures using err.globalSaved and err.phase.

- In imagePreferences.js, notify listeners of global policy updates on partial success before propagating cleanup failure.

- In imageModels.js, retain the persisted target state on admin toggle when global persistence succeeds but cleanup fails.

- In imageModels.js, reconcile admin toggle with authoritative server state via readImagePreferences() after ambiguous or partial failures.

- In imageModels.js, report partial success accurately without suppressing preference cleanup error messages.

- Add regression coverage in test_settings_save_response_ok_js.py for cleanup HTTP 500, cleanup network rejection, successful cleanup, and failed global POST.

---------

Co-authored-by: pewdiepie-archdaemon <pewdiepie-archdaemon@users.noreply.github.com>
Co-authored-by: Alexandre Teixeira <general@alexandreteixeira.dev>
2026-11-01 02:56:46 +00:00
5353241743 fix(chat): warn before regenerate, resend or edit deletes later messages; offer fork (#6225)
* fix(chat): warn before "regenerate" permanently deletes later messages

Both "regenerate" entry points — the per-message footer's ↻ "Regenerate
from here" button, and the vision editor's "Regenerate message" button —
call POST /api/session/{id}/truncate, which does a real, permanent SQL
delete of every message after the point clicked, then generates a new
reply. Clicking either on anything but the very last exchange did this with
zero warning: the button's own label doesn't say it also erases the rest
of the conversation, and neither button visually signals it's destructive
differently from any other message-footer action.

Caught live: a mis-click destroyed a real conversation with no way to
recover it (no backup covered the affected window). This adds a
confirmation prompt — via the existing uiModule.styledConfirm — whenever
the action would delete more than just the message(s) being regenerated,
stating the exact count of messages that would be lost. Regenerating the
most recent exchange (the everyday case, nothing exists after it) is
unaffected and still proceeds with zero friction.

New test: tests/test_regenerate_truncate_warning_js.py — drives the real
regenerateFrom/resendUserMessage functions under Node with a fake message
list DOM, confirming: the last-exchange case never prompts and truncates
directly; an earlier case prompts with the correct count; cancelling
aborts before any network call; confirming proceeds with the correct
keep_count. Also fixed a pre-existing, unrelated gap this surfaced while
verifying the full suite: test_pr6020_browser_review_regressions.py's
Node harness never stubbed `navigator` at all (sessions.js reads
navigator.platform at module load) — a gap on origin/dev itself, not
caused by this branch's diff, using the same Object.defineProperty fix
already applied on #6019/#6148 for the sibling issue there (Node 21+'s own
getter-only navigator global, not relevant to this specific failure but
the same defensive pattern).

Verified: full pytest suite in-container, 5798 passed / 11 pre-existing
unrelated failures (README/docs/agent-loop baseline) / 0 new.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* test(chat): cover plain resend after dev's replace-by-default change

dev made plain resend (no options) replace from the clicked turn by
default, with append-only resend opt-in via { append: true } (see
test_resend_message_nondestructive.py). The footer "Resend message"
button calls resendUserMessage(el) with no options, so it now truncates
everything after the clicked turn and goes through this PR's warning.
Replace the old "plain resend never prompts" test, which assumed the
previous append-by-default behavior, with one asserting that plain
resend on an earlier pair prompts with the right count, and one
asserting that explicit append-only resend never truncates or prompts.

Also resolve ui.js/sessions.js through the same cache-busting query
string chat.js imports them with. ES modules cache by full URL, so the
harness's unversioned import of ui.js was a second module instance and
its uiMod.styledConfirm stub never reached the instance chat.js calls.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(chat): warn before an edit deletes later messages; offer to fork instead

Sending an edited user message truncates the chat at that message, the
same unrecoverable server-side delete as regenerate and resend, but did
it with no prompt. It now goes through the same confirmation, worded for
the action ("Sending this edit will also permanently delete the N
messages after it"). Cancelling leaves the editor open with the draft.

The confirmation for all three actions (regenerate, resend, edit) also
offers "Fork from here": it forks the chat just before the user turn,
switches to the new chat, and replays the action there (the same message,
or the edited text), leaving the original chat untouched. forkFrom now
shares the same fork helper.

Tests drive the real editUserMessage Send handler under Node and cover
the edit prompt (count, cancel, last-message no-prompt) and the fork
choice for each action (fork keep_count, no truncate, replayed text).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(chat): cut and fork a chat by message id, not loaded-page position

Regenerate and edit sent keep_count, the clicked message's position among
the messages loaded in the page. A long chat loads only its newest messages
until the user scrolls up, so that position is smaller than the real one and
the truncate deleted real messages above the clicked one (regenerating the
latest reply in a ~50-message chat removed about a dozen earlier messages).
Resend already sent before_msg_id; regenerate and edit now do the same.

The fork options this PR adds had the same flaw. Fork now accepts
before_msg_id (fork before that message) and through_msg_id (include it),
resolved against the stored messages; keep_count stays as the fallback for a
message that has no id yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(chat): keep a regenerated turn's message id current; stop on a refused cut

Regenerate keeps the original user bubble on screen and resubmits its text
without drawing a new bubble. The resubmitted message is a new DB row, but
the bubble kept the deleted row's id, so the next regenerate's cut was
refused (404) and the page sent the turn anyway, stacking a second reply.

The stream now reports the saved user message's id (user_message_saved),
which the page attaches to the user bubble, or to the bubble a regenerate
kept. Regenerate and edit stop with an error when the server refuses the
cut instead of sending.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(chat): name the buttons in words instead of symbols

CONTRIBUTING asks for no Unicode emoji in UI or code; the test comments
used the regenerate and pencil glyphs to name buttons.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(chat): share the fork-and-send step across edit, resend and regenerate

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(chat): pass the regenerate fork its attachment ids explicitly

Resend already hands its collected file ids to _forkAndSend; regenerate
relied on the earlier _pendingRegenAttachments assignment. Pass _regenIds
too so both fork paths read the same, and check the hand-off in the
regenerate tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(chat): assert fork choices keep the user message's attachments

Run regenerate and resend's "Fork from here" against a user message with
an uploaded file and check that the send fired in the fork carries its
file id, replacing the source-text check. chat.js exposes a read-only
_pendingRegenAttachmentIds() for this, like cookbook-hwfit.js's test hooks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(chat): preserve attachments across edit and regeneration

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Co-authored-by: Alexandre Teixeira <general@alexandreteixeira.dev>
2026-11-01 02:47:32 +00:00
Wojciech TaisnerandAlexandre Teixeira 285d05e72e fix(docker): forward ODYSSEUS_FIRST_TOKEN_TIMEOUT through compose (#6778)
Co-authored-by: Alexandre Teixeira <general@alexandreteixeira.dev>
2026-11-01 02:28:58 +00:00
dc0fbbf7aa fix(compose): default ODYSSEUS_TTS_CACHE_MAX_BYTES so compose stops warning (#6619) (#6645)
The three shipped compose files forwarded the variable bare, so every
`docker compose` command on a default .env printed "variable is not set".
Default it to the 500 MiB that .env.example documents, like the other
limits, and add a guard test that rejects any bare ${VAR} in compose files.

Fixes #6619

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Alexandre Teixeira <general@alexandreteixeira.dev>
2026-11-01 02:03:06 +00:00
cb26ccd9a7 test: skip native bash tool tests on Windows (2 modules) (#6872)
* tests: skip native bash behavior test on Windows in test_production_external_bridge

On Windows the only containment mechanism (windows_tree) enforces wall-clock
only; ENFORCING mode refuses bash (filesystem/process_tree unavailable), so
exit_code is 1. The test asserts bubblewrap/process_group: POSIX-only by design.

Part of #4287

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* tests: skip native bash exit-status test on Windows in test_preview_execution_evidence

BashTool needs enforcing containment (filesystem/process_tree); Windows
windows_tree gives wall-clock only, so the command is not executed and
exit_code is 1 instead of 7. POSIX-only by design.

Part of #4287

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Co-authored-by: Alexandre Teixeira <general@alexandreteixeira.dev>
2026-11-01 01:47:57 +00:00
23a480571a tests: skip the 0o600 file-mode assert on Windows in the effect log fsync test (#6892)
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Co-authored-by: Alexandre Teixeira <general@alexandreteixeira.dev>
2026-11-01 01:39:56 +00:00
6a43cf23ea tests: make hardcoded /tmp assertions OS-neutral (#6864)
Root cause: _is_sensitive_path splits on os.sep, so POSIX literals missed
on Windows; /tmp is not a root on Windows (only $TMPDIR); inline-JSON test
compared against "/tmp/wf.txt" while Windows abspath is C:\tmp\wf.txt.
Change: native-separator helper, TMPDIR monkeypatch, abspath alternative.
Before: 9 failed; after: 0 failed (74 passed, 1 symlink skip).

Part of #4287

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Co-authored-by: Alexandre Teixeira <general@alexandreteixeira.dev>
2026-11-01 01:33:28 +00:00
64b457dc0a fix(tests): read static sources as UTF-8 in the static assertion tests (#6850)
On native Windows the default text encoding is the ANSI code page
(cp1252 on en/pt systems), so the module-level read_text() calls in
eight static tests fail at collection with UnicodeDecodeError on bytes
0x81/0x90 that appear in static/js/chat.js, chatRenderer.js, app.js,
index.html and src/visual_report.py. Pass encoding="utf-8" like the
other 700+ tests in the suite already do.

Found by running the suite natively on Windows 11 (Python 3.11).

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Co-authored-by: Alexandre Teixeira <general@alexandreteixeira.dev>
2026-11-01 01:26:11 +00:00
red person ef3467e8d4 fix(tasks): render daily brief calendars in local time (#6926) 2026-10-31 13:54:14 +00:00
red person 72e8520fa3 fix(models): honor visible pinned IDs in route selection (#6922) 2026-10-31 13:51:59 +00:00
red person 9276db9c11 fix(models): skip non-chat models when resolving chat defaults (#6907) 2026-10-31 13:49:26 +00:00
GrzegorzandClaude Opus 5.5 a797cee0b3 fix(cookbook): diagnose vLLM serves on an NVIDIA driver that is too old (#6727) (#6728)
- Add a diagnosis for "NVIDIA driver on your system is too old" and
  "CUDA driver version is insufficient for CUDA runtime version", the
  errors PyPI's CUDA 13 torch/vLLM builds hit on drivers older than 580.
- Remove the nested _diagnose_serve_output copy in cookbook_routes.py.
  It shadowed the helper and had drifted, so /api/cookbook/tasks/status
  never used the helper's newer diagnoses.
- Capture the tmux pane with -J in the status poll so lines wrapped at
  the pane width do not split error text mid-word.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 13:47:30 +00:00
Grzegorz 76061498c8 fix(gallery): validate album rename and image_ids input (#6822) (#6823) 2026-10-31 13:45:02 +00:00
Merajul Arefin 04f8546d9d fix(search): gallery library per-word search with LIKE escaping (#6584)
Gallery search built a single `%{search}%` LIKE, so multi-word queries only matched the exact adjacent phrase ("red car" missed "a car that is red") and literal % / _ acted as SQL wildcards. Split on whitespace and require each token to match (prompt OR tags OR ai_tags), escaping LIKE wildcards per token; same escaping for the tag filter. Promote _escape_like to public escape_like_pattern() shared helper.

Part of #2123.

Tests: tests/test_gallery_search_multiword.py (5 tests); 4 fail pre-fix, 5 pass post-fix. Neighbors (session_search, gallery null-user, shims): 25 passed.
2026-10-31 13:43:20 +00:00
Robert Vind-Gardoș 9835c1a7f9 fix(skills): refuse renaming a skill onto a name the owner already uses (#6941)
update_skill only checked whether the target directory existed. A skill
with that name in another category lives elsewhere on disk, so the
rename went through and left two skills with one name. Update and
delete look skills up by name, so the next delete removed whichever
file os.walk reached first.

Check the owner's skills in every category before renaming, and answer
409 from PUT /api/skills/{id} instead of the misleading 404.
2026-10-31 13:34:05 +00:00
GrzegorzandClaude Opus 5.5 a1a7f8fc9a fix(agent): don't clamp an unknown context window to the small-server budget (#6678) (#6706)
budget_context_for_model() returns 0 when the endpoint does not prove its
context window, and compute_input_token_budget() answers 0 with the
conservative default budget (6000). The agent loop's small-local-server
clamp (`candidate_context <= 8192`) also matched 0 and cut the request to
max(1200, 0) tokens, so on any endpoint with an unreported window an open
document or a few thousand tokens of earlier context were trimmed away
before the model saw them ("5519 tokens > 1200 budget (ctx=1800)").

Apply the clamp only to a known window.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 13:30:29 +00:00
Prince 87193d23f5 fix(agent-loop): release buffered prose when '<' is not a tool tag (#6757) (#6758) 2026-10-31 13:26:43 +00:00
VykosandClaude 516f046fef fix(chat): label the vision description injected for text-only models (#6223)
When the chat model cannot see images, the separate vision call's description
is appended to the user's message. Nothing marked it as machine-derived, so the
chat model read it as the user's own prose and answered the description instead
of the question.

The label goes below the `[Image: <name>]` marker line because the client
strips the block by matching that exact prefix; renaming the marker would leave
the raw description rendered in the user's bubble.

Fixes #5573

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-31 13:24:32 +00:00
red person 48c3a7fc36 fix(pdf): convert CMYK images before vision analysis (#6917) 2026-10-31 13:22:55 +00:00
red person 70fc58225c fix(documents): treat library search punctuation literally (#6944) 2026-10-31 13:21:10 +00:00
red person 9efedc8b07 fix(documents): retain language extensions in ZIP exports (#6848) 2026-10-31 13:18:58 +00:00
gloss-stack 1d251ef867 Fix transcript search snippet positioning (#6206) 2026-10-31 13:05:35 +00:00
Nguyen Thanh Dat bf5bf57bc1 fix(diagnostics): report a failed config source instead of "disabled" (#6154) (#6169)
`_gather_inputs()` fails soft: a source that raises leaves its inventory as
`[]`. Every probe reads an empty inventory as "not configured" and answers
`disabled`, so a broken integrations file, email store, or endpoint database is
indistinguishable from a subsystem the operator deliberately turned off. With
the remaining subsystems disabled, `GET /api/diagnostics/services` then reports
`overall: "ok"` while three of its inputs failed to load — the exceptions appear
only in DEBUG logs.

Record each failure alongside the empty value (`failed`: source -> controlled
category) and report the affected subsystem through `_source_unavailable()`
rather than probing it with an inventory that is empty for the wrong reason.

- `degraded`, not `disabled`: the configured state is unknown, not known-off.
  Not `down` either — nothing reached the subsystem and failed; the inventory
  could not be read. Severity is non-zero either way, so a report containing a
  failed source can no longer roll up to `ok`.
- A source that loads and is genuinely empty still reports `disabled`.
- One broken source degrades one entry; the others are still probed.
- `meta` carries the source name and the controlled `_classify_error()`
  category only, never exception text, credentials, or database detail.
- `inputs.get("failed")` so an inputs payload without the key still probes
  normally.

Verified with the reporter's harness: settings loading with
`search_provider: "disabled"` while the other three sources raise now yields
`overall: "degraded"` with `searxng` still `disabled`; before, all five read
`disabled` and `overall` was `ok`.
2026-10-31 13:04:18 +00:00
MBGAandBolt4243 2019a97339 fix(skills): preserve escaped quotes in frontmatter lists (#6265)
* fix(skills): preserve escaped quotes in frontmatter lists

* test(skills): use descriptive frontmatter examples

---------

Co-authored-by: Bolt4243 <277300782+Bolt4243@users.noreply.github.com>
2026-10-31 13:02:02 +00:00
Aashish Mahato 9a1fdb192e fix(cookbook): resolve NameError in hf-gguf-files exception handler (#6341) (#6369)
In routes/cookbook_routes.py, the exception handler for GET /api/cookbook/hf-gguf-files referenced repo instead of the parameter repo_id, causing an unhandled NameError and 500 status when upstream requests to Hugging Face failed.

Fixes #6341.
2026-10-31 12:59:17 +00:00
nopoz bebf53be3c fix(agent): make preview and browser output parsers linear (#7003)
Six regexes over tool output backtracked polynomially on long whitespace
runs or repeated openers: the browser snapshot generic-line filter and
post-interaction split, the task-row and skill-bullet parsers, the email
"no results" check, and the Google /sorry/ interstitial check.

Rewrite each without overlapping quantifiers, keeping the same matches for
the text these tools emit. Move the /sorry/ check into
is_google_sorry_url() so it can be tested.
2026-10-30 22:46:19 -07:00
Alexandre Teixeira a8e0ff1c8e Merge pull request #6998 from odysseus-dev/maintainer/fix-6546-scientific-data
fix(llm): support scientific and decimal literals in degenerate guard
2026-10-31 02:43:09 +00:00
Alexandre Teixeira 31685b050a fix(llm): support scientific and decimal literals in degenerate guard
Preserve complete scientific notation and signed floating-point literals across
arbitrary streaming chunk boundaries in _DegenerateStreamGuard. Buffer pending
tokens until delimiter characters arrive to avoid splitting numbers into
incomplete or arbitrary alphanumeric tokens, while maintaining the 2048-number
runaway backstop and detection of repeated phrases and word loops.
2026-10-30 20:45:09 +00:00
Alexandre Teixeira 03d25943ee Merge pull request #6993 from odysseus-dev/perf/editor-cursor-style-invalidation
perf(editor): avoid brush cursor style invalidation
2026-10-30 20:09:16 +00:00
Alexandre Teixeira 71e3649985 Merge pull request #6947 from redpersongpt/codex/compare-stream-contract
fix(compare): reject incomplete and errored SSE responses
2026-10-30 19:47:28 +00:00
Alexandre Teixeira 71f6dc4e5d Merge pull request #6912 from redpersongpt/codex/email-linkify-single-pass
fix(email): linkify URLs and addresses without rewriting anchors
2026-10-30 19:46:54 +00:00
Alexandre Teixeira eea39ce103 Merge pull request #6934 from redpersongpt/codex/skill-editor-load-guard
fix(skills): wait for source before enabling the editor
2026-10-30 19:46:21 +00:00
Alexandre Teixeira 9a5a15e17f Merge pull request #6932 from redpersongpt/codex/skill-editor-source-height
fix(skills): size the raw editor from its source lines
2026-10-30 19:46:04 +00:00
Alexandre Teixeira cfbe4aeca4 Merge pull request #6915 from redpersongpt/codex/image-quality-explicit-default
fix(images): preserve explicit medium quality requests
2026-10-30 19:45:13 +00:00
Alexandre Teixeira 6f0679bb25 Merge pull request #6253 from VykosMolt/fix/generate-image-native-schema-5520
fix(tools): reject generate_image calls without a prompt
2026-10-30 19:44:56 +00:00
Alexandre Teixeira 93c93bf076 Merge pull request #6748 from dxrpl/fix/6747-recipe-panel-toggle
fix(cookbook): bring back the Dependencies recipe-panel caret (#6747)
2026-10-30 19:44:39 +00:00
Alexandre Teixeira f0f7464dfa Merge pull request #6952 from redpersongpt/codex/mail-cli-date-order
fix(mail): sort CLI message batches by UTC date
2026-10-30 19:44:23 +00:00
Alexandre Teixeira 1e57f774d3 Merge pull request #6913 from redpersongpt/codex/font-compound-style-family
fix(fonts): group compound weight and style variants by family
2026-10-30 19:44:07 +00:00
Alexandre Teixeira 2b310010cf Merge pull request #6930 from redpersongpt/codex/stale-hf-cache-markers
fix(cookbook): ignore empty markers beside completed blobs
2026-10-30 19:43:50 +00:00
Alexandre Teixeira b88154ecf9 Merge pull request #6730 from dxrpl/fix/hwfit-hf-param-count
fix(hwfit): keep the MoE active size for HF collection models (#6729)
2026-10-30 19:43:34 +00:00
Alexandre Teixeira e7796f71d3 Merge pull request #6890 from redpersongpt/codex/checkin-calendar-window-boundaries
fix(checkin): avoid duplicate calendar events at window boundaries
2026-10-30 19:43:18 +00:00
Alexandre Teixeira 412789051e Merge pull request #6585 from robyroro/codex/notes-clear-fields
fix(notes): persist removal of optional note fields
2026-10-30 19:43:01 +00:00
Alexandre Teixeira b8adc4eb60 Merge pull request #6904 from dxrpl/fix/calendar-config-object-body
fix(calendar): answer 400 when a CalDAV config body is not a JSON object (#6903)
2026-10-30 19:42:45 +00:00
Alexandre Teixeira 2246215b79 Merge pull request #6906 from dxrpl/fix/more-validation
fix(api): answer 400 for a malformed body on integrations and document export-zip (#6905)
2026-10-30 19:42:28 +00:00
Alexandre Teixeira 06fee0a3d8 Merge pull request #6546 from harshit-ojha0324/fix/degenerate-guard-numeric-data
fix(llm): stop the repeat guard from cutting off numeric data
2026-10-30 19:41:03 +00:00
Alexandre Teixeira f3813c261c perf(editor): avoid brush cursor style invalidation 2026-10-30 19:27:58 +00:00
Alexandre Teixeira e7a376b161 Merge pull request #6950 from redpersongpt/codex/group-peer-history-identity
fix(group): preserve peer identity when reloading history
2026-10-30 19:03:48 +00:00
Alexandre Teixeira fec2bb11d6 Merge pull request #6951 from redpersongpt/codex/gallery-cli-tag-filters
fix(gallery): match stacked CLI filters against AI tags
2026-10-30 19:03:01 +00:00
Alexandre Teixeira c811f76d44 Merge pull request #6935 from redpersongpt/codex/email-paperclip-files
fix(email): retain files in attachment and inline-image pickers
2026-10-30 19:02:22 +00:00
Alexandre Teixeira 02d28c06d0 Merge pull request #6888 from redpersongpt/codex/skill-version-preservation
fix(skills): preserve version strings across markdown saves
2026-10-30 19:01:47 +00:00