Skip to content

chore(desktop): upgrade @assistant-ui to 0.14 + use built-in streaming APIs (supersedes #51653) - #63970

Merged
OutThisLife merged 10 commits into
mainfrom
bb/salvage-51653-assistant-ui
Jul 15, 2026
Merged

OutThisLife merged 10 commits into
mainfrom
bb/salvage-51653-assistant-ui

Conversation

@OutThisLife

Copy link
Copy Markdown
Contributor

Summary

Supersedes #51653 (@okisdev). Cherry-picked the author's 8 commits onto current main (Harry Yep authorship preserved) and added one salvage fix for a type that 0.14 newly requires.

What it does:

  • Bumps @assistant-ui/react ^0.12.28 → ^0.14.23 and @assistant-ui/react-streamdown ^0.1.11 → ^0.3.4; drops the @assistant-ui/store npm override (tree resolves cleanly without it)
  • Inlines removed appendOptimisticMessage with metadata.isOptimistic: true (public contract for off-branch eviction)
  • Replaces custom SmoothStreamingText / DeferStreamingText / remend-tail / math-delimiter helpers with built-in defer, smooth, tailBoundedRemend, normalizeMathDelimiters, escapeCurrencyDollars
  • Broadens MessageRenderBoundary to match the renamed useClientLookup out-of-bounds throw (session-switch/reconnect blank)

Salvage delta vs #51653:

  • Rebased onto current main (~1.6k commits ahead of the original tip; auto-merged cleanly including the remote-artifact work in markdown-text.tsx)
  • clarify-tool.test.tsx: add respondToApproval to the settled tool-part mock (required by ToolCallMessagePartProps in 0.14)

Known acceptable deltas (documented in original review):

  • Math preprocess is a behavior-changing superset (double-backslash brackets, [/math]/[/inline] tags, $$5 currency fix) — fixtures lock the new behavior
  • Reasoning smooth path is final-state equivalent but can flash raw markdown at the typewriter frontier (cosmetic, reasoning-only)

Follow-ups (out of scope): drop IncrementalExternalStore* now that core has native incremental sync; optionally set maxCharIntervalMs: 33 if smooth cadence feels too fast.

Test plan

  • cd apps/desktop && npx tsc -p . --noEmit
  • npx vitest run --environment jsdom src/components/assistant-ui/markdown-text.test.ts src/components/assistant-ui/message-render-boundary.test.tsx src/components/assistant-ui/clarify-tool.test.tsx
  • Desktop: switch sessions mid-stream + disconnect/reconnect — app must not blank
  • Stop / regenerate / edit-and-resend / branch switch — no ghost empty assistant bubble
  • Math: $$5x = 10$$, \(x^2\), $5 in my pocket, [/math]...[/math]
  • Streaming reasoning with **bold** / backticks — frontier flicker acceptable

@OutThisLife
OutThisLife requested a review from a team July 13, 2026 20:48
@alt-glitch alt-glitch added type/refactor Code restructuring, no behavior change P3 Low — cosmetic, nice to have comp/desktop Electron desktop app (apps/desktop/*) dependencies Pull requests that update a dependency file labels Jul 13, 2026
okisdev and others added 9 commits July 15, 2026 01:41
…0.1 to 0.3

bumps @assistant-ui/react from ^0.12.28 to ^0.14.23 and
@assistant-ui/react-streamdown from ^0.1.11 to ^0.3.4. this crosses
two minor bumps on each package and unlocks the built-in defer, smooth,
and tail-bounded remend primitives for PR 2.

breaking change from core 0.2.x: MessageRepository.appendOptimisticMessage
was removed (assistant-ui#4162). inline the three steps it did (generateId
+ fromThreadMessageLike + addOrUpdateMessage) in
incremental-external-store-runtime.ts, and set metadata.isOptimistic so
the new off-branch eviction logic cleans up the placeholder correctly.

fromThreadMessageLike and generateId graduated to the public API in
0.14.22 (assistant-ui#4414), so they now import from @assistant-ui/react
instead of @assistant-ui/core/internal. ExportedMessageRepository in the
test file moves to the public import for the same reason. the remaining
internal imports (AssistantRuntimeImpl, BaseAssistantRuntimeCore,
ExternalStoreThreadListRuntimeCore, ExternalStoreThreadRuntimeCore,
hasUpcomingMessage) are runtime construction internals with no public
equivalent and stay on @assistant-ui/core/internal.

the @assistant-ui/store npm override is removed: all transitive ranges
now resolve to 0.2.18 without it.

verified: tsc --noEmit passes, vitest shows zero new failures (15
pre-existing, 792 passing, identical to baseline before the upgrade).
…h props

delete SmoothStreamingText, DeferStreamingText, and useSmoothReveal
(~174 lines) from markdown-text.tsx. the built-in defer and smooth
props on StreamdownTextPrimitive now handle the same work:

- defer: routes streaming text through useDeferredValue so markdown
  re-parsing runs at lower priority (typing/scrolling stay responsive)
- smooth: typewriter-style reveal via useSmooth with SmoothOptions
  { drainMs: 500, maxCharsPerFrame: 30, minCommitMs: 33 }, matching
  the old useSmoothReveal constants exactly

MarkdownTextContent (reasoning text) gets both defer and smooth.
MarkdownText (assistant text) gets defer only, matching the previous
behavior where text messages had no typewriter effect.

the internal pipeline order changes from smooth → defer → preprocess
to preprocess → smooth → defer (the built-in primitive runs preprocess
first). this is functionally equivalent: the tail-bounded remend repair
runs once on the full text instead of per revealed prefix, and the
smooth reveal operates on already-repaired markdown. end result is
identical.

verified: tsc 0 errors, eslint clean, vitest 0 new failures (15
pre-existing, 792 passing), manual verification of 6 streaming
scenarios (defer, smooth reveal, typing-while-streaming, code blocks,
math, long text performance).
…Remend

delete lib/remend-tail.ts (108 lines) and lib/remend-tail.test.ts (105
lines). the tailBoundedRemend export from @assistant-ui/react-streamdown
0.3.4 is algorithmically identical — same findRemendWindowStart boundary
scan, same fence/math tracking, same slice-and-repair strategy. the only
differences are improvements: the built-in handles \r (CR) in line
endings for Windows compatibility, and accepts an optional RemendOptions
parameter passed through to remend.

the import in markdown-text.tsx moves from @/lib/remend-tail to
@assistant-ui/react-streamdown. the call site
(preprocessWithTailRepair) is unchanged.

verified: tsc 0 errors, eslint clean, vitest 0 new failures (15
pre-existing, 786 passing — 6 fewer than before because the deleted
remend-tail.test.ts had 6 cases), manual verification of incomplete
markdown repair during streaming.
…zeMathDelimiters and escapeCurrencyDollars

delete the custom rewriteLatexBracketDelimiters and escapeCurrencyDollars
implementations from markdown-preprocess.ts (~40 lines). the built-in
exports from @assistant-ui/react-streamdown 0.3.4 are strict
improvements:

- normalizeMathDelimiters combines rewriteLatexBracketDelimiters (now
  handles double backslashes and trims body whitespace) with
  rewriteCustomMathTags (handles [/math]...[/math] and
  [/inline]...[/inline] tags that some models emit — new capability
  HA didn't have before)
- escapeCurrencyDollars excludes $ as a preceding character, so
  display math $$5 is no longer incorrectly escaped (bugfix)

the call site in preprocessMarkdown changes from
rewriteLatexBracketDelimiters(escapeCurrencyDollars(part)) to
normalizeMathDelimiters(escapeCurrencyDollars(part)).

verified: tsc 0 errors, eslint clean, all 16 preprocessMarkdown tests
pass (including currency dollar escaping), vitest 0 new failures,
manual verification of currency amounts, LaTeX bracket delimiters,
display math, and dollar signs inside code blocks.
…ssageRenderBoundary

@assistant-ui/store renamed its index-out-of-bounds throw from tapClientLookup/tapClientResource to useClientLookup in the 0.14 upgrade, so the boundary's /tapClient.../ filter stopped matching and re-threw the transient session-switch and reconnect race to root, blanking the app. broaden the regex to accept the new prefix (keeping the old one for older store versions) and point the test at the real message so it exercises the live path instead of the dead string.
…th swap

the parseIncompleteMarkdown comment implied the reveal frontier is repaired; repair runs on the full accumulated text, so reword it to say that. drop the now-dead "multiple surfaces render the same content" clause from the block-cache comment (the smooth and defer wrappers that caused it were removed), and trim the math-preprocess comment to the load-bearing prose-only constraint.
…reprocess swap

lock the four behaviors the built-in normalizeMathDelimiters/escapeCurrencyDollars introduce over the deleted custom helpers: $$<digit>$$ display math stays intact, double-backslash brackets and [/math]/[/inline] tag pairs rewrite to dollar delimiters, and currency dollars in prose are escaped. the existing preprocessMarkdown suite had no math cases.
…timistic placeholder

a reader of this subclass can't recover from hermes code alone that the metadata.isOptimistic flag drives core's off-branch eviction and export() omission, so a future core change to it would silently break placeholder cleanup. flagged in the upgrade review.
@assistant-ui/react 0.14 makes respondToApproval required on
ToolCallMessagePartProps; the settledClarifyProps helper still lacked it
after the upgrade cherry-picks, so tsc failed on clarify-tool.test.tsx.
@OutThisLife
OutThisLife force-pushed the bb/salvage-51653-assistant-ui branch from e0ab1df to 6fc2465 Compare July 15, 2026 05:44
kshitijk4poor
kshitijk4poor previously approved these changes Jul 15, 2026
The assistant-ui upgrade lockfile omitted standalone @esbuild/* packages.
CI runs npm ci --ignore-scripts, so esbuild's postinstall never runs and
desktop/ui-tui check (build:ink, bundle-electron-main) fail without them.
Graft the 26 platform packages from main's lockfile.
@OutThisLife
OutThisLife merged commit 9baa7d4 into main Jul 15, 2026
23 checks passed
@OutThisLife
OutThisLife deleted the bb/salvage-51653-assistant-ui branch July 15, 2026 06:10
liuhao1024 pushed a commit to liuhao1024/hermes-agent that referenced this pull request Jul 15, 2026
The 0.14 upgrade (NousResearch#63970) dropped the @assistant-ui/store override, so the
whole cluster de-hoisted from root node_modules into apps/desktop/node_modules
under a single shared tap@0.9.3. The test only looked at the root hoist path
(node_modules/@assistant-ui/tap), which no longer exists, and failed on main.

Resolve tap wherever npm places it (root or workspace-nested), and assert a
single shared version across all install sites — strengthening the invariant to
also catch a split tap install, not just split declared ranges.
OutThisLife added a commit that referenced this pull request Jul 15, 2026
The 0.14 upgrade (#63970) dropped the @assistant-ui/store override, so the
whole cluster de-hoisted from root node_modules into apps/desktop/node_modules
under a single shared tap@0.9.3. The test only looked at the root hoist path
(node_modules/@assistant-ui/tap), which no longer exists, and failed on main.

Resolve tap wherever npm places it (root or workspace-nested), and assert a
single shared version across all install sites — strengthening the invariant to
also catch a split tap install, not just split declared ranges.
OutThisLife added a commit that referenced this pull request Jul 15, 2026
The change classifier treated package.json / package-lock.json as
python-irrelevant, so a lockfile-only PR skipped the Python lane entirely.
But several Python invariant tests read these files (assistant-ui tap cluster,
electron pin, lazy-deps, lockfile churn) — so a lockfile change can break the
Python suite. #63970 merged green (Python skipped on the PR) then reddened main
(push fails open and runs everything).

Drop root npm from the _py_irrelevant denylist so lockfile changes run Python,
honoring the classifier's own contract: never skip a lane a change could break.
Root npm still triggers the frontend lane as before.
Gravezzz pushed a commit to Gravezzz/hermes-agent that referenced this pull request Jul 21, 2026
…653-assistant-ui

chore(desktop): upgrade @assistant-ui to 0.14 + use built-in streaming APIs (supersedes NousResearch#51653)
Gravezzz pushed a commit to Gravezzz/hermes-agent that referenced this pull request Jul 21, 2026
The 0.14 upgrade (NousResearch#63970) dropped the @assistant-ui/store override, so the
whole cluster de-hoisted from root node_modules into apps/desktop/node_modules
under a single shared tap@0.9.3. The test only looked at the root hoist path
(node_modules/@assistant-ui/tap), which no longer exists, and failed on main.

Resolve tap wherever npm places it (root or workspace-nested), and assert a
single shared version across all install sites — strengthening the invariant to
also catch a split tap install, not just split declared ranges.
randlee pushed a commit to randlee/hermes-agent that referenced this pull request Aug 11, 2026
…653-assistant-ui

chore(desktop): upgrade @assistant-ui to 0.14 + use built-in streaming APIs (supersedes NousResearch#51653)
randlee pushed a commit to randlee/hermes-agent that referenced this pull request Aug 11, 2026
The 0.14 upgrade (NousResearch#63970) dropped the @assistant-ui/store override, so the
whole cluster de-hoisted from root node_modules into apps/desktop/node_modules
under a single shared tap@0.9.3. The test only looked at the root hoist path
(node_modules/@assistant-ui/tap), which no longer exists, and failed on main.

Resolve tap wherever npm places it (root or workspace-nested), and assert a
single shared version across all install sites — strengthening the invariant to
also catch a split tap install, not just split declared ranges.
jh1nresh pushed a commit to jh1nresh/hermes-agent that referenced this pull request Aug 25, 2026
The change classifier treated package.json / package-lock.json as
python-irrelevant, so a lockfile-only PR skipped the Python lane entirely.
But several Python invariant tests read these files (assistant-ui tap cluster,
electron pin, lazy-deps, lockfile churn) — so a lockfile change can break the
Python suite. NousResearch#63970 merged green (Python skipped on the PR) then reddened main
(push fails open and runs everything).

Drop root npm from the _py_irrelevant denylist so lockfile changes run Python,
honoring the classifier's own contract: never skip a lane a change could break.
Root npm still triggers the frontend lane as before.
prmartinow pushed a commit to prmartinow/hermes-agent that referenced this pull request Aug 26, 2026
…653-assistant-ui

chore(desktop): upgrade @assistant-ui to 0.14 + use built-in streaming APIs (supersedes NousResearch#51653)
prmartinow pushed a commit to prmartinow/hermes-agent that referenced this pull request Aug 26, 2026
The 0.14 upgrade (NousResearch#63970) dropped the @assistant-ui/store override, so the
whole cluster de-hoisted from root node_modules into apps/desktop/node_modules
under a single shared tap@0.9.3. The test only looked at the root hoist path
(node_modules/@assistant-ui/tap), which no longer exists, and failed on main.

Resolve tap wherever npm places it (root or workspace-nested), and assert a
single shared version across all install sites — strengthening the invariant to
also catch a split tap install, not just split declared ranges.
melon-xf added a commit to melon-xf/hermes-agent that referenced this pull request Sep 3, 2026
…653-assistant-ui

chore(desktop): upgrade @assistant-ui to 0.14 + use built-in streaming APIs (supersedes NousResearch#51653)
melon-xf added a commit to melon-xf/hermes-agent that referenced this pull request Sep 3, 2026
The 0.14 upgrade (NousResearch#63970) dropped the @assistant-ui/store override, so the
whole cluster de-hoisted from root node_modules into apps/desktop/node_modules
under a single shared tap@0.9.3. The test only looked at the root hoist path
(node_modules/@assistant-ui/tap), which no longer exists, and failed on main.

Resolve tap wherever npm places it (root or workspace-nested), and assert a
single shared version across all install sites — strengthening the invariant to
also catch a split tap install, not just split declared ranges.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/desktop Electron desktop app (apps/desktop/*) dependencies Pull requests that update a dependency file P3 Low — cosmetic, nice to have type/refactor Code restructuring, no behavior change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants