Download Latest Version plugins-v0.11.1 source code.zip (154.4 MB) Google Add to Preferred Sources
Home / v0.11.0
Name Modified Size InfoDownloads / Week
Parent folder
README.md 2026-08-05 77.2 kB
v0.11.0 source code.tar.gz 2026-08-05 147.2 MB
v0.11.0 source code.zip 2026-08-05 154.3 MB
Totals: 3 Items   301.7 MB 1

Core/SDK 0.11.0 (2026-08-05)

Minor Changes

  • Replace Surface.isAvailable with Surface.useIsAvailable, a hook returning a stable, memoized function. Surfaces and graph extensions with an invalid (non-camelCase) local id are now dropped with a warning instead of throwing and crashing plugin activation. (2048cb3)

  • Surface.create accepts an optional props mapper, so a container can be registered directly instead of being wrapped in an adapter that unpacks the surface's data envelope:

ts Surface.create({ id: 'defaultPluginSettings', filter: AppSurface.settings(AppSurface.Article), component: DefaultSettings, props: ({ data: { subject } }) => ({ subject }), });

The mapper's input type derives from the same filter that defines the surface's data shape, so the unpacking is type-checked rather than restated by hand, and is exported as Surface.ComponentProps for components that consume the whole envelope. component accepts any ComponentType, so a container re-exported through a lazy() barrel needs no cast. Additive: definitions without props receive the full surface props exactly as before. (ed992c2)

  • Plumb ephemeral trace events through the swarm (DX-1125).

Adds tag-based broadcast pub/sub over the existing swarm messaging layer (spec 1): a message may carry tags instead of a single recipient, and a subscriber registers a tag set and receives any broadcast whose tags intersect (logical OR). New wire fields (signal.Message.tags, signal.SubscribeMessagesRequest, messenger.Message.tags, SwarmRequest.SUBSCRIBE/subscribe_tags) and a dedicated onBroadcast channel keep broadcasts off the point-to-point path.

On top of that (spec 2), remote runtimes broadcast their ephemeral trace messages so clients can watch live progress: Trace.messageToTags/Filter/matchesFilter/encodeTraceMessage, a SwarmTraceSink producer, Process.Monitor.subscribeToTraceMessages(filter), a RemoteTraceMonitor swarm source merged into the aggregate monitor, and a plugin-client consumer that projects remote status.update events into the progress registry. (08a3eea)

  • Drive connector-auth ("Connect X") toolbar actions from a ConnectorAuthAnnotation schema annotation, resolved by a single app-graph extension in plugin-connector — replacing the per-plugin connectorAuthExtension helper (removed). Owning plugins inline their own sync/generate toolbar actions. Adds actionGroups to GraphBuilder.createExtension/createTypeExtension and a primary menu-action variant. (68e61ca)

  • Graph actions can now declare disposition as an array and a presentation chrome override per surface, letting one action multi-target the object toolbar and nav-tree context menu with appropriate chrome in each. Mailbox and calendar "Sync" now surface from a single graph action instead of a duplicated toolbar button. (1a989ed)

  • Redesign Composer URLs as pair chains (/w/<workspace>/<key>/<id>/…) resolved by the graph builder via per-extension url: { key, kind, path } declarations (replacing the NavigationPathResolver capability), and collapse the deck's layout modes into a single mode: presentation derives from plank count (fullbleed / tiling / sliding) and fullscreen is transient. Navigation is now gesture-based (no navigationDefault setting): nav-tree plain click navigates solo (shift adds a plank), and in-plank/card navigation follows the deck — adding beside the origin when sliding and replacing when solo. LayoutOperation.Open's disposition values are solo | add | auto. Breaking: LayoutOperation.SetLayoutMode is removed, ?plank= URLs are replaced by the pair-chain grammar, AppCapabilities.NavigationTargetResolver now declares its real requirement (Effect<NavigationTarget[], never, Database.Service>) so implementations no longer need a cast, and the unused companionFrameSizing field is dropped from the deck's persisted state (stripped by the existing migration). (5585ec8)

  • Add stable data-testids across the inbox and connector UI (mailbox sync/reply/message actions, message and conversation tiles, connect dropdown) and an optional testId param on AppNode.makeToolbarActionGroup / react-ui-menu's menu builder, enabling reliable browser-e2e targeting. (30ae5eb)

  • Replace CommentConfig.getAnchorLabel with a typename-keyed AppCapabilities.AnchorResolver capability; the assistant companion chat now includes the markdown editor's current selection as request context. Fix view-state persistence so a written value (e.g. a text selection) survives without a live subscriber instead of being garbage-collected back to its default. (9f7d5ad)

  • Move the WithProperties test helper from @dxos/plugin-markdown/testing to a new @dxos/app-toolkit/testing subpath export. (499dde4)

  • Add an optional attach flag to the database.objectCreate operation that files the created object in the space root collection (visible in the navigation tree). CLI: dx profile create templates now enable edge features (fixes device invitations hanging at "Connecting…" for CLI-created profiles), and dx halo share prints the joinable URL. (bda1a02)

  • Project model unification, phase 1 (breaking, no data migration — nothing deployed). Two forms of work: markdown checklists (Outline) are the cheap, fluid form; ECHO Task objects in a TaskSet are the durable, assignable form; promotion links the two. ExternalProject becomes TaskSet (org.dxos.type.taskSet@0.2.0); containment is the ECHO parent edge (TaskSet → Task → sub-Task), replacing the Task.project ref. Task 0.2.0 renames assigned: Ref<Person> to assignee: Actor (human by Person ref/email/name, agent by DID) and adds failed/cancelled statuses. Outline moves into @dxos/types (0.2.0) with checklist markdown helpers and the task-promotion helpers. Project 0.3.0 adds goals, outline, and taskSet. The Plan type is REMOVED: a conversation's working set is its outline (Chat.outline; project chats write the project's outline) plus promoted Tasks; the planning skill edits checklist markdown, and delegation promotes to a durable agent-assigned Task the supervisor reconciles over. (37c17cc)

  • Stop exporting TestStream from the package's main entry. The helper extends node:stream's Duplex, and re-exporting it from the browser-reachable barrel leaked node:stream into every browser bundle — with source-first dev resolution (vite + rolldown build system) this threw Module "node:stream" has been externalized for browser compatibility at module scope on dev-server boot, hanging the app on the loading screen.

Breaking: import TestStream from @dxos/async/testing (new Node-only subpath) instead of @dxos/async. (aea1e6e)

  • Remove the legacy SharedWorker client-services path. The @dxos/client/worker and @dxos/react-client/worker subpath exports, the createWorker client option, and ServicesMode.SHARED_WORKER support are gone; use the dedicated-worker mode (createDedicatedWorker) instead. The SHARED_WORKER proto enum values are retained but deprecated for wire compatibility. (856c4f0)

  • Remove the legacy protobuf byte-transport client providers fromSocket (websocket) and fromAgent (unix socket), along with AgentClientServiceProvider, FromAgentOptions, and getUnixSocket. createClientServices no longer supports a runtime.client.remote_source endpoint — it now throws, since the remaining deployment modes (HOST, DEDICATED_WORKER) and the shell↔app transport run over effect-rpc. This also removes clientServiceBundle from @dxos/client-protocol, which had no remaining consumers; the effect-rpc rpc surface and the Promise/Stream services surface are unchanged. A remote_source transport can be reintroduced over the effect-rpc RpcPort protocol if needed. (f15c632)

  • Remove the deprecated descriptors member from ClientServicesProvider (and the corresponding ServiceRegistry descriptor slot). The protobuf service descriptors it exposed had no consumers; the effect-rpc surface (rpc) and the Promise/Stream services surface are unaffected. clientServiceBundle remains for the legacy byte-transport bridges that still use it. (6df314a)

  • Delete the redundant dxos.iframe.WorkerService protobuf service (and its StartRequest message) now that the tab→worker control channel is defined and served via effect-rpc (WorkerService in @dxos/protocols/rpc, over the app MessagePort). Also removes the now-unused iframeServiceBundle and workerServiceBundle exports from @dxos/client-protocol (they had no consumers). The dxos.mesh.bridge.BridgeService and dxos.iframe.AppService/ShellService protobuf definitions are retained — they are still used by the WebRTC transport bridge and the shell↔app iframe transport respectively. (962c8cd)

  • Add a direct trigger kind that is invoked on demand rather than scheduled by the dispatcher, along with its spec/event constructors and an isManuallyInvokable helper. (a19443b)

  • Mailbox sync progress can now be cancelled from the sync meter: for an edge-executed sync trigger the cancel control stops the current run and its continuation chain, while the trigger's schedule stays enabled and re-syncs on its next tick. @dxos/compute now exports the Cancellation service the runtimes provide (Cancellation.Service) and operations observe (Cancellation.signal).

