Skip to content

fmt(js): npm run fix auto-fix - #1

Open
github-actions[bot] wants to merge 1 commit into
mainfrom
bot/js-autofix
Open

fmt(js): npm run fix auto-fix#1
github-actions[bot] wants to merge 1 commit into
mainfrom
bot/js-autofix

Conversation

@github-actions

@github-actions github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown

Auto-generated by the auto-fix lint issues & formatting workflow. Auto-merges (squash) once CI passes. If CI fails or main moves, the PR is auto-closed and the branch deleted — the next run re-applies on the current state.

QuarkAssistant pushed a commit that referenced this pull request Aug 11, 2026
…rst run

The first-run provider picker showed Fireworks AI alongside Nous Portal
before the user opened the 'Other providers' disclosure. Only Nous Portal
should be visible up front; Fireworks now lives inside the expanded list
but keeps its #1 position there (Nous -> Fireworks ordering preserved).
QuarkAssistant pushed a commit that referenced this pull request Aug 15, 2026
Addresses both review findings on the remote-gateway download PR:

1. Unbounded buffering (finding #1). fetchBuffer / fetchBufferViaOauthSession
   accumulated the entire response (then copied it again via Buffer.concat)
   before saveGatewayFile even opened the save dialog, so a large gateway file
   could exhaust the native process. Both auth paths now stream: once response
   headers arrive the connect timeout is cleared, the filename is derived, the
   save dialog is shown, and the body is piped to the chosen destination with
   backpressure. A read/write error tears down the stream and unlinks the
   partial file. The byte-moving, data-URL decoding, and filename/path helpers
   are extracted into gateway-file-download.ts so they're unit-testable without
   Electron.

2. No fallback for older gateways (finding NousResearch#2). saveGatewayFile required the new
   /api/fs/download route. Desktop and the remote gateway update independently,
   so a gateway predating this PR 404s. Added a 404-only compatibility fallback
   to the existing capped /api/fs/read-data-url route (bounded, so it only
   serves smaller files — enough to keep older backends working).

Tests: gateway-file-download.test.ts covers streaming, backpressure,
error-cleanup (unlink on write/response error), data-URL decoding, filename
derivation (incl. traversal reduction), and 404 detection;
gateway-file-download-transport.test.ts asserts both transports stream (no
whole-body Buffer.concat) and that the 404 fallback is wired. Both registered
in the desktop platform test list. Server-side /api/fs/download tests
(streaming + sensitive-file reject) already pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
QuarkAssistant pushed a commit that referenced this pull request Aug 15, 2026
…-renders (NousResearch#81726)

The scoped find walker wraps transcript text nodes in <mark> elements that
React does not own. Assistant responses stream through markdown-text.tsx,
which rebuilds the markdown DOM on every delta, and a new message is
appended whenever the assistant answers — so a re-render of a changed
region detaches the marks we inserted, dropping the user's highlights while
the bar stays open.

Watch the captured scope with a MutationObserver and re-wrap only when an
unmarked occurrence of the active query actually reappears. The observer is
gated behind a re-entrancy flag while the walker is mutating, coalesced to
one re-apply per microtask, torn down when the bar closes or the query
clears, and restores the active ordinal so a mid-stream re-render doesn't
reset the user's place to match #1. An append that adds no matching text is
a no-op; re-wrapping only fires when highlights genuinely went stale.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
QuarkAssistant pushed a commit that referenced this pull request Aug 24, 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 NousResearch#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>
QuarkAssistant pushed a commit that referenced this pull request Aug 24, 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.
QuarkAssistant pushed a commit that referenced this pull request Aug 27, 2026
…teway route

Fixes NousResearch#92265 (proposed fix NousResearch#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.
QuarkAssistant 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).
QuarkAssistant 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.
QuarkAssistant 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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants