88 KiB
@assistant-ui/core
0.2.20
Patch Changes
-
#4653
523e0b5- fix: skip malformed generative UI component nodes (@Kinfe123) -
Updated dependencies [
f833bc1]:- assistant-stream@0.3.25
0.2.19
Patch Changes
-
#4497
ddc40b7- fix: tolerate reasoning and image content blocks that omit their declared fields (@okisdev) -
#4466
ea52de0- refactor: add an internal createRuntimeExtras helper shared by external-store adapter authors (@okisdev) -
#4548
29c6fdb- feat(core): add shared client-side streaming timing primitive (useStreamingTiming+ purestepStreamingTiming) (@okisdev) -
#4543
d0987a3- external-store: addunstable_onBranchChangeadapter callback that fires on explicitswitchToBranch, emitting the canonical (persisted) head and visible message ids, deduped by head (@AVGVSTVS96) -
#4310
0c51b90- feat: addunstable_interactables API; restore and deprecate the previous interactables API (@AVGVSTVS96)The redesigned interactables API is now available as an additive
unstable_*surface for building editable, in-message UI while preserving the existing stable API for compatibility.unstable_useInteractable(name, config)registers an interactable and returns its state plus methods in one hook.- Each unstable interactable name gets one stable
update_{name}tool. When multiple instances share a name, the tool targets an instance byid. - Thread-scoped interactables rendered inside message parts expose
version, including the state for that message, whether it is the latest tool-driven version, andrestore(). - Added
unstable_interactableTool(...)for defining a creating tool and its in-message render UI together. - Added
unstable_useInteractableVersions(id, name)for version history UIs. - Persistence adapters can now provide
load()and be passed directly tounstable_Interactables({ persistence }).
The previous
useAssistantInteractable/useInteractableState/InteractablesAPI remains available unchanged and is marked deprecated. Existing apps do not need to migrate immediately.Migration notes for the unstable API:
- const id = useAssistantInteractable("taskBoard", config); - const [state, { setState }] = useInteractableState(id, initialState); + const [state, { id, setState }] = unstable_useInteractable("taskBoard", config);- Use
unstable_interactables: unstable_Interactables()when registering the unstable scope. unstable_useInteractableState(id)is intended for secondary readers and returnsundefineduntil the owner registers.- The unstable API uses per-name update tools (
update_{name}) with anidparameter instead of legacy per-instance tools (update_{name}_{id}). - A top-level
idfield instateSchemais reserved for instance addressing. Rename domain state fields toitemId,recordId, etc. if the model should edit them. - Model selection should be represented as ordinary state in the unstable API; the legacy
selectedregistration prop andsetSelectedmethod remain available on the deprecated stable API.
-
#4482
3a8f685- feat: addonThreadIdChangeto the remote thread list runtime sothreadIdcan be used as a managed/controlled value (e.g. synced to a URL). Only the settled remote ID is emitted; the transient optimistic local ID is never surfaced. (@Yonom) -
#4567
ec6adf4- fix: make PartPrimitive.Messages props a discriminated union so rendering with neither components nor children is a compile error (@ephraimduncan) -
#4542
4acd4c0- add unstable id-keyed thread message rendering APIs for virtualized and custom message lists.unstable_useThreadMessageIds()returns the thread's message ids (stable array identity across content-only updates), andThreadPrimitive.Unstable_MessageByIdrenders a single message by id with the same component surface asMessageByIndex. A missing or removed id rendersnullinstead of throwing. (@AVGVSTVS96) -
Updated dependencies [
cefcf27]:- assistant-stream@0.3.24
0.2.18
Patch Changes
-
#4426
68dfbaa- chore: markgenerateIdandfromThreadMessageLikeas experimental (@okisdev)these two utilities became public in #4414. they now carry an
@deprecatedJSDoc noting the API is experimental and may change without notice, matching how the other unstable public utilities (e.g.bindExternalStoreMessage) are flagged. the distribution packages (@assistant-ui/react,@assistant-ui/react-native,@assistant-ui/react-ink) re-export them, so the annotation lands in their published types too. -
#4420
fe24ad6- feat(react-ag-ui): apply external state fromThreadHistoryAdapter.load()(@dkachur1)onSwitchToThreadalready applies returnedstatevialoadExternalState, but the historyload()path did not, so state restored on a fresh page load was dropped.ThreadHistoryAdapter.load()may now return an optionalstate, andAgUiThreadRuntimeCoreapplies it — making both load paths symmetric.
0.2.17
Patch Changes
-
#4414
344f737- feat: exportfromThreadMessageLikeandgenerateIdfrom the public API (@okisdev)these two utilities were only reachable via
@assistant-ui/core/internal, so materializing aThreadMessageLikeinto aThreadMessage, or generating an id for a hand-built message, meant reaching into internals (the first-party ag-ui and a2a runtimes already did). they are now exported from@assistant-ui/core,@assistant-ui/react,@assistant-ui/react-native, and@assistant-ui/react-ink. also removes the now-redundant duplicate listing of both from the unstableINTERNALnamespace (the one in-repo consumer, the with-ffmpeg example, now uses the public export). -
#4415
a2e21ee- perf: sync the external-storemessageRepositoryincrementally instead of clear()+import() (@okisdev)when an
ExternalStoreAdapterdrives the thread viamessageRepository, each update tore the whole repository down (clear()) and rebuilt it from scratch (import()). it now diffs against the current repository (add or update incoming messages, delete the ones no longer present), so unchanged messages keep their existing per-message repository state instead of being recreated, and short-circuits when onlyisRunningflips on an unchanged repository reference. behavior is unchanged; this removes the teardown/rebuild churn on high-frequency streaming that previously pushed consumers to subclass the runtime core.
0.2.16
Patch Changes
-
#4392
4cc7eaa- chore: update peer and dependency ranges for @assistant-ui/tap 0.9 (@Yonom) -
Updated dependencies [
434bba5]:- assistant-stream@0.3.23
0.2.15
Patch Changes
-
#4367
c207bcd- feat: add reasoningEffort to LanguageModelConfig (@AVGVSTVS96) -
#4385
ae59baf- feat: precompile packages with React Compiler (@Yonom)- aui-build runs React Compiler over packages that depend on tap and remaps
react/compiler-runtimeto the tap shim subpath, so compiled hooks and components work both in React components and inside tap resource renders @assistant-ui/tap/react-shimexportsuseMemoCache(tap inside a resource render,React.__COMPILER_RUNTIME.cotherwise, with a React 18 polyfill); new@assistant-ui/tap/react-shim/compiler-runtimesubpath mirrorsreact/compiler-runtime'scexport- tap implements
useSyncExternalStoreand a no-opuseDebugValue;useSubscribablenow builds onuseSyncExternalStoreso its store reads stay visible to the compiler AssistantProviderBaseopts out via"use no memo"because the runtime receives options through an effect inside a re-rendered child element
- aui-build runs React Compiler over packages that depend on tap and remaps
-
#4378
4583ca7- feat: approval options vocabulary on tool approvals.ToolCallMessagePart.approvalgains request-suppliedoptions(machine-readable kinds allow-once / allow-always / reject-once / reject-always, open to_-prefixed custom kinds), a recordedoptionId, and a terminalresolution("cancelled" | "expired") for non-decision outcomes.respondToApprovaladditionally accepts{ optionId }, resolved in core against the option's kind; custom kinds require an explicitapproved.ExternalThreadgains anonRespondToToolApprovalcallback. The kit approval bar renders supplied options with an opt-in confirmation step showing the grants an option would persist. Persistence stays host-owned. (@okisdev) -
#4379
94cc028- feat: per-tool-call timing and stall detection.ToolCallMessagePartgains atimingfield ({ startedAt, completedAt? }in epoch ms), auto-populated by the assistant-stream accumulator at part start and result, and accepted onThreadMessageLikefor external-store hosts. NewuseToolCallElapsed()hook returns the call's elapsed milliseconds, ticking once per second while running;unstable_useMessageStallDetection({ thresholdMs })reports mid-run output stalls by watching a message content fingerprint. The kitToolFallbacktrigger renders the duration when timing is present. (@okisdev) -
Updated dependencies [
94cc028]:- assistant-stream@0.3.22
0.2.14
Patch Changes
-
#4340
ab8e5bc- fix: exclude reasoning parts from copied message text (@serhiizghama)getCopyTextfiltered parts with"text" in part, which also matchedreasoningparts (they carry atextfield), leaking the model's chain-of-thought into the clipboard. Both copy paths now delegate to the canonicalgetThreadMessageText, so copy returns onlytype: "text"content — consistent with the rest of the runtime. -
#4359
59d252f- feat: branch switching for the ExternalThread client (@okisdev)ExternalThreadaccepts an optionalbranchesadapter (ExternalThreadBranchAdapterin@assistant-ui/core, re-exported from@assistant-ui/react):getBranches(messageId)returns ordered sibling branch ids andswitchToBranch(branchId)makes a sibling visible by swapping themessagesarray. messages with more than one sibling get realbranchNumber/branchCount, which is what shows the branch picker;capabilities.switchToBranchis set for parity with the legacy external store. without the adapter, behavior is unchanged. -
#4347
feecac3- feat: support tool approvals on the local runtime (@okisdev)LocalRuntime.respondToToolApprovalpreviously threw "Local runtime does not support tool approvals". the local runtime now implements the approval gate natively, treating theChatModelAdapteras the server side of the protocol: the adapter emitsapproval: { id }on a tool call part and ends the run withrequires-action. a pending approval pauses the run (previouslyshouldContinueignored approvals, so an unlisted tool call carrying one re-invoked the adapter in a loop). denying records the decision and synthesizes an error result ({ error: reason || "Tool approval denied" }withisError: true, matching the AI SDK v6 denial shape); approving records the decision and resumes the run once every gate on the message is decided, with the decisions readable viaunstable_getMessage(). tool calls carrying an approval are exempt from theunstable_humanToolNamesresult requirement, and a gated call that receives a result viaaddToolResultcounts as resolved, so neither combination deadlocks.resumed runs (from
respondToToolApprovalandaddToolResultalike) now go through the same run loop asstartRun: they continue multi-step turns instead of stalling after one roundtrip, emitrunStart/runEndevents, mark the message queue busy so a concurrent send no longer aborts the in-flight roundtrip, and regenerate suggestions on completion.addToolResultalso notifies subscribers when it records a result without resuming.resumeToolCallstill throws, now with an error that points at the supported alternatives, and theunstable_humanToolNamesJSDoc no longer describes the pause as an approval (#4339). -
#4325
5a4f20e- chore: update @assistant-ui/tap dependency ranges to ^0.7.0 (@Yonom) -
#4328
f10b8ae- feat: exposelastMessageAton thread list items, populated from the cloud thread list adapter (@okisdev) -
#4351
1fb5862- fix: stable identity for grouped message parts across reorders (@okisdev)tool groups (and chain-of-thought groups) in
MessagePrimitive.Partsand group nodes inMessagePrimitive.GroupedPartsare now keyed by the id of their first part (toolCallId) instead of their positional index, and tool parts inside a group are keyed by their own id. when a message's parts array re-orders between live streaming and the settled shape, group and part React identity now survives the re-slice, so collapse/open state no longer resets. groups whose first part has no id keep their structural key, and duplicate ids fall back to structural keys, so keys stay unique.
0.2.13
Patch Changes
-
#4315
60ef0e9- feat: add runtime support for deleting messages (@Yonom) -
#4318
1b6a0d6- feat(tap): resources carry all hook arguments; elements are{ hook, args }(@Yonom)A
ResourceElementis now{ hook, args }(was{ type, props }): the underlying hook plus the full tuple of arguments to call it with. This lets a resource take multiple positional arguments, exactly like a hook, and makes hosting justhook(...args):const usePair = (a: number, b: string) => ({ a, b }); const Pair = resource(usePair); const element = Pair(1, "hi"); // { hook: usePair, args: [1, "hi"] }The single-object case is unchanged ergonomically (
Counter({ initialValue: 0 })still works; itsargsis just[{ initialValue: 0 }]), so existing resources and call sites are unaffected.resource()'s overloads collapse into one variadic signature, and thefnSymbol/callResourceFnindirection is gone (the element holds the hook directly;renderResourceFibercallsfiber.hook(...args)).Breaking (internal/advanced):
- The second type parameter of
Resource/ResourceElement/ContravariantResourcenow means the argument tupleA extends readonly unknown[]rather than a single payloadP. Explicit two-arg annotations must wrap the payload in a tuple (e.g.ResourceElement<R, [Props]>). - A resource's identity is now its hook. Reading
element.propsbecomeselement.args[0]; readingelement.typebecomeselement.hook.attachTransformScopesis now keyed by (and called with) the hook rather than the factory. useResource(element, deps)'s second arg is unchanged in behavior (renamedargsDeps).
- The second type parameter of
-
#4318
1b6a0d6- refactor: adopt the extracted-hook convention for resources (@Yonom)A resource body is a hook, so resources are now authored as a
use-prefixed hook wrapped withresource():const useCounter = () => { ... }; const Counter = resource(useCounter);resource()turns a hook into a Resource;useResource(Counter(props))turns it back into a hook call. Extracting the body to ause-prefixed hook lets React's stock rules-of-hooks and exhaustive-deps lint resource bodies directly. No public API or runtime behavior changes.
0.2.12
Patch Changes
- Updated dependencies:
- @assistant-ui/tap@0.6.1
0.2.11
Patch Changes
-
#4271
2a84174- feat: exposejoinStrategyonuseAISDKRuntime/useChatRuntime(@okisdev)the new AI SDK runtime always merged consecutive
role: "assistant"UIMessages into a single rendered turn, with no supported way to opt out (the converter acceptsjoinStrategybut the runtime never forwarded it, andAISDKMessageConverteris not exported). this follows up on #1633, where the same knob shipped on the legacyuseVercelUseChatRuntimeasunstable_joinStrategy. passjoinStrategy: "none"to keep proactive or history loaded consecutive assistant messages as separate turns.core now exports a shared
JoinStrategytype so the"concat-content" | "none"union has a single source of truth across the converter and the runtimes. -
#4255
a0a0769- feat: check the generative compiler version against the core package compatibility range (@Yonom) -
#4260
19c5b5f- fix: make defineToolkit usable for plain runtime toolkits (@Yonom) -
#4246
dbdfb15- feat: message queuing for external-store, langgraph, and local runtimes (@okisdev)the composer can now stay usable while a run is in progress: a message sent during a run is held in
composer.queue(rendered viaComposerPrimitive.Queue/QueueItemPrimitive.*) and processed once the run settles. external-store adapters opt in by providing aqueueadapter (typically built with the newcreateMessageQueuehelper);useLangGraphRuntimeanduseLocalRuntimeopt in viaunstable_enableMessageQueue.ExternalThreadQueueAdapternow lives in@assistant-ui/core(still re-exported from@assistant-ui/react). -
#4249
ca191dc- feat: add externalTool for render-only generative toolkit entries (@Yonom) -
#4256
44ff4bf- feat: rename hitlTool to humanTool while keeping deprecated compatibility aliases (@Yonom) -
#4245
26a365b- fix: makeSimpleTextAttachmentAdapterandSimpleImageAttachmentAdapterwork withoutFileReader. they read files via the browser onlyFileReader, so sending an attachment in a non browser runtime (e.g.@assistant-ui/react-inkin a terminal) threwReferenceError: FileReader is not defined. the adapters now feature detect: they keep usingFileReaderwhen it exists (browser, and React Native whose Blob polyfill provides it) and fall back tofile.text()/file.arrayBuffer()in Node. output is byte identical across all three environments, so@assistant-ui/react,@assistant-ui/react-native, and@assistant-ui/react-inkall keep re-exporting the same core implementation. (@ShobhitPatra) -
Updated dependencies [
15878d8]:- assistant-stream@0.3.21
0.2.10
Patch Changes
-
#4234
4145caa- fix: inferdefineToolkitstreamCall argument readers from Standard Schema parameters (@Yonom) -
#4212
5fe118d- feat: add MCP server support to generative toolkits (@Yonom) -
#4213
dcd5897- feat: add provider-executed tool support to generative toolkits (@Yonom) -
#4208
0558db2- feat: addupdateCustomto thread list runtimes, adapters, and clients (@okisdev) -
#4214
69540af- feat: add renderText helpers for tool call status text (@Yonom) -
#4199
d9b3119- feat: adefineToolkitentry may now be an already-formedToolDefinition(carrying its owntype), not only an inline definition whosetypethe compiler infers. This is what lets a factory likenew JSONGenerativeUI({ library }).present()be used directly as a tool. (@Yonom)Renames the authoring types to match
defineToolkit:ToolkitDeclaration→ToolkitDefinition, and addsToolkitDefinitionEntry(the union of an inline tool definition and a pre-formedToolDefinition). The per-tool inline type is now an internalToolkitDefinitionInputand is no longer exported. -
#4236
ae54c55- feat: addstubTool()and experimentaluseAuiToolOverrides()for locally executed generative toolkit tools (@Yonom) -
#4235
7640b31- Deprecate component tool registration APIs in favor of toolkit registrations. (@Yonom) -
Updated dependencies [
cba2b42,58f80e0,78ff336,5fe118d,dcd5897,ae54c55]:- assistant-stream@0.3.20
- assistant-cloud@0.1.31
- @assistant-ui/store@0.2.13
- @assistant-ui/tap@0.5.14
0.2.9
Patch Changes
-
#4176
27ae936- feat: add theToolkitDeclaration/ToolkitDeclarationDefinitiontypes for authoring a toolkit permissively (a backend tool may declaredescription/parameters/execute); the canonicalToolkitkeeps those fields erased. Author withdefineToolkit()from@assistant-ui/react, which the"use generative"compiler strips per build. (@Yonom) -
#4176
27ae936- feat: move thedefineToolkitandhitluse-generative markers from@assistant-ui/nextinto@assistant-ui/core/react, so they ship once from every distribution (@assistant-ui/react,@assistant-ui/react-native,@assistant-ui/react-ink) and stay portable across build targets. Import them from@assistant-ui/reactinstead of@assistant-ui/next; they remain no-op markers stripped at build time by a"use generative"compiler. (@Yonom) -
Updated dependencies [
27ae936]:- assistant-stream@0.3.19
0.2.8
Patch Changes
-
#4172
1315789- feat: add theToolkitDeclaration/ToolkitDeclarationDefinitiontypes for authoring a toolkit permissively (a backend tool may declaredescription/parameters/execute); the canonicalToolkitkeeps those fields erased. Author withdefineToolkit()from@assistant-ui/next, which the"use generative"compiler strips per build. (@Yonom) -
#4151
299d448- chore: drop stalebiome-ignorepragmas now that the repo lints with oxlint (@okisdev) -
#4136
4429aa3- centralize thread-level shared options forwarding across runtime wrapper hooks. follow-up to #4135. (@okisdev)new public exports from
@assistant-ui/core(re-exported from@assistant-ui/react):ExternalStoreSharedOptions, a typedPickoverExternalStoreAdaptercovering the four thread-level optional fields every wrapper forwards:isDisabled,isSendDisabled,unstable_capabilities,suggestions.pickExternalStoreSharedOptions(options), plucks those four fields from a wider options object. the body usessatisfies Required<...>so adding a key to the type without copying it in the function is a compile error rather than a silent missing-field bug.useExternalStoreSharedOptions(options)(from@assistant-ui/core/react), a memoized variant for wrappers that wrap their store inuseMemo. lets the wrapper list a single stablesharedreference as a dep instead of enumerating the four fields. samesatisfiesguard internally so the destructure stays in sync with the type.
internal: every runtime wrapper hook (
useChatRuntime,useAISDKRuntime,useLangGraphRuntime,useA2ARuntime,useAgUiRuntime,useAdkRuntime,useStreamRuntime,useOpenCodeRuntime) now uses these helpers instead of inlining the conditional spreads added in #4135. each wrapper sheds 20 to 40 lines of duplicated declarations and conditional spreads; future additions to the shared option set propagate through a single edit inpickExternalStoreSharedOptionsinstead of touching every wrapper. no user-facing behavior change. -
#4160
e76611f- feat: addindicatorsupport toMessagePrimitive.GroupedParts. (@Yonom)Restores loading-state handling that was dropped from the grouped renderer.
GroupedPartsnow emits a synthetic{ part: { type: "indicator" } }render call you handle withcase "indicator"in yourswitch (part.type)— render a "thinking…" dot or any loading affordance.- The indicator is only ever emitted while the message is running, so its presence alone means "render loading UI here" — there's no
statusto branch on. - New
indicatorprop restricts which running states qualify:"never","empty"(no parts yet),"no-text"(default — last part isn'ttext/reasoning, e.g. the model ended on a tool call), or"always"(any running state).
- The indicator is only ever emitted while the message is running, so its presence alone means "render loading UI here" — there's no
-
#4161
76f7d16- perf: memoize theRuntimeAdapterProvidercontext value so adapter consumers no longer re-render on every parent render whenadaptersis stable. (@Yonom) -
#4162
eef724e- fix: drop phantom sibling messages when an external store swaps an optimistic message id mid-run (#4037). (@Yonom)Messages can now be flagged
metadata.isOptimistic. Optimistic messages are treated as ephemeral: they only ever live on the current head branch (the repository evicts off-branch optimistic messages whenever the head moves) and they are never written to persisted state (export()omits them). The AI SDK v6 adapter flags the streaming assistant message as optimistic, so when its client-generated id is replaced by a server-provided one mid-run, the stale placeholder no longer lingers as a phantom branch (e.g.BranchPickershowing2/2on a turn the user never branched). Unlike the reverted blanket id-diff (#4040), only explicitly-optimistic messages are affected, so legitimateonEdit/onReload/switchToBranchbranches are preserved. -
#4167
fcb6baf- feat: add adisplaypresentation hint to tools and a"standalone-tool-call"key togroupPartByType. (@Yonom)Tool UIs fall into three buckets: prompting the user (human-in-the-loop), informing the user (generative UI), and traces of what the model is doing (routine frontend/backend tool calls). The first two should be surfaced on their own; the last belongs folded into the chain-of-thought trace. The new
displayfield on a tool lets you place a tool in the right bucket without overloadingtype:const toolkit = { ask_user: { type: "human", render: AskUI }, // standalone (forced — can't opt out) search_web: { type: "frontend", render: SearchUI }, // inline trace (default) checkout: { type: "frontend", render: CheckoutUI, display: "standalone", // opt in }, } satisfies Toolkit;display?: "standalone" | "inline"is a client-only presentation hint (it never reaches the model). Defaults to"inline".humantools are always"standalone"and cannot opt out (the type only allows"standalone"). MCP-app tool calls and the built-in generative-UI tool are standalone too. Every other tool defaults to inline and opts in explicitly.groupPartByTypegains a synthetic"standalone-tool-call"key that matches all of the above.MessagePrimitive.GroupedPartspasses the live tool-UI registry to thegroupByfunction as a secondcontextargument ({ toolUIs }), and the helper reads it to resolve the registry-driven cases; MCP-app calls are detected from the part alone.- The
"mcp-app"key ongroupPartByTypeis deprecated in favor of"standalone-tool-call"(a superset). It still works for back-compat.
The shadcn
thread.tsxtemplate is updated to use"standalone-tool-call": []in place of"mcp-app": []. -
Updated dependencies [
1315789,299d448,2dec3ae,fcb6baf,c4d3eea,331f2f7]:- assistant-stream@0.3.18
- @assistant-ui/store@0.2.13
- @assistant-ui/tap@0.5.14
- assistant-cloud@0.1.30
0.2.7
Patch Changes
-
#4121
7395092- feat: detect and diagnose duplicate@assistant-ui/coreinstalls (@Yonom)- In dev mode (
NODE_ENV !== "production"),@assistant-ui/corenow emits a singleconsole.warnwhen it detects a second copy of itself loaded into the same JavaScript runtime. Mismatched transitive versions are a common source of subtle bugs (lost tool registrations, broken context lookups, failedinstanceofchecks — see issue #4101). The warning points users atnpx assistant-ui doctor. - New
assistant-ui doctorCLI command. It walksnode_modulesrecursively (including nested copies), surfaces every duplicate version of any@assistant-ui/*,assistant-streamorassistant-cloudpackage, queries the npm registry for the latest versions and reports outdated installs. Use--no-networkto skip the registry check.
- In dev mode (
-
#4118
a6e0653- feat(core): build a client-side tool-invocations pipeline directly intouseExternalStoreRuntime. Tool-call parts in messages now firestreamCall/executeautomatically for any external-store runtime that opts in. Opt in per-adapter viaunstable_enableToolInvocations: true(off by default — most external-store runtimes either run tools server-side or already wire their own client-side dispatch path; double-firing is the risk). The_store.isLoadingflag signals when initial history is loaded: snapshots observed whileisLoading === trueare treated as historical (no fire), matching the contract that callers likeimportExternalStatealready rely on. Six in-tree runtimes (useAssistantTransportRuntime,useAISDKRuntime,useLangGraphRuntime,useStreamRuntime,useAgUiRuntime,useAdkRuntime) are migrated to the embedded tracker; the standaloneuseToolInvocationsReact hook is removed. AddsExternalStoreAdapter.setToolStatusesso adapters can mirror the tracker's per-tool-call status into local React state for converter metadata. Auto-aborts in-flight tool calls on new turns (append()withstartRun,startRun()) so a tool that finishes after the user moves on can no longer feed a stale result into the next turn. (@Yonom) -
Updated dependencies [
cabfc71]:- @assistant-ui/tap@0.5.13
- @assistant-ui/store@0.2.12
0.2.6
Patch Changes
-
#4120
372d4f0- feat: simplifyMessagePrimitive.GroupedPartsAPI and addgroupPartByTypehelper. (@Yonom)- New
groupPartByType({ ... })helper builds agroupByfrom apart.type → group-key pathlookup. The map keys are typed againstPartState["type"](autocomplete + typo rejection), missing keys leave the part ungrouped, and the returned function carries an internal memo fingerprint so the tree survives unrelated re-renders even when reconstructed inline. - Special map key
"mcp-app"matches tool-call parts that point at an assistant-ui MCP app resource (ui://...). It takes precedence over the"tool-call"entry for those parts, so MCP apps can be routed separately (e.g. rendered outside a chain-of-thought wrapper). groupBysignature simplified from(part, index, parts) => string | string[] | null | undefinedto(part) => readonly \group-${string}`[] | null. The 2nd/3rd args were unused in practice. Arrays are required (no bare-string shorthand);nullis accepted as an alias for[]` to soften the migration.- Internal memoization now uses the helper's memo fingerprint when present, otherwise rebuilds the tree per render (O(n), cheap). The previous "pass a stable reference" advice is dropped — inline
groupByis fine. - Docs and examples updated to lead with
groupPartByType. ThegetMcpAppFromToolPartbranch inpackages/uiswitches to"mcp-app": []via the helper.
- New
-
#4107
32ae846- feat: surface AI SDK v6 tool approvals as a first-classrespondToApprovalprop on tool components. tool-call parts in theapproval-requestedstate now carrypart.approval = { id, isAutomatic? }; tool components callrespondToApproval({ approved, reason? })to ack the gate without threadingchatHelpersthrough application context. also fixes a transientrequires-actionflicker for theapproval-respondedstate and tightens the external-message converter so interrupt vs pending tool calls are distinguished by an actualinterrupt/approvalfield rather than byresult === undefined. (@okisdev) -
Updated dependencies [
d4f1db4]:- assistant-stream@0.3.17
0.2.5
Patch Changes
-
#3967
0a0c306- feat(core, react): addMessagePrimitive.GenerativeUIprimitive (@samdickson22)A new first-class primitive for rendering agent-described React UI from a JSON spec, with a consumer-provided component allowlist as the security boundary.
The agent emits a new
generative-uimessage part containing a tree of components by name;MessagePrimitive.GenerativeUIwalks the spec and resolves each name against the registry you pass in. Unknown names throw a typedGenerativeUIRenderError(or invoke the optionalFallback). Composes withMessagePrimitive.Partsvia the newcomponents.generativeUIoption, and supports streaming partial specs.<MessagePrimitive.Parts components={{ generativeUI: { components: { Card, Button } }, }} /> -
#3651
6a0ecb2- feat(react-ink): add file storage adapter (@ShobhitPatra) -
#4072
e4634a5- fix(core): replay the latchedinitializethread event to late subscribers.ensureInitializedemitsinitializeonce during construction, so a runtime seeded with non-emptymessages(e.g.useChatRuntime({ messages })underuseRemoteThreadListRuntime) fired it before the title binder's effect subscribed, and therunEnd→generateTitlewiring was never installed.unstable_on("initialize", ...)now schedules a one-off replay (on a microtask, re-checking the subscription) when the thread has already initialized, mirroring a BehaviorSubject, so late subscribers (the title binder, andThreadViewport'sthread.initializetop-anchor reset) no longer miss it. (@okisdev) -
#3867
325de4c- relaxthread-message-likeimage validation to accepthttps://andblob:URLs (andsvg+xmldata URIs) alongside base64data:URIs, so assistant-authored images served from a URL render. (@samdickson22) -
#4099
f2ec01c- feat(core, react): opt-out of auto-unarchive when switching threads (@adityamohta)switchToThread(andThreadListItemRuntime.switchTo) now accept an optional{ unarchive?: boolean }argument. The default remainstrue, preserving the existing behavior of auto-unarchiving an archived thread when it becomes the main thread. Passunarchive: falseto keep the thread archived after switching — useful when the UI lets users preview an archived conversation without restoring it.// existing behavior — archived thread becomes regular await threadList.switchToThread(threadId); // new — keep status as archived await threadList.switchToThread(threadId, { unarchive: false }); // same option on the item runtime await threadListItem.switchTo({ unarchive: false }); -
Updated dependencies [
13a12c4,01244a5,1e21076]:- assistant-stream@0.3.16
- assistant-cloud@0.1.29
- @assistant-ui/store@0.2.12
- @assistant-ui/tap@0.5.12
0.2.4
Patch Changes
-
#4077
221d320- fix(core|MessageParts,GroupedParts): key part fibers by absolute part index (@Yonom)Inside
MessagePrimitive.GroupedPartsand the auto-groupedtoolGroup/reasoningGroupranges ofMessagePrimitive.Parts, leaf fibers were keyed by their structural position in the group tree rather than by the underlying part's absolute index. When the parts list reshaped (e.g., a thread switch with a different group layout), React reused the same fiber at a given structural slot but with a differentindexprop, keeping the prior tap subscription alive against an index that may now point at a different part or be out of range — surfacing astapClientLookup: Index N out of boundsorMessagePartText can only be used inside text or reasoning message parts. Keying by part index instead causes React to unmount the fiber when the part underneath actually changes.
0.2.3
Patch Changes
-
#4023
94548fa- docs: add JSDoc for core runtime and assistant tool APIs (@AVGVSTVS96) -
#3513
8b6fc88- fix: guardnavigator.clipboardavailability and swallow write rejections inActionBarPrimitive.Copy. Previously, copy clicks in SSR, non-HTTPS contexts, or older browsers without the Clipboard API threw aReferenceError, and permission-denied rejections surfaced as unhandled promise rejections. The web copyToClipboard implementation in@assistant-ui/reactnow early-rejects when the API is unavailable, anduseActionBarCopyin@assistant-ui/coresilently absorbs the rejection so the rest of the UI is unaffected. (@JustAnOkapi) -
#4057
179895f- fix(core): firestreamCallfor already-resolved tool calls observed after the initial snapshot, and promote in-progress tool calls from the initial snapshot once they change. Previously the runtime silently skippedstreamCallwhenever a tool-call part arrived already-resolved (history reload, thread switch, mid-run resume, PTC sub-call surfacing), forcing fragile render-effect fallbacks.executestays suppressed for these cases so side effects don't double-run. (@Yonom)Also collapses the per-tool-call ref soup inside
useToolInvocationsinto a single discriminatedToolCallEntrymap keyed by logical tool-call id, with execution-lifecycle bookkeeping tracked separately by physical stream id. RemovesignoredToolIds,lastToolStates,toolCallIdAliasesRefidentity entries, the parallelrestoredSignaturesRef/preResolvedToolCallIdsRef/startedExecutionToolCallIdsRefsets, and the early-return that suppressedstreamCallfor already-resolved tool calls.reset()semantics are unchanged; integrators that already callreset()on history reload don't need to change. -
#3958
7a8bf26- refactor: hoistMessagePartPrimitiveInProgressto@assistant-ui/core/reactso@assistant-ui/react,@assistant-ui/react-ink, and other distributions can share the same implementation.@assistant-ui/react'sMessagePartPrimitive.InProgressis unchanged for callers; it now re-exports from core. (@ShobhitPatra) -
#3636
3b2bbce- feat(core): expose modelName and toolNames in ModelContextState (@ShobhitPatra) -
Updated dependencies [
845c7c1,db721df,94548fa,94548fa]:- assistant-cloud@0.1.28
- @assistant-ui/store@0.2.11
- assistant-stream@0.3.15
- @assistant-ui/tap@0.5.11
0.2.2
Patch Changes
- #4024
19d4d94- feat: add native MCP Apps renderer —McpAppRenderercomposes intoToolsto render MCP UI resources inline in chat over a JSON-RPC postMessage bridge onSafeContentFrame. Adds anmcpfield toToolCallMessagePartand forwardscallProviderMetadata.mcp.appthrough the AI SDK message converter. (@Yonom)
0.2.1
Patch Changes
-
#3984
35d0146- feat(composer): exposecanSendstate andisSendDisabledadapter input (@okisdev)ComposerState.canSend(read-only) is now derivable viauseAuiState((s) => s.composer.canSend)and<AuiIf condition={(s) => s.composer.canSend}/>. it reflects whether the composer is in a state where send is permitted; cross-thread gating (isRunning,capabilities.queue) continues to be layered on top byuseComposerSend.ExternalStoreAdapter.isSendDisabledis a new optional input alongsideisDisabled. whentrue, the thread composer's input remains usable butsend()becomes a no-op andcanSendisfalse. use this to gate sending on external React state (e.g. while tool config is loading) without disabling the input itself. edit composers (saving in-progress message edits) intentionally ignore this flag, since it is a thread-scoped gate.BaseComposerRuntimeCore.send()now early-returns when!canSend, so theCmd/Ctrl+Shift+Entersteer hotkey, form-requestSubmit(), and directaui.composer().send()calls are all gated by the same flag. the same gating is wired through the tap-basedExternalThreadclient via a newisSendDisabledprop onExternalThreadProps. -
#4008
fa4510a- feat: support multi-modal tool results viatoModelOutput(@okisdev)frontend tools can now project their execution output into multi-modal model content (text + image / pdf / arbitrary file parts), aligning with the AI SDK v6
toModelOutputcallback. previously, tool results were always serialized as a single JSON value, so a "read pdf" style tool had no way to send the PDF back to a multi-modal model.assistant-streamexports a newToolModelContentParttype ({ type: "text", text } | { type: "file", data, mediaType, filename? }) and aToolModelOutputFunction<TArgs, TResult>callback type.Tool.toModelOutputis wired throughunstable_runPendingToolsandToolExecutionStream, attaching the resultingmodelContentto thetool-callpart on the assistant message.@assistant-ui/corere-exportsToolModelContentPartand adds an optionalmodelContent?: readonly ToolModelContentPart[]field onToolCallMessagePart. existing tools and renderers are unchanged.@assistant-ui/react-ai-sdk'sfrontendTools(...)helper now also registers atoModelOutputon each forwarded tool. it transparently unwraps an envelope thatuseAISDKRuntimewrites when a frontend-executed tool producedmodelContent, turning it into AI SDK's{ type: "content", value: [...] }output. plain (non-envelope) outputs fall back to the existing{ type: "text" | "json", value }shape, so behavior for tools withouttoModelOutputis unchanged.
route handlers that adopt
toModelOutputalso need to passtoolstoconvertToModelMessages(this is the AI SDK's documented pattern):const aiSDKTools = { ...frontendTools(tools ?? {}) }; streamText({ messages: await convertToModelMessages(messages, { tools: aiSDKTools }), tools: aiSDKTools, });templates and existing examples are unchanged. they keep the simpler
convertToModelMessages(messages)form because none of the tools they ship with usetoModelOutput. the new tools guide page documents how to opt in.reserved key. when a frontend tool defines
toModelOutput, its result is persisted in the AI SDK chat as{ __aui_modelContent: ToolModelContentPart[], value: <your result> }. tools must not return objects whose top-level key is literally__aui_modelContent, orconvertMessagewill misread the result. the prefix is namespaced for this reason.read/write compatibility for persisted threads. the envelope is recognized by
@assistant-ui/react-ai-sdkfrom this version onward. if you persist UI messages and read them from multiple environments, upgrade every reader before any writer starts producingtoModelOutput; otherwise older readers will treat the envelope object as theresultand break the affected toolrenderfunctions. -
#3972
c9dd16c- fix:useExternalStoreRuntimeno longer crashes with "Entry not available in the store" when the adapter setsthreadIdto a value that isn't present inthreads/archivedThreads. The runtime now synthesizes a regular thread item formainThreadId, so thin adapters (e.g.useAgUiRuntime) that only exposethreadIdresolve correctly on first render and after switching threads. Closes #3971. (@okisdev) -
#3674
dea8bc7- fix(core): guard MessagePrimitive.Attachments against missing user message attachments (@cewinharhar) -
#3634
9c3d24d- Support AI SDKsource-documentparts by preserving them as assistant-ui (@sicko7947) document source message parts across conversion and cloud serialization, including the legacy React cloud encoder. -
Updated dependencies [
9ecda1d,fa4510a]:- assistant-stream@0.3.14
0.2.0
Minor Changes
-
#3970
040d469- chore: drop APIs deprecated in v0.11/v0.12 (@Yonom)See the v0.14 migration guide for the full removal list and replacements.
useAssistantApi/useAssistantState/useAssistantEvent/AssistantIfremoved (useuseAui/useAuiState/useAuiEvent/AuiIf).getExternalStoreMessage(singular) removed (usegetExternalStoreMessages).MessageState.submittedFeedbackremoved (usemessage.metadata.submittedFeedback).ThreadRuntime.startRun(parentId)positional overload removed (pass{ parentId }).ThreadRuntime.unstable_loadExternalStateremoved (useimportExternalState).ThreadRuntime.unstable_resumeRunremoved (useresumeRun).ThreadRuntime.getModelConfigremoved (usegetModelContext).AssistantRuntime.threadList/switchToNewThread/switchToThread/registerModelConfigProvider/resetremoved (usethreads/threads.switchToNewThread/threads.switchToThread/registerModelContextProvider/thread.reset).ChatModelRunOptions.configremoved (usecontext).useLocalThreadRuntimealias removed (useuseLocalRuntime).unstable_useRemoteThreadListRuntime/unstable_useCloudThreadListAdapter/unstable_RemoteThreadListAdapter/unstable_InMemoryThreadListAdapteraliases removed (drop theunstable_prefix).react-langgraphonSwitchToThreadremoved (useload).toAISDKTools/getEnabledToolsremoved (usetoToolsJSONSchemafromassistant-stream).
0.1.18
Patch Changes
-
#3953
7098bab- Add cursor-based pagination to the thread list.RemoteThreadListAdapter.list()accepts an optional{ after }cursor and may returnnextCursoron the response. The runtime exposesloadMore(),hasMore, andisLoadingMorethrough both the legacyThreadListRuntimeAPI and the tap-onlyaui.threads()path;ThreadListRuntimeCore.loadMore?(),hasMore?, andisLoadingMore?are optional, so non-paginating cores (local, external-store, single-thread, in-memory) remain conformant. (@okisdev)@assistant-ui/reactships a matchingThreadListPrimitive.LoadMorebutton built oncreateActionButton, plus auseThreadListLoadMoreprimitive hook. Consumers wanting anIntersectionObserversentinel can reads.threads.hasMore/isLoadingMorefromuseAuiStateand callaui.threads().loadMore()directly.In-flight
loadMore()calls dedup via a single promise. The existing_loadGenerationcounter drops stale append callbacks when areload()interleaves aloadMore(). The loadMore reducer captures the active adapter so a mid-flight adapter swap cannot leak a stale page. Empty-stringnextCursoris normalised toundefined.reload()pre-clears the cursor so consumers readinghasMoredirectly during a reload do not observe a stale value.Adapter rejections are surfaced via
console.errorin both the initial-load andloadMorepaths, matching the pattern inRemoteThreadListHookInstanceManageranduseToolInvocations. -
Updated dependencies [
b090acb,5fdf17e]:- assistant-stream@0.3.13
- @assistant-ui/store@0.2.10
- @assistant-ui/tap@0.5.11
- assistant-cloud@0.1.27
0.1.17
Patch Changes
-
#3916
0bbf5dd- chore: drop./*wildcard export and surface internal attachment status types (@Yonom)The
./*wildcard inexportswas exposing the entire dist tree as importable subpaths, which inadvertently leaked internal modules (e.g.@assistant-ui/core/tests/*,@assistant-ui/core/types/*) as public API. Removing it.Two attachment status types that were previously only reachable through the wildcard (
PendingAttachmentStatus,CompleteAttachmentStatus) are now re-exported from the package root so that consumers' inferred types remain portable. -
#3917
98f165c- feat: enrichcomposer.attachmentAddErrorevent with typed payload (@okisdev)The event now carries
{ reason, message, attachmentId?, error? }so subscribers can branch on the failure mode (no-adapter/not-accepted/adapter-error). The bridge no longer relies on afindLastheuristic to recover the failed attachment id.Several state-derivable events are now annotated
@deprecatedbecause they duplicate state observation:composer.send,composer.attachmentAdd,thread.runStart,thread.runEnd,thread.initialize,threadListItem.switchedTo,threadListItem.switchedAway. They continue to fire for backward compatibility; new code should observe state viauseAuiStateinstead. -
#3914
62ec5bd- fix: add typesVersions to support moduleResolution: node (@shashank-100)Users with
moduleResolution: nodein their tsconfig were seeingProperty 'message' does not exist on type 'AssistantState'because theexportsmap sub-paths (e.g.@assistant-ui/core/react) are ignored by legacy node module resolution. AddingtypesVersionsmakes TypeScript resolve sub-path types correctly under all moduleResolution modes. -
#3853
6a919c1- feat: add<MessagePrimitive.GroupedParts>for hierarchical adjacent grouping of message parts (@Yonom)Introduces a new primitive that coalesces adjacent parts into groups via a user-supplied
groupBy(part) → "group-…" | readonly "group-…"[] | null. Adjacent parts sharing a key-path prefix coalesce up to that prefix; ungrouped parts render as direct leaves.The render function takes
{ part, children }and dispatches on a singleswitch (part.type)."group-…"cases wrapchildren(the recursively-rendered subtree); real part types ("text","tool-call","reasoning", …) render the part directly with the sameEnrichedPartStateenrichments (toolUI,addResult,resume,dataRendererUI) that<MessagePrimitive.Parts>provides.GroupPartis intentionally minimal:{ type, status, indices }. The render function is invoked once per group node and once per individual leaf part, so users never have to nest a<MessagePrimitive.Parts>call.The
groupByreturn type is constrained to`group-${string}`so the unified switch can never collide with a real part type. The component infers a literalTKeyper call site, sopart.typenarrows to the exact union of group keys plus part types.For leaf parts,
childrenis a sentinel that throws if rendered — accidental fall-through likedefault: return children;errors loudly instead of silently rendering nothing. Returningnullfrom a leaf case is fine.Deprecates the legacy
components.ToolGroup,components.ReasoningGroup, andcomponents.ChainOfThoughtprops on<Parts>, and<MessagePrimitive.Unstable_PartsGrouped>for adjacent grouping — all still work for backwards compatibility.
0.1.16
Patch Changes
-
#3895
549037a- fix(core): emit attachmentAddError when no adapter is configured or file type is rejected (@okisdev) -
#3896
976aec5- fix(core): respectadapter.acceptwhen adding externalCreateAttachment(@okisdev)composer.addAttachmentpreviously bypassed the configuredAttachmentAdapterforCreateAttachmentdescriptors, including theadapter.acceptcontent-type check. It now validates the descriptor'scontentType(or filename extension) againstadapter.acceptwhen an adapter is configured, throwing and emittingcomposer.attachmentAddErroron mismatch. Without an adapter, external attachments are still added as-is, preserving the existing "no adapter required" guarantee for external sources. -
#3716
25b97d5- fix(core): show loading state for empty parts children API (@ShobhitPatra) -
#3891
2008fc9- fix(core): hoist remote thread runtime binder out ofunstable_Provider(@okisdev)RemoteThreadListAdapter.unstable_Provideris now allowed to render any subtree it likes; the runtime binding (composer state,__internal_setGetInitializePromise,runEnd → generateTitlelistener) executes outside it. This fixesEMPTY_THREAD_ERRORwhen the Provider deferschildren(e.g. behind a history-loading state) and avoids the history-switch regression seen when only the binder, but not the init listeners, were hoisted. Adds a dev-mode warning when the Provider does not renderchildrenwithin ~100ms. -
#3889
88fcd35- feat: addcustomslot toRemoteThreadMetadataandThreadListItemState(@okisdev)allows adapter authors to carry arbitrary backend session data through
list()/fetch()and surface it on the thread list item state. matches the existingcustom: Record<string, unknown>convention used onThreadMessage,RunConfig, andChatModelRunResult. consumers can intersect a typed shape at their own boundary, e.g.RemoteThreadMetadata & { custom: { workspaceId: string } }. -
Updated dependencies [
005f83f]:- @assistant-ui/store@0.2.9
- @assistant-ui/tap@0.5.10
0.1.15
Patch Changes
-
#3857
c7a274e- fix(core): edit composer no longer re-injects original file parts when user message attachments are modified. Non-text content parts on user messages are lifted into_attachmentsso attachment removals take effect and files aren't duplicated on resend; non-user messages keep the existing content pass-through. (@okisdev) -
#3796
ca8f526- feat(react-langgraph): add uiComponents option for static and dynamic data renderers (@ShobhitPatra)Add
uiComponentsoption touseLangGraphRuntimefor registering static data renderers by name and afallbackrenderer for dynamic loading (e.g. LangSmith'sLoadExternalComponent), directly from the runtime hook.Core
DataRenderersscope also gains afallbacksstack (plussetFallbackDataUImethod) that the adapter registers into; resolution isrenderers[name][0]→fallbacks[0]→ inlineFallback. -
#3873
c56f98f- feat(core): addreload()method onThreadListRuntimeandaui.threads()that re-invokes the remote adapter'slist()and refreshes the thread list. Use this after asynchronous auth (e.g. OIDC, better-auth) completes to recover from an initial load that ran before the authenticated user was available. A generation counter ensures a mid-flight response from a superseded load cannot overwrite a newer reload's state. (@okisdev) -
#3855
974d15e- fix:useExternalStoreRuntimenow correctly initializesmainThreadId,threadIds, andarchivedThreadIdsfrom the adapter on first render. Previously they stayed atDEFAULT_THREAD_IDuntil the user switched threads, soisMainwasfalseon initial load. Closes #2577. (@okisdev) -
#3859
4b19d42- fix(core):switchToThreadcould duplicate a thread or leave it in boththreadIdsandarchivedThreadIdswhen it raced withlist(). Both arrays are now filtered before the status-keyed append, matching theupdateStatusReducerpattern. (@bilaltahseen) -
#3858
da0f598- fix:useAISDKRuntimenow throws when the suppliedThreadHistoryAdapteromitswithFormat, instead of silently dropping all history load/append/update calls. The optional-call chainhistoryAdapter.withFormat?.(…).load()previously short-circuited toundefined. ThewithFormat-wrapped adapter is now memoized, and the persist effect short-circuits when no adapter is supplied (avoiding a redundant thread subscription).ThreadHistoryAdapter.withFormatgains a JSDoc note clarifying that it is required on the AI SDK path. (@okisdev) -
#3831
d53ff4f- chore: remove decorative separator comments across packages (@okisdev) -
#3872
20f8404- feat(core): let runtimes provide an explicitisRunningthat overrides the last-message-status heuristic.ExternalStoreAdapter.isRunningnow flows through tothread.isRunningdirectly, so applications can keep the thread in a running state even after the last assistant message has completed (e.g. while non-message stream chunks like suggestions, step-finish, or metadata updates are still arriving). When a runtime does not provideisRunning, the previous last-message-based behavior is preserved. (@okisdev) -
#3834
17958c9- refactor: unify mention/slash under behavior sub-primitives; delete Mention/SlashCommand aliases and theexecutefield onUnstable_TriggerItem; split TriggerPopoverResource; rename react-lexicalMentionNode/MentionPlugin/MentionChipProvider/mentionChipprop toDirectiveNode/DirectivePlugin/DirectiveChipProvider/directiveChip; fix IME/Unicode/copy-paste/undo bugs. Breaking (Unstable_APIs): replaceonSelect={{type:"insertDirective",formatter}}with<Unstable_TriggerPopover.Directive formatter={...}>; replaceonSelect={{type:"action",handler}}with<Unstable_TriggerPopover.Action onExecute={...}>. Renameunstable_useToolMentionAdapter→unstable_useMentionAdapterwith newitems/categories/includeModelContextToolsoptions.unstable_useSlashCommandAdapternow returns{ adapter, action }—executestays in the hook closure instead of on the item. Rename CSS classaui-mention-chip→aui-directive-chipand attributesdata-mention-*→data-directive-*. (@okisdev) -
Updated dependencies [
ce865bc,055dda5,d53ff4f]:- assistant-stream@0.3.12
- assistant-cloud@0.1.27
- @assistant-ui/store@0.2.8
- @assistant-ui/tap@0.5.9
0.1.14
Patch Changes
- f20b9ca: feat: add ExportedMessageRepository.fromBranchableArray() for constructing branching message trees from ThreadMessageLike messages
- c988db8: chore: update dependencies
- Updated dependencies [c988db8]
- assistant-stream@0.3.11
- assistant-cloud@0.1.26
- @assistant-ui/store@0.2.7
- @assistant-ui/tap@0.5.8
0.1.13
Patch Changes
-
42bc640: feat: support edit lineage and startRun in EditComposer send flow
- Add
SendOptionswithstartRunflag tocomposer.send() - Expose
parentIdandsourceIdonEditComposerState - Add
EditComposerRuntimeCoreinterface extendingComposerRuntimeCore - Bypass text-unchanged guard when
startRunis explicitly set ComposerSendOptionsextendsSendOptionsfor consistent layering
- Add
-
87e7761: feat: generalize mention system into trigger popover architecture with slash command support
- Introduce
ComposerInputPluginprotocol to decouple ComposerInput from mention-specific code - Extract generic
TriggerPopoverResourcefromMentionResourcesupporting multiple trigger characters - Add
Unstable_TriggerItem,Unstable_TriggerCategory,Unstable_TriggerAdaptergeneric types - Add
Unstable_SlashCommandAdapter,Unstable_SlashCommandItemtypes - Add
ComposerPrimitive.Unstable_TriggerPopoverRootand related primitives - Add
ComposerPrimitive.Unstable_SlashCommandRootand related primitives - Add
unstable_useSlashCommandAdapterhook for building slash command adapters - Refactor
MentionResourceas thin wrapper aroundTriggerPopoverResource - Alias
Unstable_MentionItem/Unstable_MentionAdapterto generic trigger types - Update
react-lexicalKeyboardPluginto use plugin protocol - All existing
Unstable_Mention*APIs remain unchanged
- Introduce
-
Updated dependencies [376bb00]
- assistant-cloud@0.1.25
- @assistant-ui/tap@0.5.7
- @assistant-ui/store@0.2.6
0.1.12
Patch Changes
- 19b1024: fix(core): move initialThreadId/threadId handling from constructor to __internal_load to prevent SSR crash
0.1.11
Patch Changes
- de29641: fix(core): start RemoteThreadList isLoading as true
- a8bf84b: feat(core): expose
getLoadThreadsPromise()onThreadListRuntimepublic API - 5fd5c3d: feat(core): add reactive
threadIdoption touseRemoteThreadListRuntimefor URL-based routing - ec50e8a: fix(core): prevent resolved history tool calls from re-executing
- Updated dependencies [2c5cd97]
- assistant-stream@0.3.10
0.1.10
Patch Changes
-
6554892: feat: add useAssistantContext for dynamic context injection
Register a callback-based context provider that injects computed text into the system prompt at evaluation time, ensuring the prompt always reflects current application state.
-
9103282: fix: resolve biome lint warnings (optional chaining, unused suppressions)
-
876f75d: feat: add interactable state persistence
Add persistence API to interactables with exportState/importState, debounced setPersistenceAdapter, per-id isPending/error tracking, flush() for immediate sync, and auto-flush on component unregister.
-
bdce66f: chore: update dependencies
-
4abb898: refactor: align interactables with codebase conventions
- Rename
useInteractabletouseAssistantInteractable(registration only, returns id) - Add
useInteractableStatehook for reading/writing interactable state - Remove
makeInteractableand related types - Rename
UseInteractableConfigtoAssistantInteractableProps - Extract
buildInteractableModelContextfromInteractablesresource - Add
with-interactablesexample to CLI
- Rename
-
209ae81: chore: remove aui-source export condition from package.json exports
-
af70d7f: feat: add useToolArgsStatus hook for per-prop streaming status
Add a convenience hook that derives per-property streaming completion status from tool call args using structural partial JSON analysis.
-
Updated dependencies [dffb6b4]
-
Updated dependencies [9103282]
-
Updated dependencies [bdce66f]
-
Updated dependencies [209ae81]
-
Updated dependencies [2dd0c9f]
- assistant-stream@0.3.9
- assistant-cloud@0.1.24
- @assistant-ui/store@0.2.6
- @assistant-ui/tap@0.5.6
0.1.9
Patch Changes
-
781f28d: feat: accept all file types and validate against adapter's accept constraint
-
3227e71: feat: add interactables with partial updates, multi-instance, and selection
useInteractable(name, config)hook andmakeInteractablefactory for registering AI-controllable UIInteractables()scope resource with auto-generated update tools and system prompt injection- Partial updates — auto-generated tools use partial schemas so AI only sends changed fields
- Multi-instance support — same name with different IDs get separate
update_{name}_{id}tools - Selection —
setSelected(true)marks an interactable as focused, surfaced as(SELECTED)in system prompt
-
0f55ce8: fix(core): hide phantom empty bubble when user message has no text content
-
83a15f7: feat(core): stream interactable state updates as tool args arrive
-
52403c3: chore: update dependencies
-
ffa3a0f: feat(core): add attachmentAddError composer event
-
Updated dependencies [3227e71]
-
Updated dependencies [52403c3]
- assistant-stream@0.3.8
- assistant-cloud@0.1.23
- @assistant-ui/store@0.2.5
- @assistant-ui/tap@0.5.5
0.1.8
Patch Changes
-
1406aed: fix(core): prevent stale list() response from undoing concurrent delete/archive/unarchive in OptimisticState
-
9480f30: fix(core): stop thread runtime on delete to prevent store crash
-
28a987a: feat: SingleThreadList resource refactor: attachTransformScopes should mutate the scopes instead of cloning it
-
736344c: chore: update dependencies
-
ff3be2a: Add @-mention system with cursor-aware trigger detection, keyboard navigation, search, and Lexical rich editor support
-
70b19f3: feat: add native queue and steer support
- Add
queueadapter toExternalThreadPropsfor runtimes that support message queuing - Add
QueueItemPrimitive.Text,.Steer,.Removeprimitives for rendering queue items - Add
ComposerPrimitive.Queuefor rendering the queue list within the composer - Add
ComposerSendOptionswithsteerflag tocomposer.send() - Add
capabilities.queuetoRuntimeCapabilities ComposerPrimitive.Sendstays enabled during runs when queue is supported- Cmd/Ctrl+Shift+Enter hotkey sends with
steer: true(interrupt current run) - Add
queueItemscope toScopeRegistry - Add
queuefield toComposerStateandqueueItem()method toComposerMethods
- Add
-
Updated dependencies [28a987a]
-
Updated dependencies [736344c]
-
Updated dependencies [c71cb58]
- @assistant-ui/store@0.2.4
- assistant-stream@0.3.7
- @assistant-ui/tap@0.5.4
0.1.7
Patch Changes
- 7ecc497: feat: children API for primitives with part.toolUI, part.dataRendererUI, and MessagePrimitive.Quote
0.1.6
Patch Changes
-
1ed9867: feat: move resumeRun to stable
-
427ffaa: refactor: drop all barrel files
-
349f3c7: chore: update deps
-
02614aa: feat: add multi-agent support
ReadonlyThreadProviderandMessagePartPrimitive.Messagesfor rendering sub-agent messagesassistant-stream: addmessagesfield totool-resultchunks,ToolResponseLike, andToolCallParttypes, enabling sub-agent messages to flow through the streaming protocol
-
6cc4122: refactor: use primitive hooks
-
642bcda: Add
quote.tsxregistry components andinjectQuoteContexthelper -
Updated dependencies [427ffaa]
-
Updated dependencies [349f3c7]
-
Updated dependencies [02614aa]
- assistant-stream@0.3.6
- assistant-cloud@0.1.22
- @assistant-ui/store@0.2.3
- @assistant-ui/tap@0.5.3
0.1.5
Patch Changes
- 990e41d: refactor: code sharing between the multiple platforms
0.1.4
Patch Changes
- f032ea5: fix: restore
typeof processruntime guard in useCloudThreadListAdapter - Updated dependencies [2828b67]
- assistant-stream@0.3.5
0.1.3
Patch Changes
- 5ae74fe: fix: prevent double-submit when ComposerPrimitive.Send child has type="submit"
- 8ed9d6f: Refactor React Native component API: move shared runtime logic (remote thread list, external store, cloud adapters, message converter, tool invocations) into @assistant-ui/core for reuse across React and React Native
- 01bee2b: Remove zod dependency by using assistant-stream's toJSONSchema utility for schema serialization in AssistantFrameProvider
0.1.2
Patch Changes
- 03714af: fix: DataRenderers not in scope
0.1.1
Patch Changes
-
a638f05: refactor(core): depend on @assistant-ui/store, register chat scopes via module augmentation
-
28f39fe: Support custom content types via
data-*prefix in ThreadMessageLike (auto-converted to DataMessagePart), widenBaseAttachment.typeto accept custom strings, makecontentTypeoptional -
36ef3a2: chore: update dependencies
-
6692226: feat: support external source attachments in composer
addAttachment()now accepts either aFileor aCreateAttachmentdescriptor, allowing users to add attachments from external sources (URLs, API data, CMS references) without creating dummyFileobjects or requiring anAttachmentAdapter. -
c31c0fa: Extract shared React code (model-context, client, types, providers, RuntimeAdapter) into
@assistant-ui/core/reactsub-path so both@assistant-ui/reactand@assistant-ui/react-nativere-export from one source. -
fc98475: feat(core): move
@assistant-ui/tapto peerDependencies to fix npm deduplication -
374f83a: fix(core): stabilize object references in ExternalStoreThreadRuntimeCore to prevent infinite re-render loop
-
1672be8: feat: bindExternalStoreMessage
-
14769af: refactor: move RuntimeAdapter base logic to @assistant-ui/core; re-export missing core APIs from distribution packages
-
Updated dependencies [36ef3a2]
-
Updated dependencies [fc98475]
-
Updated dependencies [a638f05]
- assistant-stream@0.3.4
- @assistant-ui/store@0.2.1
- @assistant-ui/tap@0.5.1
0.1.0
Minor Changes
- 60bbe53: feat(core): ready for release
Patch Changes
-
546c053: feat(core): extract subscribable, utils, and model-context; add public/internal API split
-
a7039e3: feat(core): extract remote-thread-list and assistant-transport utilities to @assistant-ui/core
-
16c10fd: feat(core): extract runtime and adapters to @assistant-ui/core
-
40a67b6: feat(core): add message, attachment, and utility type definitions
-
b181803: feat(core): introduce @assistant-ui/core package
Extract framework-agnostic core from @assistant-ui/react. Replace React ComponentType references with framework-agnostic types and decouple AssistantToolProps/AssistantInstructionsConfig from React hook files.
-
4d7f712: feat(core): move runtime-to-client bridge to core/store for framework reuse
-
ecc29ec: feat(core): move scope types and client implementations to @assistant-ui/core/store
-
6e97999: feat(core): move store tap infrastructure to @assistant-ui/core/store
-
Updated dependencies [b65428e]
-
Updated dependencies [b65428e]
-
Updated dependencies [b65428e]
-
Updated dependencies [6bd6419]
-
Updated dependencies [b65428e]
-
Updated dependencies [61b54e9]
-
Updated dependencies [b65428e]
-
Updated dependencies [93910bd]
-
Updated dependencies [b65428e]
- @assistant-ui/tap@0.5.0
- assistant-stream@0.3.3