Breaking:

  • @dxos/app-toolkit: ProgressTraceSinkOptions.terminateProcess is renamed to cancelProcess and takes a CancelTarget (pid, space, runtime, trigger) instead of a pid, so a cancel can be routed to the runtime that owns the run.
  • @dxos/compute-runtime: SwarmRemoteTraceMonitorOptions.subscribe yields SwarmTraceBroadcast ({ payload, tags }) instead of a bare payload — the envelope tags carry the ref-typed trace meta dropped by the wire codec. (5e7839e)

  • McpToolAnnotation opts an operation into MCP projection: a name, model-facing description, safety class (read/write/destructive), and aspect, applied at the definition site with Operation.mcpTool({ … }) and read back with Operation.getMcpTool. The annotation rides through Operation.serialize into the persisted record, so a remote projector (edge mcp-space-service) discovers tools from the operation registry instead of a hand-maintained table. Projected operations must be remotely invocable — refs in, JSON snapshots out, serializable schemas, worker-safe handlers. (6067460)

  • Add Project (@dxos/compute), the successor to Topic, holding owned instructions, routine references, and an artifacts collection; the Routine schema moves into @dxos/compute alongside it. Instructions gains a structured commands field, surfaced as sentinel-command autocomplete in the assistant chat prompt. The existing @dxos/types GH/Linear-style Project (name, description, image) is renamed to ExternalProject to free the typename for the new concept. dx-input now owns its full input chrome (padding, focus shift, a single-band ring/border treatment) so markdown-backed fields match plain inputs. (f7d7735)

  • Subscription triggers now report a real mutation type on SubscriptionEvent.type'created' | 'updated' | 'deleted' (previously the placeholder 'unknown'; the field is now a narrowed literal). Subscription semantics (create/update/delete) apply uniformly to both the space database and feed items — build a feed-scoped subscription with Trigger.specSubscription(Query.select(...).from(Scope.feed(...))). Change detection is content-signature based (feed-backed objects are unversioned), and deletes are detected uniformly via queryable tombstones (deleted: 'include' + Obj.isDeleted) for both sources — a feed removal now leaves a body-preserving tombstone in the index. (7b270f2)

  • Collapse @dxos/functions and @dxos/functions-runtime into @dxos/compute-runtime (local runtime + Remote* interface tags) and a new private @dxos/edge-compute (EDGE deploy/scripts + Edge* implementations). Assistant-coupled agent runtime and test helpers move to a new private @dxos/agent-runtime (avoiding a compute-runtimeassistant build cycle).

@dxos/compute-runtime now exports the former functions SDK/services/protocol/triggers/executor plus new namespace modules: RemoteOperationInvoker, RemoteProcessManager, RemoteTriggerManager (interface tags with layerNoop), and the aggregate ProcessMonitor.layer / TriggerMonitor.layer that merge local and remote views. FunctionInvocationService now routes through RemoteOperationInvoker (superseding RemoteFunctionExecutionService). Breaking: ProcessManager.layer no longer provides Process.ProcessMonitorService — provide ProcessMonitor.layer (plus a RemoteProcessManager layer) instead; imports of @dxos/functions / @dxos/functions-runtime move to @dxos/compute-runtime, @dxos/edge-compute, or @dxos/agent-runtime. (1a9bca1)

  • Remove the deprecated local/remote function-execution machinery: FunctionInvocationService, LocalFunctionExecutionService, FunctionImplementationResolver, ServiceContainer, and FunctionExecutor. Operation invocation now runs exclusively through Operation.Service (ProcessOperationInvoker); select edge dispatch per invocation with { on: 'edge' }, keyed by the operation's deployedId. (bf013a1)

  • Fix running a routine manually. The runnable's input now comes from the routine's first trigger, so a sync routine's binding reaches the operation instead of throwing, and a routine whose trigger is remote force-runs on the edge dispatcher rather than silently running on the client. Also export createInvocationPayload for building a trigger's invocation payload. (bf055c8)

  • Default edge replication to the Subduction sedimentree transport: the built-in client config now enables edgeFeatures.subductionReplicator instead of edgeFeatures.echoReplicator. Set subductionReplicator: false (and echoReplicator: true) to restore the previous Automerge edge replicator. (41141d8)

  • Agents become identity/presets (breaking, no data migration — 0.1.0 agents must be recreated): Agent 0.2.0 keeps only name, DID, enabled, and a typed Instructions ref; a chat and the agent it runs as are linked by the CompanionTo relation (resolved with AgentChat.loadAgent / AgentChat.loadChat), neither type referencing the other by field; durable artifacts belong to a Project collection; subscriptions and cron schedules compile to Routines whose relay qualifies events with a cheap model and forwards them onto the durable agent session. (f9ba47a)

  • Add an order option to Aggregate.items({ limit, order }): an explicit, per-group member ordering independent of any orderBy elsewhere in the query. Previously a preceding orderBy did double duty — establishing group order and silently determining which members (and in what order) landed in a following Aggregate.items({ limit }) — so moving that orderBy relative to aggregate could silently change which items appeared. The mailbox list now uses order to keep each thread's preview newest-first, independent of the query's own group ordering. (4e64123)

  • Ambient (Google-Docs-style) document review. The default document view now overlays every author's suggestions plus comments on main, with a per-user Editing/Viewing mode governed by a product-level ReviewRenderPolicy; the explicit branch switcher / diff selector remains as the advanced path. Also fixes a crash when adding a comment while viewing a branch (comment anchors now resolve against the editor-bound document) and prohibits inline comments on suggestion branches. @dxos/ui-editor gains suggestionsOverlay and a readonly option on comments(). (c035062)

  • Chats carry a typed instructions ref rendered into the system prompt at request time (replacing typename-based inlining of bound Instructions objects, which now bind as ordinary context objects), and the new Project skill lets the assistant file created objects into a project's artifacts collection and list them. (b5ecf54)

  • Make the published @dxos/cli runnable, and keep React out of node and bun builds.

