Mihe

React SDK reference

Every export of @mihe-dev/react, with its props, arguments and types.

@mihe-dev/react is ES modules with TypeScript types, for React 18 and later. Its entry is marked "use client", so in a Next.js App Router app you can import it from a server component's file and render the provider in your layout.

npm install @mihe-dev/react

Not using React? The JavaScript SDK is the same integration as function calls, and lists its methods.

AssistantProvider

Connects to the runtime and makes the assistant available to everything inside it. Render it once, near the root, around the parts of your app the assistant should know about.

<AssistantProvider
  url="wss://runtime.mihe.dev/v1/ws"
  publicKey={process.env.NEXT_PUBLIC_MIHE_PUBLIC_KEY!}
  getUserToken={() => fetch("/api/mihe/token").then((r) => r.text())}
  navigate={(route) => router.push(route)}
  onActionComplete={() => queryClient.invalidateQueries()}
>
  {children}
  <AssistantWidget />
</AssistantProvider>
PropType
urlstringRequired. The runtime's WebSocket address.
publicKeystringRequired. The app's public key from the dashboard. Safe to ship in a browser bundle.
getUserToken() => Promise<string>Required. Fetches a token for the signed-in user from your own server. The runtime reads who the user is and what they may do from this token's verified claims, and from nothing else. See user tokens.
navigate(route: string) => voidYour router's push. Without it, navigation is a full page load, which works but throws away your app's state.
openModal(modalKey: string) => void | booleanOpens a dialog the assistant wants to show. Return false for a key your app can't open, so the assistant is told instead of claiming it opened.
onActionComplete(action: { actionName: string; status: ProposalStatus; result?: unknown }) => voidCalled when an approved action finishes, whatever the outcome. The assistant changes data your page is showing; invalidating your cache here keeps the page current.
debugbooleanLogs what each screen costs to the console: the tokens one answer re-sends, and the largest tools. Use while building an integration. See what a screen costs.
childrenReactNodeRequired.

AssistantWidget

The assistant's interface: by default an orb that opens a menu of chat and voice. Render it inside the provider. Most of its look is set in the dashboard, so it changes without a deploy; a prop here overrides the setting. See the widget.

PropTypeDefault
form"orb" | "classic"dashboard settingorb shows voice in itself and keeps the page visible. classic is a launcher that opens a panel.
draggablebooleandashboard settingOrb only. The user can drag it to either side, and it remembers where.
corner"bottom-right" | "bottom-left"dashboard settingOrb only. Where it sits until dragged.
voiceModes("hands-free" | "hold")[]dashboard settingOrb only. Narrows the voice modes the app allows, and never widens them.
showLauncherbooleantrueTurn off when your app has its own trigger.
defaultOpenbooleanfalseOpen on first mount.
launcherIconReactNodedashboard icon, else the Mihe markWhat the launcher shows.
titlestringthe assistant's nameThe header, and the launcher's accessible name.
placeholderstringThe message box's placeholder.
showClosebooleanShow the header's close button.
showVoicebooleantrueShow the microphone and hands-free buttons in the panel, when voice is on.
styleCSSPropertiesMerged over the panel's own styles.

AssistantPanel

The conversation panel on its own, for embedding in your layout, such as a sidebar. It takes title, placeholder, showClose (off by default here), showVoice and style, as AssistantWidget does. See your panel too.

MiheMark

The Mihe logo as a React component, for a launcher of your own.

Hooks

Every hook works anywhere inside the provider, and does nothing outside one, so shared components can call them whether or not a page has the assistant.

useAssistantScreen(screen)

Declares the screen the user is on. Call it once per page or view. See screens and components.

