chore(desktop): upgrade @assistant-ui to 0.14 + use built-in streaming APIs (supersedes #51653) - #63970
Merged
Conversation
…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
force-pushed
the
bb/salvage-51653-assistant-ui
branch
from
July 15, 2026 05:44
e0ab1df to
6fc2465
Compare
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.
kshitijk4poor
self-requested a review
July 15, 2026 06:10
kshitijk4poor
approved these changes
Jul 15, 2026
This was referenced Jul 15, 2026
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.
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.
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:
@assistant-ui/react^0.12.28→^0.14.23and@assistant-ui/react-streamdown^0.1.11→^0.3.4; drops the@assistant-ui/storenpm override (tree resolves cleanly without it)appendOptimisticMessagewithmetadata.isOptimistic: true(public contract for off-branch eviction)SmoothStreamingText/DeferStreamingText/remend-tail/ math-delimiter helpers with built-indefer,smooth,tailBoundedRemend,normalizeMathDelimiters,escapeCurrencyDollarsMessageRenderBoundaryto match the renameduseClientLookupout-of-bounds throw (session-switch/reconnect blank)Salvage delta vs #51653:
main(~1.6k commits ahead of the original tip; auto-merged cleanly including the remote-artifact work inmarkdown-text.tsx)clarify-tool.test.tsx: addrespondToApprovalto the settled tool-part mock (required byToolCallMessagePartPropsin 0.14)Known acceptable deltas (documented in original review):
[/math]/[/inline]tags,$$5currency fix) — fixtures lock the new behaviorFollow-ups (out of scope): drop
IncrementalExternalStore*now that core has native incremental sync; optionally setmaxCharIntervalMs: 33if smooth cadence feels too fast.Test plan
cd apps/desktop && npx tsc -p . --noEmitnpx 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$$5x = 10$$,\(x^2\),$5 in my pocket,[/math]...[/math]**bold**/ backticks — frontier flicker acceptable