@dxos/cli@0.10.0 could not execute at all once installed from npm. Nothing marked external in the compiled binary can resolve at runtime (Bun's embedded filesystem has no node_modules), so the externals are gone and esbuild-wasm's WASM is inlined; the @dxos/node-std shims resolve to node builtins, since Bun miscompiles export * from 'node:<mod>'; @automerge/automerge-subduction uses its self-contained web entry rather than the node one that reads a sibling file; the platform binary keeps its executable bit through publishing; and the pinned bun no longer leaks --smol into process.argv. Persistent SQLite on bun also now creates its parent directory, which any dx command needed on a machine with a stored profile but no data root.

The binary also contained React, react-dom and the whole react-ui graph. Capability.lazy, OperationHandlerSet.lazy and React.lazy defer evaluation but not bundling, so plugin barrels that merely listed a React surface pulled it into every non-browser consumer: the plugins with a node variant now have node-conditioned #capabilities, and plugin-sheet a node-conditioned #operations. Headless code no longer reaches for React packages — @effect-atom/atom instead of @effect-atom/atom-react wherever only Atom/Registry/Result are used, and @dxos/client/* instead of @dxos/react-client/*. @dxos/ui-editor/headless is a new UI-free entrypoint for the editor helpers operation handlers need.

Breaking:

  • formatForDisplay and formatForEditing move from @dxos/react-ui-form to @dxos/schema.
  • renderByline and BylineIdentity move from @dxos/react-ui-transcription to @dxos/plugin-transcription.
  • The icon list moves from @dxos/react-ui-pickers/icons to @dxos/ui-types, and that subpath is removed; hues moves from @dxos/ui-theme to @dxos/ui-types beside ChromaticPalette.
  • @dxos/plugin-graph no longer exports its React hooks from the package root — import them from @dxos/plugin-graph/hooks.
  • @dxos/plugin-deck and @dxos/plugin-navtree are browser-only: #plugin no longer resolves a node or workerd condition. (3f6ac61)

  • The dx binary no longer depends on the machine that built it: @dxos/kv-store's createLevel moves to @dxos/kv-store/level so importing the package for its types no longer binds LevelDB's native addon, and Automerge's WASM is inlined rather than read from disk. LevelDB, SublevelDB and BatchLevel are unchanged on the main entry. Each @dxos/cli-<platform>-<arch> package also exposes dx directly, so one platform can be installed without pulling the rest. (091ebe4)

  • Add ECHO-core per-object time travel and subtree branching: setTimeTravel/clearTimeTravel pin a live object to a historical version (writes throw, latestOnly subscribers stay live), createBranch/switchBranch/mergeBranch/deleteBranch fork an object subtree into writable CRDT branches with shared history and true merge-back, and db.branch() returns caller-owned writable per-surface branch bindings. (46ec569)

  • New Lens namespace: an object lens that views one live ECHO object through a second declared type. Sibling of the existing Panproto wire lens, which crosses the serialization boundary to a foreign record — an object lens never creates a second object, so reads project the base object and writes invert onto it.

A lens binds two written-out types (Lens.make(id, Source, Target, mapping)), so the target's TypeScript type is the view's type and an interface written once against the target works for every source that maps to it. A lensed object reports the target's typename, so surfaces and forms already written for that type resolve unchanged, while Obj.getURI still resolves to the underlying object.

The mapping is partial. A target property with a same-named, type-compatible source property maps itself; one with no counterpart stores itself in the object's annotation dictionary; a name match whose types are incompatible is reported by Lens.coverage as suspicious rather than auto-mapped or auto-overlaid, since either would record the same fact twice and let the copies drift. Lens.coded covers transforms a per-property mapping cannot express, such as parsing.

Lens.of returns a live handle the ordinary Obj.* API accepts, including Obj.update, which batches every assignment in its callback into a single change touching only the properties actually assigned — so two peers editing one object through different lenses merge instead of clobbering each other. Lens.checkLaws verifies the GetPut round trip, Lens.register preserves its argument's precise type, and a declarative mapping can be persisted as an ordinary ECHO object (Lens.Object) referencing its value conversions by registered codec name.

useLens ships on the new @dxos/echo-panproto/react entrypoint, mirroring @dxos/echo-react's useObject tuple and overload shape. It sits on its own subpath so the package's main entry stays React-free for worker contexts. A lens holds no state: the hook subscribes to the base object for the render schedule and projects on every render, so replicated changes, overlay writes, and character-level text edits all reproject.

The wire lens schema moved from src/lens.ts to src/wire-lens.ts, internal to the package; the Panproto export surface is unchanged. (f8637f1)

  • Add soft-fork support to feeds: Feed.append(feed, items, { parent }) continues a feed from an earlier item, and Feed.history(items) resolves the live branch at read time. Feeds that set no parent are unaffected. (af5fbf4)

  • Resolve a replicated document's containing space from local collection membership in the share policy, so a document whose handle is evicted or still loading is no longer falsely reported as belonging to no space, removing the false share-policy denials and the replication stalls they caused on both the edge/subduction and mesh replication paths.

Additionally, the subduction WASM console log level is set to error once the repo is constructed. Subduction syncs every document with every connected peer, so with multiple spaces each space-scoped edge peer is asked for every foreign document and correctly denied — and subduction_core logged each denial as a not authorized to access sedimentree warning, flooding the console (dispatch-scoping gap tracked as DX-1121). Set localStorage.debug to a value matching subduction (or set globalThis.__SUBDUCTION_DEBUG) to restore verbose WASM logging when debugging.

Breaking: createIdFromSpaceKey is no longer re-exported from @dxos/echo-host; import it from @dxos/echo-protocol instead. (ae18615)

  • Move the space protocol, control/feed pipeline, and metadata store out of @dxos/echo-host into @dxos/client-services. @dxos/echo-host now exposes only EchoHost and its Automerge/database implementation. Consumers of SpaceManager, SpaceProtocol, Space, AuthProvider/AuthVerifier, Pipeline, MetadataStore, SqliteMetadataStore, createMappedFeedWriter, and valueEncoding must now import them from @dxos/client-services (test helpers from @dxos/client-services/testing). (14983db)

  • New package @dxos/echo-panproto: declarative, JSON-serializable lenses (Panproto.Lens) between ECHO objects and foreign wire records, executed by a runner (Panproto.encode/decode) rather than expressed as closures.

Annotation-driven publishing of ECHO objects to the AT Protocol. @dxos/schema gains AtprotoRecordAnnotation (type-level: target collection, record-key strategy, and a declarative serializable lens) and AtprotoVisibilityAnnotation (field-level, private by default — a field is published only when explicitly marked), so a generic companion can discover and publish any annotated type without knowing the type itself.

MasterDetail moves from plugin-routine into @dxos/react-ui-list as a reusable primitive: a selectable master list above a detail slot, nestable by placing another MasterDetail in detail. Per-row overflow menus are driven by useMenuBuilder from @dxos/react-ui-menu.

ComboboxField now shows the selected option's label rather than the stored value, which is often an opaque id the user never chose to see. (9da013f)

  • One identity rule per type, shared by the extractor's create-vs-merge decision and by a new duplicate scan, plus a Duplicates tab on the database type article for reviewing and merging what has already accumulated.

Contact extraction is now an allow-list: a sender earns a Person only when we sent or replied to it, or its domain matches a known Organization, and never when the address or message is automated. Mail sync and Google Contacts sync resolve against one index per space rather than a snapshot each, so concurrent syncs no longer both create the same person. (0a4bbde)

  • Gmail and JMAP sync are now always bidirectional and durably resumable: the sync cursor tracks a max/min watermark pair (replacing value), each run syncs new mail forward and continues backfilling backward in the same pass, and a per-run message cap requests a durable re-run via Operation.runAgain() instead of looping in-process. The sync operations now take only the binding — the direction/after/before inputs are removed. Breaking: the Cursor schema field value becomes the max/min pair, Cursor.resolveWindow is replaced by Cursor.resolveHorizon/Cursor.resolveWindows, Cursor.dedupStage drops its direction option, and Cursor.advance/Cursor.parseKey/Cursor.formatKey operate on max instead of value. (48d168e)

  • Mail sync is now incremental and provider system state maps onto shared canonical tags.

Incremental delta-resume: the sync cursor carries an opaque provider delta token (Gmail historyId, JMAP Email/get state). After the initial window backfill, each run fetches only the delta since the token (Gmail history.list — paginated so multi-page deltas are not dropped; JMAP Email/changes), applying additions plus label/flag reconciliation to already-committed feed messages via objectless commit units. A stale token falls back to the window scan and recaptures; the token advances only after the run's merged stream fully drains, so a crash re-fetches the delta idempotently.

Unified system tags: Gmail system labels, JMAP mailbox roles, and the JMAP $flagged keyword now resolve to a shared, provider-agnostic tag registry (org.dxos.tag: starred / inbox / important / sent / and the Gmail categories) instead of provider-scoped tags — so a Gmail star, a JMAP flag, and a locally-toggled star are the same tag. Read-state, drafts, trash, spam, and archive are intentionally not tagged (archive is derived as "not in inbox"). The starred tag's foreign key moves from org.dxos.org to org.dxos.tag; existing locally-starred items under the old key are not migrated. (2543b63)

  • Add an in-app log viewer as a composite Logger component (@dxos/react-ui-debug, replacing LogPanel) with per-file log-level control and a text-match buffer filter, backed by a new dev-mode logFileRegistry in @dxos/log that records every log file at module load via the @dxos/vite-plugin-log transform. (f6a01e3)

  • Unify the signaling sendMessage/sendBroadcast methods and encapsulate message-subscription routing.

Breaking:

  • SignalMethods.sendMessage(ctx, message) now handles both point-to-point and swarm-broadcast (DX-1125) delivery. A message carries exactly one of recipient (point-to-point) or tags (broadcast, targeting the swarm in author.swarmKey); Message.recipient is now optional. The separate sendBroadcast method is removed.
  • subscribeMessages({ peer, tags?, onMessage }) now takes the delivery callback, encapsulates routing (point-to-point by recipient, broadcasts by tag intersection), and returns an unsubscribe callback that owns the subscription lifecycle. The standalone unsubscribeMessages method and the onMessage/onBroadcast events are removed.
  • The @dxos/signal package (the KUBE signal-server test harness) has been removed; tests now use MemorySignalManager.
  • The KUBE signaling client is removed: WebsocketSignalManager, SignalClient, SignalRPCClient, SignalLocalState, and the SignalClientMethods interface no longer exist. Edge signaling (EdgeSignalManager) is the only real transport; the non-edge fallback in the services host / worker runtime / local client services is now MemorySignalManager (isolated, no cross-process signaling). (b3a3fcf)

  • Google OAuth access tokens are no longer replicated through ECHO. EDGE stores the granted token and returns a MANAGED_ACCESS_TOKEN placeholder in its place, which Credential.CredentialsService resolves transparently — consumers no longer see whether a credential came from the space or from EDGE. CredentialQuery gains accessTokenId so a specific AccessToken can be looked up rather than any credential for a service, which also fixes a by-service lookup that picked arbitrarily among a space's several connections to the same provider. OnTokenCreated and TestConnection now take Credential.CredentialsService in their requirement channel rather than reading accessToken.token. Existing connections keep working until their token expires; re-authenticating migrates them. (c727a43)

  • Inbox draft composer rebuilt as a compose-style form, plus the shared UI it needs. @dxos/react-ui Input.TextInput gains MUI-style start/end adornments rendered inside the input container; @dxos/ui-theme adds a shared .dx-input box treatment (surface + hairline border + focus-within shift) now used by Input, MarkdownField, RefEditor, and the inbox editor. @dxos/react-ui-form RefEditor email mode renders committed mailboxes as atomic tag widgets (trailing delete affordance, no @ marker) — a raw address stays plain text until committed with comma/Space/Enter, typing before a tag starts a fresh token, and the single line is centered so text and tags align. @dxos/ui-editor's defaultThemeSlots is now fullWidth (no longer forces h-full). @dxos/plugin-inbox EditMessage gains To/Cc/Bcc recipient pickers with Person autocomplete, arrow-key field navigation, and a layout fix so Send no longer overlaps the editor. (d958118)

  • Rework the light-mode surface ladder and control states.

Surface levels, separators, wells, scrollbar thumbs and rail tones are now derived from the enclosing --surface-bg and attenuated for light mode through a single --dx-attenuate-* table, replacing several fixed neutrals that had drifted from the ladder. Filled controls derive their hover from their own fill (--color-input-bg-hover) rather than from the host surface, so hovering a default button no longer lightens it into the selected tone. Panel.Toolbar owns the toolbar bar treatment, so a nested Toolbar.Root matches content width without floating. Cards now carry their padding unconditionally. (e65432c)

  • Rename Message.Content to Message.Body and add a new optional Message.Content wrapper that carries the message's default padding. Card.Root accepts a gutter prop so a card whose body is a form insets its fields like a standalone form. (51aaffe)

  • Add a Slider primitive built on the Radix slider (Slider.Root/Track/Range/Thumb composed behind a single themed component), supporting one or more thumbs, horizontal and vertical orientation, and a disabled state. react-ui-form's Form.Row gains an additive labelEnd slot that renders trailing content at the end of the label row, so a field can show a live value beside its label without nesting it inside Input.Label (which would change the input's accessible name). (848ba1b)

  • Runtime icon resolver: ThemeProvider mounts a shared IconRegistry that ingests the static /icons.svg sprite into an in-DOM defs container and resolves missing icons on demand from a per-icon-set route (Phosphor at /phosphor/{weight}/{name}.svg by default, configurable via IconSource), so icons referenced only by runtime-loaded plugins render without being present in the build-time sprite. useIconHref now returns a same-document #name href (or undefined while unresolved), and <dx-icon> consumes the same registry via a globalThis.__dxIconRegistry bridge. Breaking: the unused noCache prop is removed from ThemeProvider, withTheme, and <dx-icon> — cross-document sprite URLs are no longer built, so there is nothing to cache-bust. (55bb048)

  • Add Html, a sandboxed renderer for untrusted HTML: sanitized content in a Shadow DOM host, so the document's CSS cannot reach the app while it still flows in the app layout, with remote images blocked by default. Content-specific behaviour is supplied as an HtmlDialect — a plain value carrying CSS, transforms and a src resolver — rather than baked into the component; emailDialect() is the first of these. plugin-inbox's HtmlViewer is replaced by that pair, moving cid: attachment resolution into the plugin (useCidResolver) so the shared UI package no longer depends on ECHO.

