feat: implement ambient web component - #49
Merged
Natalia Markitantova (markitosha) merged 52 commits intoJun 8, 2026
Merged
Conversation
…d endpoint-specific logic
…ket controller feat: added separate ambient controller
…gs, and recording state
…nd error management
…d removing unused properties
Copilot started reviewing on behalf of
Natalia Markitantova (markitosha)
May 12, 2026 13:12
View session
…sole-integration-dxg-1047
Contributor
There was a problem hiding this comment.
Pull request overview
Implements an ambient-capture web component (<corti-ambient>) alongside a supporting ambient context/root, recording button, and stream socket controller, while refactoring shared dictation/ambient plumbing (contexts + sockets) into reusable mixins and a generic SocketController.
Changes:
- Added ambient components and Storybook stories (
corti-ambient,ambient-root,ambient-recording-button) backed by a newAmbientController. - Refactored connection lifecycle into a reusable
SocketController, and refactored root context responsibilities into composable Lit context mixins. - Extended event typing and dispatch to support stream messages (e.g.,
facts, stream transcript/usage variants) and updated exports/registrations.
Reviewed changes
Copilot reviewed 33 out of 33 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| stories/recording-button.stories.ts | Updates Storybook imports to use dictation-recording-button. |
| stories/corti-ambient.stories.ts | Adds Storybook coverage for the new <corti-ambient> component. |
| stories/ambient-root.stories.ts | Adds Storybook coverage for the new <ambient-root> provider + composed children. |
| src/utils/events.ts | Expands event detail types to include stream variants; adds facts event helper. |
| src/types.ts | Adds a shared inbound message union type for recording socket messages. |
| src/index.ts | Registers/exports new components (ambient + renamed recording button) and types. |
| src/controllers/socket-controller.ts | Introduces shared socket lifecycle/queueing controller used by dictation + ambient. |
| src/controllers/languages-controller.ts | Stops mutating host dictation config directly; relies on emitted events instead. |
| src/controllers/dictation-controller.ts | Refactors dictation socket logic onto SocketController. |
| src/controllers/ambient-controller.ts | Adds stream/ambient socket controller built on SocketController. |
| src/contexts/root-context.ts | Adds a shared root context base built from new mixins. |
| src/contexts/mixins/types.ts | Adds common mixin constructor typing helper. |
| src/contexts/mixins/recording-state-context.ts | New recording-state context provider + event synchronization. |
| src/contexts/mixins/proxy-context.ts | New socket URL/proxy context provider. |
| src/contexts/mixins/languages-context.ts | New languages context provider with lazy initialization behavior. |
| src/contexts/mixins/keybindings-context.ts | New keybinding contexts + defaults on context request. |
| src/contexts/mixins/devices-context.ts | New devices/selected-device contexts + lazy initialization behavior. |
| src/contexts/mixins/auth-context.ts | New auth contexts + token parsing and authConfig support. |
| src/contexts/dictation-context.ts | Refactors dictation-root to extend RootContext and keeps dictation config contexts. |
| src/contexts/ambient-context.ts | Adds ambient-root and its ambient config + interactionId contexts. |
| src/constants.ts | Adds DEFAULT_STREAM_CONFIG for ambient streaming. |
| src/components/settings-menu.ts | Updates recording state context import to the new mixin location. |
| src/components/recording-button-base.ts | Generalizes recording button logic into RecordingButtonBase usable by dictation + ambient. |
| src/components/language-selector.ts | Updates contexts import locations (languages context now from mixin). |
| src/components/keybinding-selector.ts | Updates keybinding context import location (mixin). |
| src/components/keybinding-input.ts | Updates keybinding context import location (mixin). |
| src/components/dictation-recording-button.ts | Adds a concrete dictation recording button built on RecordingButtonBase. |
| src/components/device-selector.ts | Updates devices context import location (mixin). |
| src/components/corti-root.ts | Adds shared host base class for all-in-one components (corti-dictation, corti-ambient). |
| src/components/corti-dictation.ts | Refactors to extend CortiRoot and use dictation-recording-button. |
| src/components/corti-ambient.ts | Adds the new all-in-one ambient component built on CortiRoot. |
| src/components/ambient-recording-button.ts | Adds ambient recording button built on RecordingButtonBase, validates interactionId. |
| biome.json | Adds Biome overrides for mixin files (allow any and unused private members). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…ation-dxg-1047' of https://github.com/corticph/dictation-web-sdk into implement-ambient-web-component-beta-for-console-integration-dxg-1047
…and improve clarity
… context handling
Rely on RecordingSocketInboundMessage as the generic bound so switch cases dispatch events directly from message.
Self-hosted ci runners were blocking workflow jobs from completing reliably.
Add lit, @corti/sdk, and @lit/context to root devDependencies so tsc -p core resolves on CI; align Biome schema and format recording-button-base imports.
pnpm version at the workspace root does not honor --dir; run it inside each package folder instead.
tsc output keeps @core imports that are not published; only bundle.js inlines core. Point main/module and exports.import at bundle.js so Vite and other bundlers load the correct artifact.
Shared core tags are bundled into both dictation-web and ambient-web. Guard registration so loading both packages on one page does not throw.
Wire dictation and ambient to @corti/core-web workspace imports, add core/package.json, and strip the bundled core dep from dist manifests before publish.
Use @core path alias for shared source only. safeCustomElement on all custom elements. Ship self-contained .d.ts via dist/core/ rewrite; keep bundle.js as the runtime entry.
Per-package READMEs for @corti/dictation-web and @corti/ambient-web with install, quick start, and links to docs.corti.ai. Copy README into dist on build so npm publish includes them.
Publish from package roots again so dist/bundle.js matches legacy jsdelivr URLs. Consolidate build scripts, commit per-package LICENSE files, and drop dist/package.json copying.
Move virtual-mode transcription updates into a util; only inject default doctor/patient channels when participants are empty, and clear auto-injected defaults on disable via reference equality.
Self-hosted ci runners are not available for this repository.
Juozas (juozaspeleckas)
previously approved these changes
Jun 5, 2026
Juozas (juozaspeleckas)
left a comment
Contributor
There was a problem hiding this comment.
Looks good!
There is one issue with running storybook or I am doing something wrong 🤦
Pin Storybook addons to 10.1.5 to prevent startup crashes from version drift, update package repository URLs to speech-web-components, and fix story paths after the monorepo split.
Juozas (juozaspeleckas)
approved these changes
Jun 5, 2026
Natalia Markitantova (markitosha)
enabled auto-merge (squash)
June 8, 2026 08:48
Natalia Markitantova (markitosha)
deleted the
implement-ambient-web-component-beta-for-console-integration-dxg-1047
branch
June 8, 2026 08:48
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Ships the Ambient speech web component and the repo split needed to maintain dictation and ambient as separate npm packages without duplicating UI or socket code.
Why: Corti Console’s AI Studio ambient preview (DXG-1047) needs a browser component on the Streams API, not Transcribe. Dictation already had most of the plumbing (auth context, devices, recording UX, WebSocket lifecycle). This PR extracts that into shared
core/and adds an ambient-specific layer on top.What you get
New:
@corti/ambient-web—<corti-ambient>and modular<ambient-*>elements. Connects viaAmbientControllerto/streams, requiresinteractionId, surfacestranscript/facts/audio-event(and the same auth, proxy, and recording-state events dictation already had). Virtual mode mixes display-media audio with the mic and drives multichannel transcription; integrator-suppliedparticipantsonambientConfigare kept when non-empty (defaults only when empty).Unchanged for dictation users:
<corti-dictation>and<dictation-*>keep the same public API. The package is now@corti/dictation-webpublished fromdictation/with shared internals compiled in.Same page: Both bundles can load together —
safeCustomElementavoids double-registration of sharedspeech-*tags.Mixins and inheritance
Shared behavior is composed with Lit context mixins under
core/src/contexts/mixins/, then extended per product:RootContext=DevicesContextMixin→RecordingStateContextMixin→KeybindingsContextMixin→LanguagesContextMixin→AuthContextMixin→ProxyContextMixin→LitElementEach mixin owns one concern (
@providefor access token / proxy URL, device list, languages, keybindings, recording state, etc.). Package roots inherit that stack and add only what differs:DictationRoot/AmbientRootextendRootContextand providedictationConfigorambientConfig,interactionId,virtualMode, …<corti-dictation>/<corti-ambient>extendCortiRoot— thin all-in-one shells that render the matching*-rootand recording button via refs, forwarding auth/socket propsDictationRecordingButton/AmbientRecordingButtonextendRecordingButtonBase(media capture, keybindings, socket send queue) with package-specificSocketControllersubclasses (DictationControllervsAmbientController) and connect config types*-baseclasses incore/(device-selector-base,language-selector-base,settings-menu-base, …); dictation/ambient packages register the public custom element namesInbound WebSocket message shapes are centralized in
core/src/socket-messages.tssoRecordingButtonBasecan type the handler once; transcribe vs stream message unions are narrowed in each package.How the repo is organized
Single pnpm workspace:
core/(not published;@core/*alias),dictation/,ambient/. Publish is tag-driven: one version tags both packages; artifacts aredist/bundle.jsper package (jsDelivr-compatible path restored in this branch).Prerelease on npm tag
ambient: 0.7.0-ambient.19.Elsewhere
/sdk/ambient/*, dictation pages kept aligned withmainwhere possible@corti/ambient-web@0.7.0-ambient.19