FieldType
screenIdstringRequired. The id your registry knows it by, such as orders.list.
routestringRequired. The path the user is on.
titlestringRequired.
descriptionstringWhat the screen is for.
keywordsstring[]Other words users might use for it.
visibleDataRecord<string, unknown>Summary values on screen, small and scalar: counts, totals, statuses. It's what makes answers concrete. Sent on every screen change, so keep it short.
loadingbooleanTrue until the page's data has arrived. While true, visibleData isn't sent, so the assistant doesn't read placeholder zeros as fact.

useAssistantComponent(componentKey, meta)

Declares something the assistant can talk about or point at, and returns the props that make it findable. Spread them onto a real DOM element; without them it can be described but not highlighted.

const props = useAssistantComponent("orders.newButton", {
  type: "button",
  label: "New order",
  description: "Opens the form to create an order",
});
return <button {...props}>New order</button>;
FieldType
type"button" | "input" | "select" | "table" | "card" | "link" | "modal" | "other"Required.
labelstringRequired.
descriptionstring
actionsstring[]Actions this component relates to.

Returns { "data-mihe-component": string }.

useAssistantAction(action)

Supplies the code for a frontend action the assistant may run in the browser. The action's risk, permissions and confirmation are set in your registry, not here. See actions.

FieldType
namestringRequired. The action's name in your registry.
handler(input: Record<string, unknown>) => unknown | Promise<unknown>Required. Its return value is what the assistant is told, so return something descriptive. Throwing reports a failure honestly.

useAssistantTabs(tabs)

Lets the assistant see which tab is open and switch to another.

FieldType
idstringRequired. Unique on the screen, such as reports.tabs.
labelstringRequired. What the tabs choose between: "Report", "Period".
tabs{ value: string; label: string }[]Required.
valuestring | undefinedRequired. The tab really showing. A switch isn't reported done until this matches.
onChange(value: string) => void | Promise<void>Required. Called only with one of tabs' values.

useAssistantTable(table)

Lets the assistant read a table. Rows aren't sent with the screen: the assistant reads them when a question needs them, and only the columns you declare ever leave the browser.

FieldType
idstringRequired. Unique on the screen, such as orders.table.
labelstringRequired.
columns{ key: string; label: string; value?: (row) => unknown }[]Required. value defaults to row[key]. Long cells are cut at 200 characters.
rowsRow[]Required. The rows loaded now.
rowId(row: Row) => stringRequired.
rowIdNamestringThe action input a row's id fills, such as orderId.
opens{ screenId: string; params: (row) => Record<string, string> }The screen a row opens, and its route params.
totalnumberRows in the whole list, when rows is one page.
queryAssistantTableQuery<Row>Search past the loaded rows with your own API. See below.

query lets the assistant search your data the way your page would:

FieldType
paramsRecord<string, AssistantQueryParam>Required. What the assistant may fill in: { kind: "text" }, { kind: "enum", values: [...] } or { kind: "date" }, each with an optional description. Only these keys, and only an enum's values, ever reach run.
run(params) => Promise<{ rows: Row[]; total?: number }>Required. Your search, with the user's own session.
show(params) => void | Promise<void>Makes the page show this search, by setting its filters. Without it, results are read but not shown.

A search only reads; it changes what's shown, never what's stored.

useAssistantChart(chart)

Lets the assistant explain a chart. Each series is summarised in the browser (start, end, high, low, total and the largest steps), and exact points are read only when asked for. A picture of the chart is never sent.

FieldType
idstringRequired. Unique on the screen.
titlestringRequired.
dataDatum[]Required. The same array your chart library gets.
x{ key; label; kind?: "ordered" | "category"; format?: (value) => string }Required. kind defaults to ordered; rises and falls are worked out only for ordered axes.
series{ key; name: string; unit?: string }[]Required.

useAssistantValues(key, values)

Adds figures a component shows to the screen's visibleData, under key: for values that live below the page that calls useAssistantScreen, like the stat cards inside a tab. They're dropped when the component unmounts.

useAssistantTrigger()

Makes any element open the assistant, with the keyboard and screen-reader props a real button has. Returns null when there's no assistant, so you can render nothing rather than a dead control.