Email bodies now honour the sender's color-scheme declaration, read from the raw markup before sanitization strips it: a body declaring light is left as authored on a light sheet in dark mode, and anything undeclared is recolored to the app theme regardless of layout (the previous table-layout exemption preserved too little to justify leaving marketing mail glaring white in dark mode). (ba7aabf)

  • Add a Minimap component (@dxos/react-ui-components): a vertical rail of ticks representing anchor markers in a scrollable document, with a wave hover animation, per-marker popover, and brighter ticks for the currently-visible range.

MarkdownStreamController gains scrollTo, getVisibleRange, and onVisibleRangeChange. In plugin-assistant the chat thread now renders a Chat.Minimap rail (one tick per prompt turn, scrolls to the turn on click), and prompt prev/next navigation steps through the prompt range table rather than the xml-tag widget bookmarks. (801b77f)

  • The editor's object picker is now a combobox: the query is typed into a search input in the popover instead of into the document, opted into per trigger via searchTriggers. In markdown, the picker sorts objects by name and leads with a generic "Add object" that opens the create-object dialog and inserts a link to whatever it creates. Links to internal objects no longer show a raw-URI hover tooltip. (2e10525)

  • Masonry no longer flashes a bunched, overlapping stack on the initial render of a large set: unmeasured tiles now use an estimated height so the first layout is already spaced into columns, and the grid stays hidden until the layout settles before fading in (respecting prefers-reduced-motion). Reflow animation is limited to small add/remove edits — the initial render, bulk data swaps, and resizes snap instead of animating — and a new animate prop on Masonry.Root disables animation entirely. (9ded6b9)

  • Clean up inbox operations: remove unused DeleteEmail, DeleteEvent, SyncDraftEvents, SyncContacts operations and the dead tool-ids.ts file. Deprecate ExtractContact and ExtractMailbox. Add a defensive double-click guard to toolbar action buttons — they now disable while the handler is in-flight. (bb63d91)

  • Full-text search across a space in the search plugin — ranked, highlighted results backed by the ECHO FTS index, plus a new SearchResultList. The mailbox filter now searches messages by subject, sender/recipients, and plain/markdown body (never raw HTML) and shows a best-match highlighted snippet; the query is debounced to avoid re-rendering the list on each keystroke. Shared match/snippet utilities (computeMatchSpans, buildSnippet, Highlighted) moved to @dxos/react-ui-search. (e510f3b)

  • Rename Tabs.TabTabs.Button and Tabs.IconTabTabs.IconButton. Both now honor a caller-supplied variant and skip label-alignment classes when iconOnly. (105dac4)

  • Promote Topic to a first-class domain type. Topic moves from @dxos/pipeline-email to @dxos/types as a Project-style class (inline title/label/icon annotations + make factory), keeping a shared Topic.Props struct and its org.dxos.type.topic DXN. The Topic detail view (TopicArticle) moves to @dxos/plugin-brain and renders via a regular object/article surface.

