Commit Graph
34 Commits
Author SHA1 Message Date
webtecnica 813b293c82 fix(commands): remove duplicate top-level const breaking messages.js load
static/commands.js and static/messages.js both declared
const _BACKEND_EXECUTED_AGENT_COMMANDS at file scope. static/index.html
loads them consecutively as classic defer scripts in the same global
lexical realm, so the second declaration threw
SyntaxError: Identifier '_BACKEND_EXECUTED_AGENT_COMMANDS' has already
been declared, aborting messages.js entirely.

The constant was unused in both files (a duplicate authority mirror, not
a genuinely shared source), so both declarations are removed. The
existing three-way parity test is preserved, and a new regression
evaluates commands.js followed by messages.js in one shared
classic-script vm realm, asserting both files evaluate cleanly and the
dispatch consts of both files are bound.
2026-09-20 11:59:09 +00:00
webtecnica ff06f6d032 fix(commands): exact cross-authority parity for announced slash commands 2026-09-20 11:59:09 +00:00
webtecnica a85c1d1f62 fix(commands): exact cross-authority parity for announced slash commands (#6951) 2026-09-20 11:59:09 +00:00
webtecnica d03891a307 fix(commands): autocomplete only announces webui-dispatchable slash commands (#6951) 2026-09-20 11:59:09 +00:00
webtecnica 06fc0575d5 fix(async): close pre-ACTIVE_RUNS stream window, never strand wakeup admission (#6989) 2026-09-20 10:36:36 +00:00
webtecnica b7f536b006 fix(async): atomic per-origin wakeup admission prevents delivery budget exhaustion (#6959) 2026-09-20 10:36:36 +00:00
webtecnica da4e4ef316 fix(picker): catalog is authority for @custom labels; keep plain-lane colon models whole
The #7240 fix peeled the leading @custom: segment on first-colon split, but a
plain-lane custom id whose model carries a tag/variant colon
(@custom:ollamacloud/qwen3.5:397b) was still misread as slug=ollamacloud/qwen3.5,
rendering only "397b". Two changes:

- _dynamicModelLabels (the backend-populated catalog) is now consulted BEFORE
  the string peel: the backend knows the true provider/model split and ships an
  exact m.label per routing id, so catalogued ids — including plain-lane colon
  models and collision cases — render verbatim.
- The legacy string fallback now treats a slash-bearing first segment as the
  model itself (a provider slug is a config key or host:port authority and
  never contains '/'), mirroring the '/' means routable rule api/config.py
  applies when building ids.

Tests: add plain-lane @custom:ollamacloud/qwen3.5:397b controls, a
post-catalog dynamic-label control, and a collision case proving labels stay
distinct by full routing id. Driver now accepts an optional pre-hydrated
catalog map.
2026-09-20 06:33:58 +00:00
webtecnica e71c3e1f97 fix(picker): stop truncating model names with colons 2026-09-20 06:33:58 +00:00
webtecnica 65e968c447 fix(commands): drop slash-skill caches on profile switch
The slash-skill caches (_slashSkillCache, _slashSkillCachePromise,
_skillCommandCache) outlived a profile switch, so the outgoing profile's
/api/skills payload kept hiding skills that the incoming profile enables
(#7509).

- call invalidateSlashSkillCaches() from both switch handlers
  (static/panels.js switchToProfile, static/sessions.js
  _switchProfileForSessionLoad), after the /api/profile/switch request
- bump a generation counter in invalidateSlashSkillCaches() and capture it
  in both loaders: a reply issued for the outgoing profile can no longer
  commit once the switch has landed
- tests: in-flight race and cache-refresh regression on both picker
  surfaces, plus a check that both switch paths call the invalidation
2026-09-18 02:23:23 +00:00
webtecnica 9cb0235f5e fix(commands): keep disabled skills out of the slash-command picker
`skills.disabled` entries are already excluded from the backend skill-command
map, but the composer still offered them as selectable slash commands and as
`/use` sub-args: both picker surfaces read `/api/skills` and ignored the
`disabled` flag the endpoint reports per skill.

Add one `_isSkillDisabled()` gate in static/commands.js and apply it at the two
places that turn `/api/skills` rows into completions:

* `_buildSkillCommandEntry()` returns null for a disabled skill, which keeps
  `_skillCommandCache` (and every consumer of it, including the dropdown) clean;
* `_loadSlashSkillSubArgs()` skips disabled skills when building `/use`
  sub-args.

Both caches still rebuild from `/api/skills`, so a skill toggled off in the
skills panel disappears from the picker on the next load.

Adds tests/test_issue7509_disabled_skills_slash_picker.py, which runs the real
static/commands.js in a vm context with a mocked `api()` and asserts on
`getSlashAutocompleteMatches()` for both surfaces, over 0 / 1 / many skills,
enabled / disabled / flag-absent entries and a disable-then-refresh cycle.

Fixes #7509
2026-09-18 02:23:23 +00:00
webtecnica 80610c7b6c docs(architecture): document the /api/models cache invalidation contract
The /api/models cache identity shipped in #7556 (release #7558) changed from a
stat identity to content fingerprints with volatile-key deny-lists, and the #7556
review flagged that this runtime contract had no project-level documentation.
Record the three source-fingerprint axes and their rationale, the one-directional
deny-list invariant, the stat-identity fallbacks (including the deep-tree
RecursionError path), the independent schema/version stamps, and the change
protocol; index the document from docs/CONTRACTS.md. Docs only.
2026-09-13 15:02:03 -03:00
webtecnica 617881feab test: drive the auxiliary loader behaviorally instead of grepping panels.js (#7521) 2026-09-10 23:18:44 -03:00
webtecnica dc1d41db04 fix: keep endpoint-error provider groups in auxiliary model pickers (#7521) 2026-09-10 23:11:12 -03:00
webtecnica e34980d969 test(7514): pass strict=True to zip() in the namespace projection test
Fixes the B905 finding flagged by the forward ruff gate on #7518.
2026-09-10 22:39:18 -03:00
webtecnica 4f109aebbe fix(settings): preserve configured aux provider when absent from catalog (#7486) 2026-09-10 22:37:09 -03:00
webtecnica 4359ed4fee fix(onboarding): use OpenRouter namespace z-ai/ for Z.AI models (#7514) 2026-09-10 22:30:44 -03:00
webtecnica ca653eca1d test: tolerate conversation_id kwarg in title mock 2026-09-08 22:15:46 -03:00
webtecnica 61f3cf7ed9 fix(title): publish conversation context for aux title calls
Title generation via the aux client ran without the Agent's ambient
conversation context, so relay targets that key on it (OpenCode Go)
rejected the completion call with HTTP 400.

Publish the webui session id as the Agent conversation context around
the aux completion (restoring it in a finally block) and pass it from
all three title entry paths: background update, background refresh and
the on-demand regenerate helper.

Refs #7470
2026-09-08 22:06:32 -03:00
webtecnica 2c0b4902d0 fix(renderer): emit nested lists iteratively to avoid stack overflow (#6700) 2026-09-08 01:16:01 -03:00
webtecnica 660d54af63 test(renderer): mirror nests same-marker child lists inside parent li (#6700)
greptile P2: the Python mirror's handle_ul/handle_ol closed the parent
<li> before opening the child <ul>/<ol> for same-marker nested lists
('- parent\n  - child'), so structural assertions passed without
validating renderMd()'s parent-child hierarchy. Child lists now render
inside the parent <li>, byte-matching renderMd() for the two-level case;
adds a mirror regression test asserting the exact nested structure.
2026-09-08 01:16:00 -03:00
webtecnica b810e5466f fix(renderer): preserve ordered flag on list items (#6700)
openItem() received ordered but dropped it from the item constructor, so
it.ordered was always undefined and every item looked unordered at the
task-list check. An ordered item whose text begins with [x] or [ ] (e.g.
'1. [x] shipped') was silently converted to a task icon and lost its
literal prefix. Task-list rendering now applies only to unordered items.
2026-09-08 01:16:00 -03:00
webtecnica 13dd97d60d fix(renderer): preserve nested mixed ul/ol list hierarchy (#6700) 2026-09-08 01:16:00 -03:00
webtecnica ec4bac9fc9 fix: model picker search matches OpenRouter display names (#7228) 2026-08-31 15:29:28 -03:00
webtecnica b36fbdd633 fix(regeneration): refuse bounded tail on in-tail duplicate keys + real WAL interleaving test (#6826 r5) 2026-08-26 00:24:07 +00:00
webtecnica 7abd4773ca fix(regeneration): snapshot reuses canonical projection+ordering; WAL data_version guard (#6826 r4) 2026-08-26 00:24:07 +00:00
webtecnica b33aff9d09 fix(regeneration): occurrence-count guard + single-snapshot (no TOCTOU) for bounded tail read (#6826 r3 round-3) 2026-08-26 00:24:07 +00:00
webtecnica 40ff74b6fc fix(regeneration): bounded tail read only when skipped state.db prefix is provably identical; compression-anchor coverage (#6826 r3) 2026-08-26 00:24:07 +00:00
webtecnica 3672e0038b fix(regeneration): bounded sidecar-anchored tail read instead of full transcript refetch (#6826) 2026-08-26 00:24:07 +00:00
webtecnica 8c9f505fab fix(ui): avoid full transcript fetch on regenerate (#6826) 2026-08-26 00:24:07 +00:00
webtecnica 91ceb60996 fix(sessions): dedup title on collision instead of leaving blank (#6964) 2026-08-12 18:35:09 -03:00
webtecnica a5b1898e20 fix(api): read memory flags from nested memory config section (#6498) 2026-08-05 22:23:55 -03:00
webtecnica ed09ee6930 fix(api): request-owned config snapshot for memory gates (#6498)
- _handle_memory_read: pass the request-owned get_config_snapshot() into
  _external_notes_sources_enabled() so no ambient/process-global config is
  re-read later in the handler (review requirement).
- tests: add cross-profile forced-reload regressions for both directions
  (A disabled/B enabled and inverse), covering memory_enabled and
  user_profile_enabled for read (no content/path/mtime) and write (403 +
  byte-identical file).
- tests: adapt _external_notes_sources_enabled mock arity in
  test_3866_project_context_memory_section.py to the new snapshot param.
2026-08-04 11:46:32 -03:00
webtecnica 6dd1fed8d3 fix(ui): guard all bare _autoScrollFollow reads (#6614) 2026-08-01 17:52:30 -03:00
webtecnica f4f9157f8d fix: guard _autoScrollFollow access against ReferenceError before settings init
Browser race in static/ui.js: _autoScrollFollow can be undefined when
scroll/scrollpin listeners fire before boot.js initializes settings.
Bare global reference (ReferenceError) occurs on the golden path.

Fix: wrap both consumer sites with a typeof guard that defaults to
true (matching the boot.js fallback) when the variable hasn't been set.

Closes #6606
2026-08-01 17:45:43 -03:00