const trigger = useAssistantTrigger();
return trigger ? <div {...trigger}>Ask the assistant</div> : null;

useAssistantPrompt(text)

A one-tap "ask this", for suggestion chips and help links. Returns a click handler that sends text and opens the assistant, or null when there's no assistant.

const ask = useAssistantPrompt("How do I add a product?");
return ask ? <button onClick={ask}>How do I add a product?</button> : null;

useAssistant()

Everything the assistant's own interface uses, for building your own. Throws outside the provider.

FieldType
messagesChatMessage[]The conversation: { id, role: "user" | "assistant", text, streaming?, sources? }. sources lists the documentation an answer drew on.
send(text: string) => voidSend a message.
busybooleanTrue while the assistant is answering.
proposalsProposalPayload[]Approval cards waiting for the user. See below.
respondToProposal(proposalId: string, confirmed: boolean) => voidApprove or decline one.
connection"idle" | "connecting" | "open" | "reconnecting" | "closed"
lastErrorstring | null
isOpen, open, close, toggleWhether the assistant's interface is showing, and control of it.
assistantNamestring | nullThe name set in the dashboard, once connected.
launcherIconUrlstring | nullThe icon uploaded in the dashboard.
widgetSettingsWidgetSettings | nullThe widget's settings from the dashboard.
voiceVoiceControlsSee below.
storeAssistantStoreThe registered screen, components and handlers.

A proposal is everything its card shows, taken from your registry and never from the model: proposalId, actionName, label, description, risk, the input it would run with and its inputSchema, expiresAt, and uiConfirmationRequired, which is true when only a tap may approve it. Always render the card from these fields.

voice controls the voice session:

FieldType
availablebooleanVoice is on for this app.
state"idle" | "connecting" | "listening" | "recording" | "thinking" | "speaking" | "error"
handsFreebooleanTrue for a hands-free session, false for hold to talk.
noticestring | nullSomething worth saying that isn't a failure, such as the session ending soon.
start(options?: { handsFree?: boolean; openPanel?: boolean }) => voidOpens the session and the microphone. Call it from a user gesture: browsers require one for the microphone.
stop() => void
press, release() => voidHold to talk: start and stop recording. press({ hold: true }) waits for confirm() or discard(), for a control a press might turn into a drag.
onLevel(listener: (source: "user" | "assistant", level: number) => void) => () => voidHow loud each side is, 0 to 1, many times a second. Returns the unsubscribe. Move an element directly rather than setting state.
captionstringThe line being spoken, as it streams. The widget doesn't show it; finished lines appear in messages.

Lower level

For an interface further from the widget than useAssistant goes:

Export
AssistantClientThe session WebSocket: connection, reconnects, turns and approvals.
AssistantStoreThe registry of the current screen, components, tables, charts and handlers.
VoiceSessionOne voice session: the voice socket, microphone and speaker.
MicrophoneCapture, SpeakerQueueMicrophone capture at 24 kHz, and gapless playback.
toPcm16, fromPcm16Float samples to 16-bit PCM and back.
HighlightEngineDraws the highlight around a component the assistant points at.
executeCommandRuns one command from the runtime against the page.
formatContextReportFormats what debug logs.

Constants: SDK_VERSION, PROTOCOL_VERSION, VOICE_SAMPLE_RATE (24000), ASSISTANT_PANEL_ID, and COMPONENT_ATTRIBUTE (data-mihe-component).

Types: AssistantProviderProps, AssistantContextValue, ChatMessage, VoiceControls, VoiceState, VoiceEvent, VoiceSessionOptions, AssistantWidgetProps, AssistantPanelProps, OrbCorner, OrbVoiceMode, AssistantTabs, AssistantTable, AssistantTableColumn, AssistantTableQuery, AssistantQueryParam, AssistantChart, AssistantTriggerProps and ContextReport.

On this page