Breaking: Topic / TopicProps are no longer exported from @dxos/pipeline-email — import from @dxos/types and use the namespace form (Topic.Topic, Topic.Props). No compatibility re-export is left behind. (f0ec728)

  • Introduce @dxos/link, a low-level infrastructure package holding a unified Cursor ECHO type (org.dxos.type.cursor 0.2.0), the relocated AccessToken type, and the durable-progress sync machinery. Cursor replaces @dxos/plugin-connector's SyncBinding relation with a flat object whose discriminated spec covers both external-source sync (Gmail, Trello, GitHub, Linear, Slack, Discord, Bluesky) and internal feed-to-feed processing (e.g. mailbox fact extraction), so progress now persists across reloads for both. Connection/Connector stay in @dxos/plugin-connector and correlate to a Cursor via their shared AccessToken rather than a direct relation. This is a breaking change: existing SyncBinding relations and Cursor 0.1.0 objects are not migrated and are abandoned on upgrade — external syncs re-bind and feed-to-feed analysis restarts from the beginning. (a49131a)

  • Render editor comment highlights as a selection-style layer that fills wrapped lines to the edge (straight left/right edges, rounded only when single-line, 1px padding) and colours the comment text. comments() now folds in external synchronisation via subscribe/getComments options (replacing createExternalCommentSync) and requires an id; linkTooltip now takes an options bag ({ render }). (a31ef40)

  • Highlight fenced mermaid code blocks in the markdown editor, and add createMermaidExtensions for documents that are entirely mermaid. (6e4ac74)

  • Convert outline items into Task objects: a "Convert to task" action replaces the item with a link to a new Task parented to a project created lazily on first use, and the link navigates to the task in place. Adds the getItemText, replaceItemWithLink, and syncLinkLabels editor commands. Fixes the outliner content column not being centered, which pushed the drag grip outside the document and the line menu inside it. (59a65a8)

  • Suggesting mode (Google-Docs-style authoring). In the ambient review view, switching to Suggesting binds the editor to the current user's own suggestion branch: their typing accrues there and renders as character-level tracked changes over main (trackChanges), while other authors' suggestions overlay against main via suggestions({ base }) + rebaseHunks (so a foreign author no longer strikes your own new text). Accept/reject controls moved into a non-clipped hover popover. @dxos/ui-editor gains trackChanges, rebaseHunks, computeCharHunks, and a base option on suggestions(). (77fff35)

  • Fold the review "Suggesting" mode into the editor view-mode dropdown. addViewMode now accepts an optional ViewModeItem[] (default the three built-in modes), threaded through EditorToolbarFeatureFlags.viewModes; plugin-markdown establishes a ViewModeExtension capability that plugin-comments implements to contribute the "Suggesting" entry, and the separate toolbar branch-selector / review-mode dropdowns are removed (the History companion covers branch switching). Single-select dropdowns now render a check on the current value (with radio semantics). Also: an author-coloured change-bar gutter on lines containing suggestions, a fix for comments flashing out of the companion on submit, and a suggestion-overlay perf improvement (compute the base/document character diff once across all authors). (6e624bd)

  • Split the blocks editor extension into blockOutline (the below-text border boxes — usable on its own), blockSelection (whole-block selection state, highlight, and clipboard), and blockDrag (the gutter grip that drives selection and drag-to-reorder). blocks() composes all three; blockOutline stands alone, while blockSelection and blockDrag are a pair (the grip lives in blockDrag). The drag core (createBlockDrag) and selection core (createBlockSelection) are generalized over a document-agnostic BlockOps contract, shared by markdown blocks and the outliner.

Add document-agnostic whole-block selection: the gutter shows a grip on the caret's block and each selected block; clicking a grip selects the block (shift-click toggles it in a multi-selection). Dragging a grip reorders the block, or the whole selection when it is part of it, and Cut/Copy/Paste operate on the selected blocks. Wire the same selection, drag, and clipboard into the outliner (outlinerDnd).

The drag experience lifts the source block(s) out of the document (collapsing them and their trailing blank line), opens a block-sized placeholder at the drop slot, centers each grip on its line's first row, and matches the floating preview's wrapping to the source. Drags abort on a concurrent edit and start on the primary button only. (392c700)

  • Export design tokens as @dxos/ui-theme/tokens.css, so stylesheets compiled outside this repo — Composer plugins loaded from the registry — can generate token-backed utilities themselves rather than relying on whichever ones the host happens to bundle. (c58ebb7)

  • Add @dxos/versioning (checkpoints, draft branches, and 3-way merge for automerge-backed ECHO objects) and document revisions and branches in Markdown: named checkpoints with read-only time travel and restore, draft branches (separate Text objects anchored to a parent revision) with 3-way merge-back, a History companion panel, a Versions section in object properties, an editor banner with a branch switcher, agent operations (create-checkpoint, create-branch, merge-branch, get-history), and a diffView setting selecting inline, side-by-side, or gutter diff rendering. (dd190a0)

  • Worker connections accept an onPersistentFailure escalation hook (with a maxLeaderFailures threshold, exposed as onPersistentWorkerFailure in createClientServices), invoked after consecutive leader-session failures so apps can surface or recover from a stuck worker connection instead of backing off silently forever. (6ad2084)

