Commit graph

15949 commits

Author SHA1 Message Date
Ben Barclay
11eaa77daf fix(mcp): serialize hosted oauth reauthorization 2026-07-17 04:50:47 -07:00
Ben Barclay
b09f1ba770 fix(mcp): reject invalid dashboard oauth callbacks 2026-07-17 04:50:47 -07:00
Ben Barclay
05dea7be04 fix(mcp): complete OAuth through hosted dashboards 2026-07-17 04:50:47 -07:00
Teknium
14ea8de763 fix(agent): harden non-finite wait recovery
Only advertise finite watchdog deadlines that are still in the future, exercise the full MoA heartbeat path, and register the salvaged contributor attribution.
2026-07-17 04:46:59 -07:00
发飙的公牛
1a5d2a12d8 fix: handle infinite Codex wait deadlines 2026-07-17 04:46:59 -07:00
Teknium
6dcbcd0277
refactor(console): remove hosted-context command blocking from Hermes Console (#66144)
The dashboard console previously ran under a 'hosted' context that
blocked most commands (auth add, config set model.*, mcp add --command,
cron --script, ...) behind an allowlist + line-policy layer. With the
full Hermes CLI now built into the dashboard, that policy layer is
redundant gatekeeping: the console gets the same command surface
everywhere.

Removed:
- ConsoleContext/contexts plumbing on ConsoleCommand + engine
- EXPECTED_HOSTED_PATHS allowlist + _mark_hosted
- _enforce_hosted_line_policy + HOSTED_CONFIG_* allow/block tables
- _dashboard_console_context() and the context field on the ready frame
- hosted-context tests; context badge in HermesConsoleModal

Kept (mechanical, not policy): shell-syntax rejection, the
interactive/server command blocks (gateway, dashboard, mcp serve, ...),
mutating-command confirmations, output caps, and command timeouts.
2026-07-17 04:33:34 -07:00
Teknium
60419dfb4b fix(codex): reconcile app-server bridge with #38835, gate commentary on show_commentary
Follow-ups on top of @xxxigm's salvaged bridge (#33294):

- Remove the now-dead narrow item/started-only mapper from #38835
  (_codex_note_to_tool_progress) — the full bridge supersedes it and
  keeps the same tool-name contract; its tests are repointed at the
  bridge helpers.
- Preserve main's request_routing/approval-bypass wiring on the
  CodexAppServerSession constructor (landed after the PR was filed).
- Gate agentMessage interim delivery on display.show_commentary so the
  app-server runtime honors the same toggle as the codex_responses
  commentary channel (tool progress is unaffected).
- Add json import (bridge helpers use json.dumps) and modernize the
  wiring test's stub agent for main's usage-accounting attributes.
2026-07-17 04:32:56 -07:00
xxxigm
68d5368f38 test(codex): regression coverage for app-server event bridge (#33200)
42 tests across five suites:

* ``TestCodexItemToToolName`` / ``TestCodexItemToArgs`` /
  ``TestCodexItemToPreview`` / ``TestCodexItemCompletionPayload`` —
  pin the per-type mapping so the synthetic tool name + args the
  UI sees match what ``CodexEventProjector`` writes into messages.
* ``TestStreamDeltaDispatch`` / ``TestToolProgressDispatch`` /
  ``TestAgentMessageInterimDispatch`` — drive each Codex
  notification shape through the bridge and assert the right
  agent callback fires with the right arguments (including the
  duration / is_error / result kwargs the gateway renders).
* ``TestBridgeRobustness`` — defensive paths: non-dict
  notifications, missing params, raising callbacks (must not
  tear down the codex turn loop), and agents without callbacks
  registered (cron / gateway-less contexts).
* ``TestBridgeWiredInRuntime`` — integration guard that
  ``run_codex_app_server_turn`` actually constructs the session
  with ``on_event=<bridge>``, preventing a future refactor from
  silently regressing live progress visibility again.
2026-07-17 04:32:56 -07:00
xxxigm
7b63c4955a fix(codex): surface live tool-progress + commentary on app-server runtime (#33200)
Pass ``on_event=make_codex_app_server_event_bridge(agent)`` when
spawning the per-session ``CodexAppServerSession``. The session has
always had a raw event hook but ``run_codex_app_server_turn`` never
supplied one, so Discord / Telegram / TUI users saw nothing while
codex was working — only the final answer landed.

Now each ``item/started`` for a tool-shaped item fires
``tool_progress_callback("tool.started", ...)``, ``item/completed``
fires the matching ``"tool.completed"`` with duration + result,
``item/agentMessage/delta`` flows through ``_fire_stream_delta`` and
each completed ``agentMessage`` surfaces through
``_emit_interim_assistant_message`` so the gateway's
``already_streamed`` dedupe keeps interim commentary in the channel
without duplicating text the stream already showed.
2026-07-17 04:32:56 -07:00
xxxigm
e840cca1a9 feat(codex): add app-server event bridge for Hermes UI callbacks
Adds ``make_codex_app_server_event_bridge(agent)`` plus four small
mapping helpers (``_codex_item_to_tool_name`` / ``_codex_item_to_args``
/ ``_codex_item_to_preview`` / ``_codex_item_completion_payload``)
that translate codex JSON-RPC ``item/*`` notifications into the
exact shape Hermes' gateway UI callbacks expect — tool names match
``CodexEventProjector`` so the progress bubbles and the projected
``tool_calls`` entries use the same identifiers.

No behaviour change yet: the next commit wires the bridge into
``run_codex_app_server_turn`` (#33200).
2026-07-17 04:32:56 -07:00
slow4cyl
bd208a6d77 test(cron): public save_jobs()/load_jobs() post-import HERMES_HOME regression
Review follow-up: the store-internals tests proved _current_cron_store()
resolves lazily, but not that the PUBLIC job I/O honors it. This exercises
save_jobs()/load_jobs() after a late env repoint and asserts the
import-time jobs.json stays byte-identical to a planted sentinel.
2026-07-17 16:08:56 +05:30
slow4cyl
65d6bd2b9f fix(cron): patched compatibility constants take precedence over a repointed env
Review follow-up: tests that monkeypatch CRON_DIR/JOBS_FILE/OUTPUT_DIR (the
documented process-wide compatibility surface) were bypassed by the lazy
env fallback — 3 file-permission tests, the cross-process lock test, and
the heartbeat roundtrip regressed. _current_cron_store() now snapshots the
constants at import and honors any deliberate re-point of them ahead of
the env resolution, so the precedence is: use_cron_store() override >
patched constants > fresh HERMES_HOME > import defaults. Adds a test
pinning constants-beat-env; the late-env sentinel behavior is unchanged.
tests/cron: failure set byte-identical to unpatched main on this box
(the 5 regressions gone); 138 pass in the touched files.
2026-07-17 16:08:56 +05:30
slow4cyl
5c121f157f fix(cron): resolve the no-override store fallback lazily so late env repoints can't write the real jobs file
Complements ec0227b43 (context-scoped cron store): the ContextVar override
is the right tool for deliberate cross-profile scoping, but with no
override active, _current_cron_store() returned the import-time constants —
so a HERMES_HOME set AFTER cron.jobs import (the filed incident: test
fixtures patching the env too late) still read/wrote the user's real
jobs.json. The fallback now resolves the active profile home fresh via
get_hermes_home() (context-local override, then env) and scopes the store
to it; when the home is unchanged since import, the exact module-level
constants are returned as before (zero change in the common path, and they
remain the documented compatibility surface). use_cron_store() still wins.

Three tests: late env repoint scopes the store; unchanged home returns the
import-time constants identically; an active use_cron_store() override
beats the env.
2026-07-17 16:08:56 +05:30
Teknium
0f102fa4dc
feat(browser): store full snapshots on truncation; make eval denylist opt-in (#65923)
* feat(browser): store full snapshots on truncation; make eval denylist opt-in

Two harness fixes motivated by BU_Bench results where fixed-verb + lossy
observation cost Hermes heavily vs code-driven browser agents:

1. Snapshot truncation no longer loses content. When a snapshot exceeds
   the 8000-char threshold, the complete accessibility tree is saved to
   cache/web (same truncate-and-store pattern as web_extract) and the
   truncated view / LLM summary includes the file path plus a ready-made
   read_file call. Element refs beyond the cut are recoverable without
   re-snapshotting. Stored copies are force-redacted and capped at 2MB;
   content-hash filenames dedupe repeated snapshots of the same page.

2. The browser_console(expression=...) sensitive-primitive denylist is
   now opt-in via browser.restrict_evaluate (default false). The
   names-based denylist blocked legitimate DOM extraction — any selector
   or expression containing 'fetch', 'cookie', 'input', etc. — which
   crippled the agent's only programmatic page-inspection path. The
   SSRF/private-URL egress guards in _browser_eval are independent of
   this policy and remain always-on. browser.allow_unsafe_evaluate keeps
   its meaning (bypass the denylist) for configs that already set it.

* test: update None-guard test for stored-snapshot pointer in _extract_relevant_content

test_normal_content_returned pinned the exact return value; the summary
now carries a pointer to the stored full snapshot. Assert the summary
passes through and the pointer is present instead.

* feat(browser): align snapshot threshold with web_extract's 15k char budget

SNAPSHOT_SUMMARIZE_THRESHOLD 8000 -> 15000, matching
web_tools.DEFAULT_EXTRACT_CHAR_LIMIT so the snapshot and web_extract
truncate-and-store paths give the model the same per-page budget.
_truncate_snapshot's default max_chars now follows the constant.
Invariant test added; docs (en+zh) and CLI tip updated.
2026-07-16 23:41:26 -07:00
Teknium
779019ef7d feat(agent): add display.show_commentary toggle for Codex commentary channel
Commentary delivery is on by default; users who find the extra mid-turn
narration noisy can set display.show_commentary: false to restore the
previous behavior (commentary routed to the reasoning channel, visible
only with show_reasoning).

- hermes_cli/config.py: display.show_commentary default true
- agent/agent_init.py: wire config -> agent.show_commentary
- run_agent.py: gate structured commentary extraction on the flag
- agent/codex_runtime.py: gate live-stream commentary callback (falls
  back to legacy reasoning-channel routing when off)
- docs + 2 tests (interim path off, live stream fallback)

Also adds AUTHOR_MAP entries for davidrobertson and 100yenadmin.
2026-07-16 23:27:12 -07:00
Eva
7041c56cdf feat(agent): stream Codex commentary separately 2026-07-16 23:27:12 -07:00
Eva
b008131b54 fix(agent): harden Codex commentary interim delivery 2026-07-16 23:27:12 -07:00
David Robertson
a15397d61a fix(agent): redact Codex interim commentary 2026-07-16 23:27:12 -07:00
David Robertson
136ade2ed5 fix(agent): surface Codex commentary items as interim messages 2026-07-16 23:27:12 -07:00
kshitijk4poor
73ad9136b7 refactor(credentials): consolidate single-use OAuth refresh lock scaffolding
The openai-codex and xai-oauth branches of _refresh_entry duplicated the
lock-timeout computation and _auth_store_lock acquisition. Extract the
shared scaffolding: a combined provider guard, a dispatch to the
provider-specific sync helper, and a _single_use_refresh_lock_timeout()
helper. Each provider's distinct post-sync decision logic (codex
needs-refresh short-circuit vs xai token-equality adoption) is preserved
verbatim. Behavior parity verified by the credential pool suite (98
passed) and a direct timeout-helper probe for both providers.

Follow-up to salvaged PR #62285.
2026-07-17 11:37:25 +05:30
cresslank
34837597d2 fix(auth): make xAI OAuth pools multi-account resilient
Keep each xAI OAuth auth-add login as an independent manual device-code pool entry and recognize xAI personal-team spending-limit 403 responses as billing exhaustion. Preserve the structured top-level error message so the failed credential is quarantined and the next healthy account is selected without attempting a pointless token refresh.

Route direct xAI HTTP consumers through the credential pool as well. Proactive and 401-reactive refreshes update the exact issuing manual entry, preserve validated xAI base URL overrides, and serialize single-use refresh-token rotation across concurrent pool instances.
2026-07-17 11:37:25 +05:30
Thatgfsj
ef1c622105 fix(title): prevent stale background title generation from reloading unloaded Ollama models
Add a runtime_validator callback to generate_title() / auto_title_session()
/ maybe_auto_title(). Callers snapshot the session's model+provider when
spawning the background titler; the validator runs right before the LLM
request and skips it silently when the live runtime no longer matches —
so a stale title request can't reload a model that strict_single_load
already evicted after a user model switch. Fail-open: a raising validator
never disables titling.

Wired at all four call sites (cli, gateway, tui_gateway, acp_adapter).

Surgical reapply of PR #19137 (base was 8k+ commits stale; the original
patch predates the pinned-language prompts, the atomic-write helper, and
the moved TUI/ACP call sites). Original work by @Thatgfsj. Closes #19027.
2026-07-16 23:07:13 -07:00
Teknium
61be8b3112 chore(release): map seagpt noreply identity for PR #62983 salvage 2026-07-16 22:54:09 -07:00
Steven Seagondollar
ed2f48b2e6 fix(titles): use active runtime for gateway sessions 2026-07-16 22:54:09 -07:00
Teknium
7facf63ae7 fix(title): reconcile atomic auto-title writes with collision dedup retry
Combines the two salvaged fixes so they compose instead of conflict:
_persist_session_title (#50575) now writes through set_auto_title_if_empty
(#51483) when the store provides it — the collision-dedup retry and the
manual-/title race protection apply together. Predicate failure (a manual
title landed while generation was in flight) returns None: nothing written,
no callback. Legacy stores without the atomic method keep the plain
set_session_title path, including the vanished-session RuntimeError.

Tests cover both store shapes plus the race-skip path; E2E verified against
a real SQLite SessionDB (collision -> 'Weekly Report #2', manual title
preserved, cron dedup, blank guard). AUTHOR_MAP entry for rasitakyol.
2026-07-16 22:39:47 -07:00
Trevor Gordon
9bf5822a2f fix(cron): robust session title generation (#50535, #50536, #50537) 2026-07-16 22:39:47 -07:00
Raşit Akyol
d05cd7c1ef fix(agent): make auto-title write atomic 2026-07-16 22:39:47 -07:00
Raşit Akyol
f725cf830f fix(agent): avoid overwriting manual session titles 2026-07-16 22:39:47 -07:00
Teknium
46d16f4c28
fix(tui): recover mouse tracking without a resize via DECRQM watchdog (#66080)
When the terminal's own 'disable mouse reporting' toggle (or an external
app / tmux) clears the DEC mouse modes, a mouse-only user is deadlocked:
every existing recovery trigger (resize, >5s stdin gap + keypress,
raw-mode bounce) needs stdin — and mouse reporting being off is exactly
why no stdin arrives. Users had to resize the window to scroll again.

Fix: a mouse-mode watchdog in App that DECRQM-probes mode 1000 every 2s
while tracking is expected on. If the terminal reports the mode RESET,
reassertTerminalModes() re-arms tracking — the same recovery a resize
performs, without the resize. Probes are skipped whenever a mouse/wheel
event arrived within the interval (tracking provably alive → zero query
chatter during normal use), never fired while paused for an editor
handoff or when /mouse off was chosen, and the watchdog permanently
disables itself on terminals that don't answer DECRQM (DA1-sentinel
resolution via the existing timeout-free TerminalQuerier).

Terminals whose toggle merely gates event delivery report SET, so an
active user toggle is never fought; terminals whose toggle clears the
modes report RESET after re-enable and recover within ~2s.
2026-07-16 22:25:50 -07:00
Teknium
b170f522a4 test(honcho): align observer-resolution test with post-#62290 call shape
The salvaged test from PR #62982 asserted search_query=None as an explicit
kwarg; current _fetch_peer_context omits search_query when None.
2026-07-16 22:25:22 -07:00
Teknium
04d84df63c fix(honcho): memoize timeout staleness check + host-aware status cadence
Follow-ups for the consolidated salvage:
- Memoize the config.yaml-derived timeout on the file's mtime_ns so the
  rebuild-on-timeout-change check from PR #57437 costs one stat() per
  get_honcho_client() call instead of a full YAML load on the hot path.
- hermes honcho status now displays the host-block-resolved
  dialecticCadence (remnant from PR #63776, whose runtime fix landed
  in #62290).
- AUTHOR_MAP entries for the salvaged contributor emails.
2026-07-16 22:25:22 -07:00
liuhao1024
e5bebe2cad fix(plugins): rebuild Honcho client when timeout config changes
The Honcho client singleton cached the HTTP timeout at first build.
In long-lived processes (gateway, dashboard), changing the timeout
via config.yaml or HONCHO_TIMEOUT had no effect until restart.

Track the resolved timeout alongside the cached client and compare
on each get_honcho_client() call. When the timeout differs, reset
the singleton so the next call rebuilds with the new value.

Fixes #57347
2026-07-16 22:25:22 -07:00
Hermes Pi
73a4574ede fix(honcho): preserve profiles for local IP config 2026-07-16 22:25:22 -07:00
Hermes Pi
cd268c1226 fix(honcho): read base_url and defaultHost from honcho.json host blocks
Fixes Honcho client initialization for setup-generated configs that store
connection details in a named host block (e.g. "local"). Previously:
- base_url was only read from flat config root, not from host_block.
- resolve_active_host() ignored defaultHost and always used the Hermes
  profile key ("hermes"), so the host block lookup returned {} and the
  api_key was also lost.

Fixes NousResearch/hermes-agent#61661
2026-07-16 22:25:22 -07:00
vizi0uz
602998b76c fix(honcho): warn model away from minimal reasoning_level on multi-fact queries
honcho_reasoning's minimal tier hard-caps Honcho's dialectic output at 250
tokens combined with the model's own hidden reasoning tokens. Confirmed via
direct honcho-api server logs that a multi-fact query ("summarize known
facts about this peer and communication preferences") run at
reasoning_level=minimal gets cut off mid chain-of-thought at exactly
output_tokens=250, before the model ever reaches a synthesized answer.

low/medium/high/max fall back to Honcho's much larger global dialectic
default and don't hit this cap. Since dialecticDynamic is on by default and
the calling model picks reasoning_level itself via this tool parameter, the
fix is to make the tradeoff explicit in the parameter description so the
model defaults to low unless the query is genuinely a single-fact lookup.

Schema-description-only change; the shared dialectic_max_chars truncation
cap in session.py's dialectic_query() is a separate fix (its own PR).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 22:25:22 -07:00
RainbowAndSun
b08a13cd33 test: add prefetch_context observer-resolution test for ai_observe_others
Verify that get_prefetch_context queries user context through the
assistant observer when _ai_observe_others is enabled, matching
the fix that routes _fetch_session_context through
_resolve_observer_target.
2026-07-16 22:25:22 -07:00
RainbowAndSun
9a887e7c5b fix(honcho): use _resolve_observer_target for user context in session context
_fetch_session_context was using user_peer_id directly as observer
when calling _fetch_peer_context, bypassing _resolve_observer_target.
This caused honcho_context to return empty data because the observer
perspective was wrong (user instead of hermes/assistant).

Fixed by resolving observer via _resolve_observer_target(session, 'user'),
consistent with all other call sites (get_peer_card, honcho_search, etc.).
2026-07-16 22:25:22 -07:00
fjlaowan1983
af550a7053 fix(honcho): reject whitespace-only search/reasoning queries
Strip query before validation; add regression tests (aligns upstream #11192).

Made-with: Cursor
2026-07-16 22:25:22 -07:00
Teknium
8222b16785 fix(title): follow-ups for salvaged #37349 — lazy config import, guard ordering, config example
- Make the config imports lazy inside _auto_title_enabled(), matching the
  existing _title_language() pattern (title_generator is imported from agent
  code paths where a module-level hermes_cli import risks circularity).
- Check the enabled flag after the cheap first-exchange guard in
  maybe_auto_title so config isn't read on every turn of a long session.
- Repoint the two new tests at the real import site.
- Document the key in cli-config.yaml.example and merge the enabled flag
  into the existing title_generation block in configuration.md.
- AUTHOR_MAP entry for the contributor.
2026-07-16 22:24:45 -07:00
Danny Huang
e20c3c1c29 fix: honor disabled title generation config 2026-07-16 22:24:45 -07:00
Gille
7cb2d2cd4a
fix(auth): detect configured providers absent from registry (#66017)
* fix: detect env-var-configured providers absent from PROVIDER_REGISTRY

is_provider_explicitly_configured() only checked PROVIDER_REGISTRY (a
manually-maintained dict) for env-var names. Providers that exist solely
in the models.dev catalog — e.g. openrouter — were never recognised as
explicitly configured, so they were filtered out of the desktop model
picker even when their API key was set in .env.

Add a fallback to get_provider() (which reads the models.dev catalog)
when PROVIDER_REGISTRY returns None. Both ProviderConfig and ProviderDef
expose .auth_type and .api_key_env_vars with the same shape.

* test: keep OpenRouter provider gate assertion behavioral

* chore(release): map salvaged OpenRouter contributor

---------

Co-authored-by: zzpigpinggai <zzpigpinggai@users.noreply.github.com>
2026-07-16 22:56:45 -04:00
brooklyn!
629aeeebea
docs(developer-guide): document htui/hgui worktree UI dev helpers (#64783)
Add a developer-guide page for running the Ink TUI and Electron desktop
app from a git worktree without a full npm install per checkout, via the
htui/hgui shell helpers that share node_modules from a canonical deps
checkout by symlink (falling back to a local npm ci when the lockfile
diverges). Registers it in the sidebar, cross-links from the TUI and git
-worktrees pages, and documents the previously-undocumented
HERMES_DESKTOP_PYTHON / HERMES_DESKTOP_DEV_SERVER env vars the desktop
backend reads.
2026-07-16 22:51:23 -04:00
Gille
531e5763e8
fix(desktop): hide Windows updater console during handoff (#66040)
* fix(desktop): hide Windows updater console (#56884)

* test(desktop): cover hidden updater handoffs behaviorally

---------

Co-authored-by: Kyssta <218078013+kyssta-exe@users.noreply.github.com>
2026-07-16 22:50:40 -04:00
Gille
1f7d2be22f
fix(install): detect Git Bash Mandatory ASLR failures (#64651) 2026-07-16 22:46:46 -04:00
brooklyn!
c856f36459
perf(desktop): kill the layout-thrash cascade on session switch (#66033)
Follow-up to #65890 (router transitions off) and #65898 (structural
compare + first-paint budget): profiling the switch path on real 1000+-
message sessions with a new CDP harness showed the remaining freeze is
NOT markdown rendering — it's a forced-reflow cascade from mount-time
layout reads interleaved with style writes across the transcript's
layout effects, plus the first-paint budget cut landing too late to
stop the full-budget commit.

Measured on the two largest local sessions (996 and 1363 messages),
main-thread longtask totals per switch: warm 2450ms -> 557ms and
1158ms -> 194ms; first paint 1690ms -> 444ms. Harness:
scripts/profile-session-switch.mjs (same CDP family as
profile-real-stream.mjs).

- use-resize-observer: drop the synchronous initial callback and ride
  the observer's spec-guaranteed first delivery instead (same frame,
  after layout, before paint). The sync call ran while the commit's
  layout was dirty, so every size read in a callback forced a full
  reflow — with one instance per user bubble (measureClamp read
  scrollHeight, then WROTE --human-msg-full, re-dirtying layout for the
  next bubble), the switch commit thrashed for over a second. Inside RO
  timing the same reads are free. Composer metrics (2x
  getBoundingClientRect + documentElement style writes) rides the same
  fix.
- Same class, same fix at the remaining call sites profiling surfaced:
  ExpandableBlock and TerminalOutput (dozens per tool-heavy transcript)
  now measure/pin via RO initial delivery; the tool-window and
  thinking-preview pins drop their sync pin() call; the thread
  timeline's initial active-tick compute joins its existing
  scroll-time rAF batching so back-to-back transcript updates coalesce.
- thread/list: cut the render budget in the RENDER phase (state-from-
  props adjustment) instead of the post-commit layout effect. The
  effect-time cut was too late — on a warm switch React first built and
  committed the full 300-part tree, then re-rendered at 60, then bumped
  back to 300, so the expensive commit still happened (and on a cold
  switch the bump rAF usually fired while the transcript was still
  empty, so the prefetched messages rendered at full budget anyway).
  The render-phase cut restarts the component before any child renders;
  a second trigger handles the cold path where messages land later
  under the same sessionKey.
- thread/list: backfill 60 -> 300 inside startTransition so the older
  turns' markdown+shiki render is interruptible background work instead
  of a synchronous freeze one frame after the switch paints. Functional
  Math.max so an urgent "Show earlier" click can't be rebased back down.
- composer focus: skip the rAF/timeout focus retries when the element
  is already focused — focus() runs the full focusing steps (forcing
  layout) even on the active element, ~585ms per switch on a large
  dirty DOM.
- Replace the tautological render-budget test (it re-declared the
  constants locally and asserted 60 < 300) with behavior tests of the
  now-exported buildGroups + firstVisibleGroupIndex.

Verification: apps/desktop `npx tsc --noEmit` clean; full
`npx vitest run` 210 files / 1763 passed; manual CDP check confirms the
deferred backfill commits the full transcript, stays pinned to bottom,
and "Show earlier" still pages.
2026-07-16 22:46:08 -04:00
liuhao1024
3951d769fb fix(models): add kimi-for-coding-highspeed to kimi-coding provider list 2026-07-16 19:35:16 -07:00
SHL0MS
d57531b1a4 fix(unreal-mcp): pitfall 21b rewritten from live video production — hide sprites at source
Post-hoc sprite removal is a losing battle (three inpainting strategies
failed QC on letter-edge overlap frames). The production answer: sprites
are BillboardComponent/SpriteComponent/ArrowComponent subobjects — set
bVisible:false via ObjectTools (remove_component fails on default
subobjects), swept scene-wide in one ProgrammaticToolset script
(148 actors, 13 sprites, one round-trip, verified).
2026-07-16 19:30:22 -07:00
SHL0MS
665eaf1977 feat(unreal-mcp): video/frame-sequence pitfalls from live orbit production
21c: the viewport axis gizmo survives bShowUI=false — measured extent on
5.8, deterministic ffmpeg post-crop recipe. 21d: frame-sequence discipline
(one session, serial captures, idempotent resumable loop, s/frame budget,
smoothstep easing, VolumetricCloud artifact removal) — all from producing
a real 240-frame orbit through CaptureViewport.
2026-07-16 19:30:22 -07:00
SHL0MS
18694e96d8 feat(unreal-mcp): advanced-workflows layer, live-verified against UE 5.8
New references/advanced-workflows.md covering the sophisticated-workflow
surface, each section exercised against a running editor:

- ProgrammaticToolset batching: full contract (get_execution_environment
  gate, execute_tool fully-qualified names, JSON-string inputs,
  returnValue unwrapping, allowed imports) + a verified worked example
  (12-column colonnade, 36 components in one round-trip vs 37 serial calls)
- Blueprint DSL authoring loop, verified end-to-end: create -> list_graphs
  -> get_graph_dsl_docs -> find_node_types per node -> write_graph_dsl ->
  compile_blueprint -> spawn instance. Every node-ID gotcha hit live is
  recorded (EventTick not Tick, Math|Rotator|MakeRotator, registry
  categories vs doc categories, no (self) node)
- PIE session options schema (bSimulate/playMode/warmupSeconds/
  startTransform, out-of-process downgrade behavior)
- Sequencer orientation: 140-tool surface mapped by capability group +
  sibling keyframing/controlrig/conditions toolsets + minimal cinematic
  skeleton
- LogsToolset self-debugging, AutomationTestToolset CI loop,
  SemanticSearch, ConfigSettings, project AgentSkillToolset precedence
- Per-situation decision table

New pitfalls from this round's live failures: 10b (refPath-object vs
plain-string params; schema-in-error as tiebreaker), 10c (DSL node IDs
must come from find_node_types). SKILL.md: batching exception wired into
the operating loop, reference table row, description updated.
2026-07-16 19:30:22 -07:00
SHL0MS
ab818493ff fix(unreal-mcp): dedupe pitfall numbering (two sections numbered 4) 2026-07-16 19:30:22 -07:00