fmt(js): npm run fix auto-fix - #1
Open
github-actions[bot] wants to merge 1 commit into
Open
Conversation
shannonsands
pushed a commit
that referenced
this pull request
Jul 20, 2026
…reaming Two real render-cost wins found by inspection (no behavior change): 1. Sidebar re-rendered on every stream token. $sessionStates is republished on every message delta (tens/sec during a turn), and the derived ID computeds ($workingSessionIds, $attentionSessionIds, $backgroundRunningSessionIds) allocated a fresh array each time. nanostores notifies on !==, so the whole ChatSidebar + every mounted row re-rendered per token even when the working/ attention/background set was unchanged. Return the previous array reference when the contents match → nanostores skips the notify unless the set actually changes. Turns streaming from O(visible rows)/token into O(0) for the sidebar. 2. Tool rows normalized the FULL uncapped detail every render. `looksRedundant` (lowercase + whitespace-collapse over the entire read_file/terminal payload) ran twice in the ToolEntry render body, so every completed tool re-normalized its whole output on every stream tick of the running message. Memoize on the view fields so it recomputes only when the tool's content changes. Both are correctness-preserving (stable refs + memoization). The CI stream scenario drives $messages directly, not the publishSessionState path, so it won't reflect #1 — verified by inspection.
github-actions
Bot
force-pushed
the
bot/js-autofix
branch
from
August 4, 2026 06:09
3da3610 to
67916cf
Compare
shannonsands
pushed a commit
that referenced
this pull request
Aug 17, 2026
Two independent bugs let a deleted profile reappear / leave orphaned resources on next launch: 1. hermes_cli/profiles.py's backend-process scanner required argv[0] to resolve to an executable literally named "hermes". Electron's pool-backend spawn resolves the hermes console-script shim's path and execs it via the interpreter directly (python3 /path/to/hermes ...), so argv[0] reports as "python3" and the scanner never matched the running backend -- delete removed the profile's files but left its live backend process running (still bound to a port via uvicorn), which accumulates across repeated delete/recreate cycles. 2. The desktop sidebar's ProfileRail only refreshed its cached profile list once, on mount, so a delete/create/rename from another surface (another window, or the CLI) left a stale ghost entry until something unrelated triggered a refetch. Note: a delete via this window's own Manage-Profiles view already refreshes the shared $profiles atom ProfileRail subscribes to (confirmed by reading refreshProfiles() and handleConfirmDelete()) -- this fix only covers the cross-window/cross- process staleness gap, not a duplicate of the already-merged NousResearch#57329's Manage-Profiles rail-refresh work. Fix 1: recognize a python-interpreter argv[0] exec'ing a hermes-named console-script shim via argv[1]. Fix 2: refresh the profile list on window focus/visibilitychange, matching the existing pattern used elsewhere in the sidebar (sidebar/index.tsx, use-background-sync.ts, star-map.tsx, use-gateway-boot.ts all use the same focus+visibilitychange pattern). ## Related work already on main PR NousResearch#57329 (merged) fixed the *headline* symptom from issue NousResearch#52279 (deleted profile respawns) via a different, non-overlapping mechanism: routing profile-delete through the primary backend instead of spawning a fresh pool backend, plus a separate recreation guard in ensure_hermes_home() (NousResearch#49435, merged) that makes a backend spawned into a deleted profile's directory raise FileNotFoundError instead of silently recreating it. This PR is NOT a duplicate of that fix. Verified: even with both of those merged, a backend process that survives because of gap #1 above still holds a bound port via uvicorn -- it just can no longer resurrect the profile directory. That's real resource-hygiene, not a symptom already covered. Gap #2 touches a different file/component (ProfileRail / profile-switcher.tsx) than NousResearch#57329's rail-refresh half (which touched the Manage-Profiles view's own $profiles.ts / index.tsx) and covers a distinct staleness path (cross-window/cross-process, not same-window delete-then-refresh). Tests: tests/hermes_cli/test_profiles.py -- 156 passed (existing + regression coverage for the argv[0] python-interpreter detection case). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
shannonsands
pushed a commit
that referenced
this pull request
Aug 21, 2026
posix.sh now probes `update --help` before the real update call; the fake counted the probe as call #1, shifting the exits.N mapping so the retry gate never fired. Answer the probe out-of-band so counted calls remain actual update attempts.
shannonsands
pushed a commit
that referenced
this pull request
Aug 27, 2026
…teway route Fixes NousResearch#92265 (proposed fix #2; #1 and NousResearch#4 are separate follow-ups, see below). ensureGatewayForAgent() and ensureGatewayForProfile() both decided whether a secondary activation "succeeded" by checking Boolean(entry.connection) alone. entry.connection is set in openSecondary() BEFORE the WebSocket dial completes (`entry.connection = conn` happens ahead of `await entry.gateway.connect(wsUrl)`), so a transient first-dial failure -- caught by the surrounding try/catch and left for scheduleReconnect's backoff retry -- still left entry.connection truthy. Both functions then treated this as a successful activation: applyActive() switched g.activeKey and published $gateway to the closed socket, and publishActiveConnection() pushed the connection descriptor to the UI. The next chat RPC then failed with "Hermes gateway is not connected" against a route the user/desktop believed was live. Added an isOpen(entry.gateway) check alongside the existing Boolean(entry.connection) check in both functions' activation/publish conditions, gating BOTH applyActive() (which switches g.activeKey and publishes $gateway) and publishActiveConnection() (which pushes the connection descriptor) on the socket having actually reached 'open'. A failed first dial now correctly returns false / leaves the previous active route untouched, matching option 3 from the issue's own proposed fix ("if both bounded attempts fail, keep the existing active route") -- the existing scheduleReconnect backoff still owns recovery for that entry going forward. Not implemented in this PR (separate, lower-priority follow-ups): - Proposed fix #1 (one immediate bounded reconnect attempt before returning activation status) -- a larger behavioral change with its own retry/timing tradeoffs; left to a separate PR. - Proposed fix NousResearch#4 (Bot Mode's own connection-ID-only guard in plugins/hermes-bots/plugin.js) -- host.ensureAgent() calls into the now-fixed gateway.ts functions, so this class of bug is already closed at the root; Bot Mode's own additional profile/state verification may still be worth adding but is a separate, narrower hardening pass on top of this fix. Found and fixed a genuine test-suite inconsistency while verifying: the existing "refreshes the active connection after a pooled profile reconnect succeeds" test in gateway-shared-remote.test.ts asserted setConnection was called once after a SINGLE ensureGatewayForProfile() call whose first dial failed -- i.e. it encoded the exact bug this issue reports as the EXPECTED, correct behavior. Rewrote it to assert the corrected contract: the failed first attempt does not call setConnection at all, and a realistic retry (calling ensureGatewayForProfile() again, since g.activeKey correctly never left the primary after the failed attempt -- ensureActiveGatewayOpen() is for reconnecting an already-active gateway that went stale, not retrying an activation that never succeeded) succeeds and publishes once the second dial goes through. Added a new test file (gateway-secondary-open-check.test.ts) following the established mocking pattern from gateway-agent-scope.test.ts, covering both ensureGatewayForAgent and ensureGatewayForProfile: a transient first-dial failure does not activate/publish (the exact reported symptom), and a successful dial still activates/publishes normally (sanity, no regression to the happy path). Verified as genuine regressions by reverting both isOpen() checks and confirming 2 of 4 new tests fail with exactly the reported symptom (activated resolves true / the primary gets replaced despite the failed dial). 44/44 pass across all 9 gateway-related test files (no regression). Dupe-swarm winner for issue NousResearch#92265; Biotrioo (PR NousResearch#92307) was the earliest submitter of the swarm and deserves first-report credit.
shannonsands
pushed a commit
that referenced
this pull request
Aug 27, 2026
fal's post-trained H3 variant — #1-ranked quality/prompt adherence/ aesthetics, 5s 768p video in under 3 seconds, $0.04/s launch pricing. - New minimax-h3-max family: minimax/h3-max/{text,image}-to-video - Inherits base-H3 wire quirks (integer duration, i2v drops aspect_ratio) but caps at 768P (480P/768P enums, no 2K/4K) and declares seed on both endpoints - New generic static_payload family flag: constant keys the endpoint requires on every request (H3 Max lists prompt_expansion_mode in its required array; sent as 'balanced') Payload asserted against the endpoint OpenAPI schema; 73/73 targeted tests green (surface matrix auto-covers the new family).
shannonsands
pushed a commit
that referenced
this pull request
Sep 2, 2026
… read Addresses teknium1's review (NousResearch#64195) finding #1: the previous PR placed the migration inside the connection IIFE, AFTER `resolveRemoteBackend(primaryProfileKey())`. When the preference file was missing, `primaryProfileKey()` resolved to 'default' and the remote branch returned immediately without ever reaching the migration. Remote- mode users got no migration at all. Move the call site to the top of `startHermes()`, before the connection IIFE that reads `primaryProfileKey()`. Both remote and local branches now flow through this path before any profile-dependent resolution, so the migration runs on first boot regardless of mode. The inlined implementation is replaced with a thin wrapper that builds a `MigrationDeps` bag and delegates to `migrateActiveProfileIfMissing` from `profile-migration.ts`. No production behavior change beyond the call- site move. Tests added in a separate commit.
shannonsands
pushed a commit
that referenced
this pull request
Sep 2, 2026
…reate Routing the branch create to the parent's owning connection was only half the job. The child then landed in the sidebar as a row that lied about who owned it, so the chat pane spun forever on "draft: branch #1" and never hydrated — the create was right, the row was wrong. upsertOptimisticSession stamps the row's profile from $activeGatewayProfile and omits connection_id entirely when no owner is passed (utils.ts:1318-1342), and it also skips setSessionOwnerHint. The branch call site passed no owner, so the child got NEITHER a row tag NOR a hint. resumeSession's owner ladder starts at `capturedOwner || getSessionOwnerHint(storedSessionId)` and forkBranch calls it without a capturedOwner, so the missing hint alone was enough to send the resume to whichever backend happened to be active. Pass the parent's route as the owner argument, restoring both mechanisms. The two sibling routed creates in this file already did exactly this. The tile path had the same defect one rung further out. A branch of a session that is not the open chat opens a tile instead of resuming, and SessionTileChrome resolved its owner from the tile route alone. openSessionTile is called for a branch child with no workspaceScope, and session-states.ts only persists a tile ownerRoute in bots mode, so that tile had no owner at all and its model + composer RPCs fell back to the ambient socket. Use the same tile-route-then-row ladder its sibling in session-tile-actions.ts already uses, resolved per render so it cannot go stale against the tile store, the recents/cron/messaging rows, or the hint map, with only the resulting identity memoised on primitives. An untagged parent row still reproduces the previous ambient behaviour exactly, so single-connection users are unaffected. Verified end to end against two real gateways: a session owned by a remote connection, branched through the actual sidebar context menu in a running dev app. The remote gateway served the create (ws closed ... messages=11 detached_sessions=1) and the resulting row polled stable at connection_id = the remote for the full 8s window. Before the fix the same gesture produced a row with no connection_id.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Auto-generated by the
auto-fix lint issues & formattingworkflow. Auto-merges (squash) once CI passes. If CI fails ormainmoves, the PR is auto-closed and the branch deleted — the next run re-applies on the current state.