Patch Changes

  • Add routed scripts to the scripted test language model (per-session cursors for supervisor/sub-agent scenarios) and restore per-message span publishing from the chat thread (minimap markers and prompt navigation). (bdf9f68)

  • Resolve an object's canonical navigation path through NavigationOperation.ResolveNavigationTargets, so opening an object from a generic surface (a card, a search result, an agent following a reference) lands where the nav tree shows it — its collection, or its type's sidebar section — instead of the hidden database path every object falls back to. This also fixes the nav tree showing no selection for objects opened from cards. (5b05d75)

  • Plugin-declared decks and deck scroll stability. A type can now declare how the deck behaves when one of its objects is the root: AppAnnotation.DeckAnnotation carries a DeckSpec (initial planks and a chain of levels), LayoutOperation.Open accepts root + level so opening at a level reuses that level's plank and closes the levels below it, Collections are navigation targets that open their contents as planks, and the mailbox declares mailbox / message / attachment (meta-click opens a message in its own plank; a message swap carries the open companion along). Deck scrolling is now strictly intent-driven: an in-deck click yields to the navigation it triggers, navigations re-issue if a reflow kills the glide, browser scroll anchoring is disabled on the deck viewport, a companion opening past the trailing edge is revealed by exactly the overflow, and stale companionPlanks entries are pruned. (f10b1ce)

  • ProgressMeter now shows a live elapsed-time readout for indeterminate tasks (no known total) instead of a perpetually-pulsing bar; the fractional bar and remaining-time ETA render only when a total is known. (717edc0)

  • Add dx space export and dx space import commands. Export writes a space archive to disk in either the binary storage-dump format (includes document history) or a JSON snapshot of current object state; import reads an archive of either format back as a new space. (179afc6)

  • Fix comment author attribution and reset-device reload. useIdentity now seeds its atom with the service's synchronous snapshot so the current identity is available on the first render instead of a transient undefined — a comment sent in that window was stamped with an empty sender and never matched its author, hiding the edit affordance. During client.reset() the worker-reconnect handler now reloads to the origin (fresh boot) rather than the stale current route, and Client.resetting exposes that state. SQLite hypercore storage drains in-flight writes on close() so a save racing reset teardown can't stall or reject against a torn-down connection. (eec72c5)

  • Restore the iframe shell (shell='./shell.html') client-services connection after the effect-rpc migration. The app now re-serves its services to the shell over effect-rpc (matching the shell's ClientServicesProxy consumer) instead of the removed protobuf peer, and the shell provides its parent origin upfront so the effect-rpc client can initiate the connection without deadlocking. Fixes apps that embed the external shell iframe hanging on startup. (410a019)

  • Use the WebRTC transport for bun as well as node: bump node-datachannel to 0.32.3 (the 0.30.0 darwin-arm64 binary crashed under both runtimes) and remove the obsolete bun memory-transport guard. CLI halo share prints the joinable URL and validates --host as an absolute URL. (d547045)

  • Fix an unhandled SqlError when a hypercore file load races client teardown. If the SQLite connection is torn down while a background SqliteRandomAccessFile read is in flight (and that file's own close() hasn't run yet), the read now falls back to an empty buffer instead of rethrowing "database connection is not open" as an unhandled rejection. (da66270)

  • Import ECHO data-access hooks (useQuery, useObject, useType, usePagination, …) directly from @dxos/echo-react in Composer plugins and UI packages instead of through the @dxos/react-client/echo re-export, decoupling pure ECHO data access from @dxos/react-client. (b8c0825)

  • Auto-create a recurring sync Routine when a mailbox or calendar is bound to a connection (new connection, multi-target selection, or reusing an existing connection); the toolbar "Sync" action force-runs it and disables while a sync is already in progress. Fixes a legacy-DXN compatibility gap in refToEffectSchema and a bug where cancelling a Gmail sync left its progress monitor stuck at "running". (923d5be)

  • Fix the mailbox silently dropping a compose draft, which has no thread. A draft with no threadId is now created as a thread of one — keyed on a fresh id — so the mailbox list's whole-thread semi-join and conversation grouping keep it. Also align the JMAP Email schema with RFC 8621, where threadId is a required, server-set property. (85893fe)

  • Fix memoized language model dynamic-value remapping: collect tokens over the normalized prompt so timestamp metadata cannot shift positional ids, and preserve per-pattern regex flags so uppercase-hex UUIDs match. (12fd785)

  • Stop the client-side diagnostics from retaining the whole ECHO client graph. Every QueryResultImpl added a record to a module-level QUERIES set that nothing ever pruned, and while the record held no direct reference to the query, it held a StackTrace — which keeps an unformatted Error, and V8 retains a captured stack structurally, with a strong reference to each frame's receiver, until .stack is read. The frame for new QueryResultImpl(...) therefore pinned the query, its query context, the hypergraph, the client, the database and every document loaded through them: one entire client graph per query, for the lifetime of the process. On hosts that never read the diagnostics this was unbounded — a Cloudflare Worker running ECHO operations on a cron trigger OOMed after ~390 invocations. QueryResultCache is a WeakDictionary precisely so results can be collected; this defeated it.

QUERIES now holds weak refs pruned by a FinalizationRegistry, so a query, its diagnostic and its graph collect together. OBJECT_DIAGNOSTICS had the same defect on a longer fuse and now stores the formatted string; being keyed by object id and never evicted, it is also capped at 1,000 entries with oldest-first eviction. StackTrace formats once and releases the Error, making the release deterministic rather than incidental, and documents the retention hazard. (5f08a6a)

  • Report writes that were never sent, and stop a scheduled callback from running concurrently with itself. UpdateScheduler now starts its callback from a single site: runBlocking/forceTrigger funnel into the scheduled runner instead of claiming it themselves, so two passes can no longer each claim part of the shared queue — the loss behind server-side writes arriving without their data. RepoProxy.flush() rejects when a batch could not be sent instead of always resolving, so a short-lived writer whose isolate is disposed the moment flush resolves can fail its operation rather than silently drop the write. (3761762)

  • Chats no longer spend a query-skills call before every enable-skills — the available-skills list is already rendered into the system prompt — and project chats pre-bind the artifact-type skills, so creating the artifact you asked for costs fewer tool calls. Deleting an object now also closes planks for the objects it cascade-deletes (e.g. a project's chats), which previously stayed open pointing at removed objects. (4bb7e3b)

  • Fix: re-entering Suggesting mode no longer strikes through text typed on main in between. An unedited per-user suggestion branch whose fork point fell behind is retired and re-forked at the current heads; a branch with pending suggestions is preserved. (686fac1)

  • Documents created from the editor's slash/link menu are now filed in the same collection as the document they were created from, instead of the space root. (ac51564)

  • Assigning a nested record read off a detached (never-added) object into a database-backed object now copies it by value, as it already did for records read off database-backed objects. Previously it threw Object references must be wrapped with \Ref.make``, because the copy-on-assign path only recognized proxies from the database handler; callers had to spread by hand. (a83d98a)

  • EchoDatabase.waitUntilHeadsReplicated now also waits for the client's replica of the space root document to carry the given heads, so a query issued right after it sees the replicated objects instead of racing the client's routing table. (4f24c4e)

  • usePagination's isLoading now reflects genuine query settlement instead of clearing on the next microtask regardless of delivery, so consumers can reliably distinguish "still loading" from "loaded and empty" even for async, feed-backed queries. The mailbox article uses this to fix a bug where it could briefly flash the wrong empty-state message (e.g. "No connections configured") while a large mailbox's messages were still loading. (9cde1c6)

  • Fix the function bundler's resolveDir in the built @dxos/edge-compute/native entry. It was computed with new URL('.', import.meta.url).pathname, which Vite's library-mode build treats as an asset reference and base64-inlines as a data:video/mp2t;base64,… data URL. In dist that left resolveDir pointing at garbage, so the bundler could not resolve @dxos/compute-runtime / @dxos/functions-runtime-cloudflare and function bundling failed. The directory is now derived via dirname(fileURLToPath(import.meta.url)), which the bundler leaves untouched. (d79482a)

  • Publish the HALO Effect service packages (@dxos/halo, @dxos/halo-adapter-client, @dxos/halo-react) and begin migrating Composer/plugins off direct @dxos/client HALO access onto them: plugin-client now provides Identity.Service / Space.Service layer specs and wraps the app in HaloProvider. (6439417)

  • Adopt the triple-slash echo:///<objectId> form as the canonical local EID. EID.make({ entityId }) now emits echo:///<id>, and EID.parse normalizes the legacy single-slash echo:/<id> form to it so legacy and freshly-produced EIDs compare equal. The legacy form is still accepted on read.

  • @dxos/debug@0.11.0
  • @dxos/invariant@0.11.0
  • @dxos/node-std@0.11.0 (6a03a30)

  • Send $survey_completed with captured user feedback so PostHog survey destinations trigger, and serialize errors logged as context to OTel instead of dropping them. (41d1e4a)

  • Fix the daemon watchdog failing to start with ERR_MODULE_NOT_FOUND after the vite/rolldown build migration by importing from the correct dist/lib entrypoint. (22fdfa4)

  • Fix corruption of large query results containing emoji or other astral characters. The QueryService RPC now encodes its payloads with Effect schemas instead of protobuf, avoiding a @protobufjs/utf8 bug that injected a lone surrogate into string fields larger than 8KB and broke object hydration. (114fb98)

  • Add an in-app @dxos/log viewer (new @dxos/react-ui-debug LogPanel) so logs can be filtered, level-configured, and copied without opening DevTools; plugin-debug surfaces it as an R0 companion tab and a status-bar popover, and the devtools performance panel reuses the same component. Make the devtools subscribeToFeeds/subscribeToSpaces feedKeys/spaceKeys payload fields optional, fixing a Storage-panel schema decode error on empty subscriptions. Reimplement the devtools performance Panel and PanelContainer on the shared @dxos/react-ui Panel primitive. (b591791)

  • Move the useFlush hook from @dxos/plugin-assistant/hooks to @dxos/react-client/echo. It operates on a Space, so it belongs with the other space hooks; import it from @dxos/react-client/echo instead of @dxos/plugin-assistant/hooks. (c9da903)

  • Supporting changes for the new plugin-blogger / plugin-typefully feature:

  • @dxos/plugin-connector: expose Connection types via a new ./types export subpath so provider plugins can consume the connection contract without pulling the full package barrel.
  • @dxos/react-ui: Card.Root now accepts and forwards onKeyDown, enabling keyboard-interactive cards (Enter/Space activation) without a cast. (e0e1a9f)

  • useThemeContext no longer throws when no ThemeProvider is mounted; it falls back to the default theme (with a one-time warning) so error-reporting surfaces such as the fatal dialog remain renderable. (2fe5a7a)

  • Logger panel review follow-ups:

  • @dxos/react-ui-debug: each Logger.Root recording session now self-filters via its own parsed filter and registers in a module-level recorder registry that composes the shared @dxos/log config (union) and restores it on the last release — concurrent panels with divergent filters no longer clobber each other. The log list gains a per-row checkbox (Copy log then exports only the checked rows), full-line selection styled via aria-current/dx-current, arrow-key navigation between lines (inner controls opt out of the roving tabindex), Space to toggle expansion, and Enter to toggle the checkbox. Expanded rows render message/context via JsonHighlighter and error stacks via the shared ErrorStack (clickable vscode:// frames). Each log record also retains the derived package (from its source path) for display/export.
  • @dxos/react-ui: ErrorStack now accepts a classNames prop so consumers can style the trace container. (c9651f1)

  • Move contexts, hooks, constants and helpers out of React component modules into sibling modules so each component module is a react-refresh boundary. Public package APIs are unchanged; the previously exported names are re-exported from each directory barrel. (37874ce)

  • The inbox message view selector (HTML / Markdown / Plain) now persists across messages and sessions. The choice is stored alongside the other inbox settings (the loadRemoteImages toggle) in the plugin's settings store, so it survives reloads instead of resetting to HTML on every open. Also reorganizes useArticleKeyboardNavigation under AttentionProvider (no change to the @dxos/react-ui-attention public exports). (3b4a7c8)

  • The debug Logger now persists per-file log level overrides across reloads (via a local-backed react-ui-attention view-state aspect instead of component-local state) and shows the full repo-relative source path — as a file key in the expanded row's JSON, and as the row tooltip — while the row column keeps showing just the basename. (46ac889)

  • Bump CodeMirror packages (@codemirror/state, @codemirror/view, @codemirror/lang-markdown) to their latest patch releases. (53fde97)

  • HeyGen avatar/voice pickers now list only the account's own assets (/v3/avatars?ownership=private, /v3/voices?type=private) instead of HeyGen's public catalog, with names trimmed (HeyGen returns user-named assets with leading newlines / non-breaking spaces) and sorted alphabetically; list requests are bounded by a timeout so a slow response can't hang the picker. Listbox.ItemContent no longer reserves the leading icon column when no icon is set, so icon-less rows are flush to the edge instead of indented. (277e365)

  • The conversation view (MessageArticle) now renders threads as a Mosaic stack: each message is a tile with its own toolbar, so Reply/Reply All/Forward/AI reply/Delete act on that specific message rather than always targeting the newest one. Body view controls (view mode, load remote images) and collapse-all/expand-all move to a single thread toolbar that applies to the whole conversation, and each message can be individually collapsed to a compact summary. The per-message Message.Toolbar no longer includes the view-mode switcher or load-images toggle.

By default only the most recent message is expanded and the rest are collapsed. Replying to a message now records the specific message it answers (parentMessage), so the draft renders directly after that message in the thread rather than always at the bottom, and it is smoothly scrolled fully into view.

Listbox.Item rows with an onClick (not just selectable ones) are now keyboard-focusable and respond to Enter/Space, matching native <button> activation. (2a68c3b)

  • Fix mailbox paging and the list blanking during sync. usePagination now keeps the previously-shown page across a query-identity change instead of resetting to empty + loading, and the virtualizer pagination hook re-arms getNext after a page lands and no longer misreads a reordered item as an eviction. The mailbox renders a loading spinner in-flow at the end of the list rather than replacing the whole panel. (0afbf15)

  • TagIndex membership now compares tag ids by their entity id rather than their full (space-absolute) URI, so tags applied to feed objects survive a space export/import — the importer mints a new space id, which previously left every stored tag key unmatchable. Absolute keys already in existing spaces keep resolving (no migration), and a relatively-stored key resolves against an absolute query and vice versa. (96109be)

  • Fix shell bundle build failing with ENOENT on a clean checkout. (14848a1)

  • e2ePreset now defaults timeout to 60s. Playwright's 30s default equalled the preset's action bound, leaving a test no budget beyond one slow action — and a storybook-backed suite spends most of it on the story compile the first test pays for, which measured 29.3s against the 30s cap. (bce1dbc)

  • Move DraftMessage out of @dxos/plugin-inbox into @dxos/types, and move the generic email-sync pipeline stages (excluding the SyncBinding-coupled toCommitUnit) out of @dxos/plugin-inbox into @dxos/pipeline-email, so these can be reused without depending on a full app-framework plugin. Connection and SyncBinding remain in @dxos/plugin-connector; toCommitUnit and factsCommit (both coupled to SyncBinding) live in @dxos/plugin-inbox. (6d2afe0)

  • Reorganize CodeMirror extensions into themed folders (core, state, behavior, decoration, language, collab, completion, streaming, structure, demo, debug) with per-folder barrels; the package's public export set is preserved. Fixes the misspelled exported type CompoetionContextCompletionContext, de-duplicates escapeRegExpSource into util (closing a latent tag-escaping bug in extendedMarkdown's mixed parser), and adds an xmlTags characterization test suite. xmlTags block widgets now keep their portal alive across viewport culls (removing the blank/flicker on scroll-back for known-height embeds). @dxos/ui: adds a string overload to Domino.of for custom-element tags (e.g. dx-icon); @dxos/plugin-assistant drops the now-unneeded Domino.of(... as any) casts. (a256a87)

  • Document versioning: Google-Docs-style suggestion review.

  • @dxos/ui-editor: suggestChanges (inline per-change accept/reject over a proposal) plus word-level diffHunks; a multi-author suggestions({ sources }) overlay and groupHunks grouping; the comments / diff / suggest review extensions are grouped under a new review/ folder (package barrel exports unchanged).
  • @dxos/app-framework: NamePopover moved to @dxos/app-framework/ui, decoupled from translations via a submitLabel prop.
  • @dxos/plugin-markdown: branch/merge/checkpoint exposed as agent skill tools; a suggest diff-view mode; the compare/diff overlay is reconfigured through a CodeMirror Compartment so switching views no longer remounts the editor (rebinding automerge / losing selection). The branch banner's Compare toggle becomes a three-way [Base | Diff | Branch] view selector — Base shows the parent content at the anchor read-only.
  • @dxos/plugin-space: NamePopover removed from @dxos/plugin-space/components (relocated to @dxos/app-framework/ui); VersioningState.compare (boolean) becomes view (base | diff | branch).
  • @dxos/types: new ContentBlock.Change (a suggested edit — before/after) so a suggestion renders through the message tile.
  • @dxos/react-ui-thread: Message.Tile renders the change block (struck original → proposed text) with Accept/Reject via new onAcceptChange/onRejectChange thread callbacks; CommentThread is decoupled from @dxos/react-client (metadata/activity/identity injected as props).
  • @dxos/plugin-review: a unified review companion — comment threads and suggestion cards in one surface. Suggestions reactively tracks the document's active kind:'suggestion' branches (one bound probe per branch) and renders each grouped change as a change-block tile, routing Accept/Reject to the durable AcceptChange/RejectChange ops.
  • @dxos/plugin-markdown: a SuggestEdit operation + "Suggest edits" authoring action that find-or-creates the caller's per-author suggestion branch and edits it. (3f1fc67)

  • Fix markdown list formatting: toggling between bullet/task/ordered list styles now converts markers in place instead of nesting them, list markers align with the hanging indent, and the outliner block drag shows a full-width preview with a stable empty drop placeholder (no flicker when dragging items with children). (20153c0)

  • Fix XML tag widgets rendering blank after the document is replaced — widget state applied around the reset (for example tool call rows when returning to a chat) now reaches the mounted widget. (a1c89fa)

  • Disable the Tailwind/Vite file watcher in ThemePlugin when running under Vitest. Its server.watch config was a non-null object that overrode the test runner's watch: null, keeping a live watcher whose per-file fs_event handles (registered by Tailwind's @source scan) were never released — hanging single-pass vitest run teardown so the process never exited. HMR-ignore patterns are retained for interactive storybook dev / vite dev. (4df6cf3)

215 packages in this release @dxos/agent-runtime@0.11.0 @dxos/ai@0.11.0 @dxos/app-framework@0.11.0 @dxos/app-graph@0.11.0 @dxos/app-solid@0.11.0 @dxos/app-toolkit@0.11.0 @dxos/assistant@0.11.0 @dxos/assistant-e2e@0.11.0 @dxos/assistant-evals@0.11.0 @dxos/assistant-toolkit@0.11.0 @dxos/async@0.11.0 @dxos/av@0.11.0 @dxos/beast@0.11.0 @dxos/blade-runner@0.11.0 @dxos/brand@0.11.0 @dxos/cli-util@0.11.0 @dxos/client@0.11.0 @dxos/client-e2e@0.11.0 @dxos/client-protocol@0.11.0 @dxos/client-services@0.11.0 @dxos/codec-protobuf@0.11.0 @dxos/codemorph@0.11.0 @dxos/composer-forensics@0.11.0 @dxos/compute@0.11.0 @dxos/compute-hyperformula@0.11.0 @dxos/compute-runtime@0.11.0 @dxos/conductor@0.11.0 @dxos/config@0.11.0 @dxos/context@0.11.0 @dxos/crawler@0.11.0 @dxos/credentials@0.11.0 @dxos/crx-protocol@0.11.0 @dxos/crypto@0.11.0 @dxos/debug@0.11.0 @dxos/deus@0.11.0 @dxos/devtools@0.11.0 @dxos/devtools-extension@0.11.0 @dxos/discord-bot@0.11.0 @dxos/discord-worker@0.11.0 @dxos/display-name@0.11.0 @dxos/dx-build@0.11.0 @dxos/dx-compile@0.11.0 @dxos/dx-tools@0.11.0 @dxos/dx-trace-imports@0.11.0 @dxos/echo@0.11.0 @dxos/echo-client@0.11.0 @dxos/echo-client-e2e@0.11.0 @dxos/echo-doc@0.11.0 @dxos/echo-generator@0.11.0 @dxos/echo-host@0.11.0 @dxos/echo-panproto@0.11.0 @dxos/echo-protocol@0.11.0 @dxos/echo-query@0.11.0 @dxos/echo-react@0.11.0 @dxos/echo-solid@0.11.0 @dxos/edge-client@0.11.0 @dxos/edge-compute@0.11.0 @dxos/effect@0.11.0 @dxos/effect-atom-solid@0.11.0 @dxos/effect-proto@0.11.0 @dxos/effect-zod@0.11.0 @dxos/env-tests@0.11.0 @dxos/errors@0.11.0 @dxos/esbuild-plugins@0.11.0 @dxos/eslint-plugin-rules@0.11.0 @dxos/examples@0.11.0 @dxos/extractor@0.11.0 @dxos/extractor-lib@0.11.0 @dxos/feed@0.11.0 @dxos/feed-store@0.11.0 @dxos/fixtures@0.11.0 @dxos/functions-runtime-cloudflare@0.11.0 @dxos/functions-simulator-cloudflare@0.11.0 @dxos/functions-testing@0.11.0 @dxos/graph@0.11.0 @dxos/halo@0.11.0 @dxos/halo-adapter-client@0.11.0 @dxos/halo-e2e@0.11.0 @dxos/halo-react@0.11.0 @dxos/hypercore@0.11.0 @dxos/i18n@0.11.0 @dxos/index-core@0.11.0 @dxos/introspect@0.11.0 @dxos/introspect-mcp@0.11.0 @dxos/introspect-tools@0.11.0 @dxos/invariant@0.11.0 @dxos/keyboard@0.11.0 @dxos/keyring@0.11.0 @dxos/keys@0.11.0 @dxos/kv-store@0.11.0 @dxos/link@0.11.0 @dxos/lit-grid@0.11.0 @dxos/lit-ui@0.11.0 @dxos/lock-file@0.11.0 @dxos/lockfile-explorer@0.11.0 @dxos/log@0.11.0 @dxos/log-store-idb@0.11.0 @dxos/markdown@0.11.0 @dxos/mcp-client@0.11.0 @dxos/merkle-search-tree@0.11.0 @dxos/messaging@0.11.0 @dxos/migrations@0.11.0 @dxos/network-manager@0.11.0 @dxos/nlp@0.11.0 @dxos/node-std@0.11.0 @dxos/observability@0.11.0 @dxos/operation@0.11.0 @dxos/phoenix@0.11.0 @dxos/pipeline@0.11.0 @dxos/pipeline-discord@0.11.0 @dxos/pipeline-email@0.11.0 @dxos/pipeline-rdf@0.11.0 @dxos/pipeline-transcription@0.11.0 @dxos/process@0.11.0 @dxos/progress@0.11.0 @dxos/proto-guard@0.11.0 @dxos/protobuf-compiler@0.11.0 @dxos/protobuf-test@0.11.0 @dxos/protocols@0.11.0 @dxos/random@0.11.0 @dxos/random-access-storage@0.11.0 @dxos/react-client@0.11.0 @dxos/react-edge-client@0.11.0 @dxos/react-error-boundary@0.11.0 @dxos/react-hooks@0.11.0 @dxos/react-input@0.11.0 @dxos/react-list@0.11.0 @dxos/react-ui@0.11.0 @dxos/react-ui-attention@0.11.0 @dxos/react-ui-audio@0.11.0 @dxos/react-ui-board@0.11.0 @dxos/react-ui-calendar@0.11.0 @dxos/react-ui-canvas@0.11.0 @dxos/react-ui-canvas-compute@0.11.0 @dxos/react-ui-canvas-editor@0.11.0 @dxos/react-ui-card@0.11.0 @dxos/react-ui-chat@0.11.0 @dxos/react-ui-components@0.11.0 @dxos/react-ui-dashboard@0.11.0 @dxos/react-ui-debug@0.11.0 @dxos/react-ui-diagram@0.11.0 @dxos/react-ui-dnd@0.11.0 @dxos/react-ui-editor@0.11.0 @dxos/react-ui-experimental@0.11.0 @dxos/react-ui-form@0.11.0 @dxos/react-ui-gameboard@0.11.0 @dxos/react-ui-geo@0.11.0 @dxos/react-ui-graph@0.11.0 @dxos/react-ui-grid@0.11.0 @dxos/react-ui-introspect@0.11.0 @dxos/react-ui-list@0.11.0 @dxos/react-ui-markdown@0.11.0 @dxos/react-ui-masonry@0.11.0 @dxos/react-ui-mcp@0.11.0 @dxos/react-ui-menu@0.11.0 @dxos/react-ui-mosaic@0.11.0 @dxos/react-ui-pickers@0.11.0 @dxos/react-ui-rdf@0.11.0 @dxos/react-ui-search@0.11.0 @dxos/react-ui-syntax-highlighter@0.11.0 @dxos/react-ui-table@0.11.0 @dxos/react-ui-tabs@0.11.0 @dxos/react-ui-task@0.11.0 @dxos/react-ui-thread@0.11.0 @dxos/react-ui-transcription@0.11.0 @dxos/rpc@0.11.0 @dxos/rpc-tunnel@0.11.0 @dxos/rpc-tunnel-e2e@0.11.0 @dxos/schema@0.11.0 @dxos/shell@0.11.0 @dxos/solid-ui@0.11.0 @dxos/solid-ui-geo@0.11.0 @dxos/sql-sqlite@0.11.0 @dxos/stories-assistant@0.11.0 @dxos/stories-brain@0.11.0 @dxos/stories-inbox@0.11.0 @dxos/stories-lens@0.11.0 @dxos/stories-projects@0.11.0 @dxos/storybook-addon-logger@0.11.0 @dxos/storybook-testing@0.11.0 @dxos/storybook-utils@0.11.0 @dxos/teleport@0.11.0 @dxos/teleport-e2e@0.11.0 @dxos/teleport-extension-automerge-replicator@0.11.0 @dxos/teleport-extension-gossip@0.11.0 @dxos/teleport-extension-object-sync@0.11.0 @dxos/teleport-extension-replicator@0.11.0 @dxos/test-utils@0.11.0 @dxos/timeframe@0.11.0 @dxos/toolbox@0.11.0 @dxos/tracing@0.11.0 @dxos/types@0.11.0 @dxos/typings@0.11.0 @dxos/ui@0.11.0 @dxos/ui-editor@0.11.0 @dxos/ui-theme@0.11.0 @dxos/ui-types@0.11.0 @dxos/util@0.11.0 @dxos/vendor-hypercore@0.11.0 @dxos/vendor-hyperformula@0.11.0 @dxos/vendor-kbn-handlebars@0.11.0 @dxos/vendor-quickjs@0.11.0 @dxos/versioning@0.11.0 @dxos/vite-plugin-icons@0.11.0 @dxos/vite-plugin-import-source@0.11.0 @dxos/vite-plugin-log@0.11.0 @dxos/vite-plugin-log-example@0.11.0 @dxos/vite-plugin-shutdown@0.11.0 @dxos/vscode-extension@0.11.0 @dxos/web-context@0.11.0 @dxos/web-context-react@0.11.0 @dxos/web-context-solid@0.11.0 @dxos/websocket-rpc@0.11.0 @dxos/worker-framework@0.11.0 @dxos/x@0.11.0
Source: README.md, updated 2026-08-05