@docyrus/rn-assistant
v0.26.1
Published
Standalone React Native AI assistant package for Docyrus-compatible backends.
Downloads
4,642
Readme
@docyrus/rn-assistant
@docyrus/rn-assistant is a standalone React Native AI assistant package for Docyrus-compatible backends.
It is host-app independent:
- it does not import app-local aliases
- it does not read
.envinternally - it does not require Tailwind, NativeWind, Uniwind, or
className - it supports embedded page, modal, and sheet presentations
What You Get
DocyrusRNAssistantas the main entry componentDocyrusRNAssistantEmbeddedfor page or tab usageDocyrusRNAssistantModalfor full-screen modal usageDocyrusRNAssistantSheetfor bottom-sheet or action-sheet usage- built-in chat UI
- session and message management
- model and reasoning selection
- attachment picker
- voice recording and transcription UI
- internal light/dark aware theme tokens with overrides
- read-optimized send behavior: on submit the keyboard dismisses and the just-sent user message pins to the top of the viewport (matches ChatGPT/Claude mobile), giving the generated reply the full remaining screen
Installation
Install the package:
pnpm add @docyrus/rn-assistantInstall the required peer dependencies in the host app. These are declared as peers so Expo autolinking sees a single copy of each native module in the host's node_modules:
npx expo install expo expo-clipboard expo-image react react-native react-native-keyboard-controller react-native-safe-area-context react-native-svgIf the host app enables optional features, install the corresponding peers on demand:
# enableVoice
npx expo install expo-audio
# enableAttachment
npx expo install expo-document-picker expo-image-pickerCurrent peer requirements (versions pinned to Expo SDK 55):
Always required:
expo55.0.17expo-clipboard55.0.13expo-image55.0.9react19.2.0react-native0.83.6react-native-keyboard-controller1.20.7react-native-safe-area-context5.6.2react-native-svg15.15.3
Optional (only when the matching feature is enabled):
expo-audio55.0.14 (voice)expo-document-picker55.0.13 (attachments)expo-image-picker55.0.19 (attachments)react-native-webview13.16.0 (embedded web content)
Host App Responsibilities
The host app is responsible for:
- providing backend URLs from
.envor any config source - providing a valid user access token when authenticated requests are needed
- providing
agentIdand optionallydataSourceId - deciding whether the assistant renders embedded, modal, or sheet
- storing and refreshing auth or session state
The package is responsible for:
- rendering the assistant UI
- fetching deployments and models
- managing sessions and messages
- chat streaming
- attachment and transcription flows
- filling the full host height in embedded, modal, and sheet modes
Environment Variables
The package does not read env values directly. The host app should read env variables and map them into apiConfig and assistant props.
Suggested Docyrus host env shape:
EXPO_PUBLIC_API_BASE_URL=https://alpha-api.docyrus.com/v1
EXPO_PUBLIC_ASSISTANT_AGENT_ID=your-agent-id
EXPO_PUBLIC_ASSISTANT_DATA_SOURCE_ID=your-thread-data-source-id
EXPO_PUBLIC_OAUTH2_CLIENT_ID=your-oauth-client-id
EXPO_PUBLIC_OAUTH2_SCOPES=openid profile offline_access User.Read Users.Read.All DS.Read.All DS.ReadWrite.All AI.Read.All AI.ReadWrite.All
EXPO_PUBLIC_OAUTH2_CALLBACK_URL=your-app-scheme://auth/callbackRecommended Docyrus scopes:
User.ReadUsers.Read.AllDS.Read.AllDS.ReadWrite.AllAI.Read.AllAI.ReadWrite.All
Minimum deployment-read requirement:
AI.Read.AllorAI.ReadWrite.All
If OAuth scopes change, the user should sign out and sign in again so the host app receives a fresh token.
Native Permissions
If the host app enables voice recording or media attachments, the host app must define the required native permission strings.
For Expo apps, add these keys in app.config.ts or app.json under ios.infoPlist:
ios: {
infoPlist: {
NSMicrophoneUsageDescription: 'Docyrus Assistant uses the microphone for voice prompts and transcription.',
NSCameraUsageDescription: 'Docyrus Assistant uses the camera so you can attach photos to prompts.',
NSPhotoLibraryUsageDescription: 'Docyrus Assistant uses your photo library so you can attach images to prompts.',
NSPhotoLibraryAddUsageDescription: 'Docyrus Assistant saves exported images and files to your photo library when requested.'
}
}Notes:
- these keys belong to the host app, not the package
- after changing native permission keys, rebuild the iOS app with a fresh native build such as
run:ios - microphone permission is requested only when the user starts recording
Quick Start
import {
DocyrusRNAssistant,
createDocyrusRNAssistantConfig
} from '@docyrus/rn-assistant';
const assistantConfig = createDocyrusRNAssistantConfig({
baseUrl: process.env.EXPO_PUBLIC_API_BASE_URL || ''
});
export function AssistantScreen() {
return (
<DocyrusRNAssistant
apiConfig={assistantConfig}
agentId={process.env.EXPO_PUBLIC_ASSISTANT_AGENT_ID || ''}
dataSourceId={process.env.EXPO_PUBLIC_ASSISTANT_DATA_SOURCE_ID}
credentials={{
token: session.accessToken,
userId: session.userId
}}
userId={session.userId}
showHeader
/>
);
}Embedded Usage
Use this when the assistant lives inside a screen, tab, or routed page.
import {
DocyrusRNAssistantEmbedded,
createDocyrusRNAssistantConfig
} from '@docyrus/rn-assistant';
const assistantConfig = createDocyrusRNAssistantConfig({
baseUrl: process.env.EXPO_PUBLIC_API_BASE_URL || ''
});
export function AssistantTab() {
return (
<DocyrusRNAssistantEmbedded
apiConfig={assistantConfig}
agentId={process.env.EXPO_PUBLIC_ASSISTANT_AGENT_ID || ''}
dataSourceId={process.env.EXPO_PUBLIC_ASSISTANT_DATA_SOURCE_ID}
credentials={{
token: session.accessToken,
userId: session.userId
}}
userId={session.userId}
showHeader
/>
);
}Modal Usage
Use this when the assistant opens from a dedicated trigger or overlay flow.
import { useState } from 'react';
import {
DocyrusRNAssistantModal,
createDocyrusRNAssistantConfig
} from '@docyrus/rn-assistant';
const assistantConfig = createDocyrusRNAssistantConfig({
baseUrl: process.env.EXPO_PUBLIC_API_BASE_URL || ''
});
export function AssistantLauncher() {
const [open, setOpen] = useState(false);
return (
<>
<Button title="Open Assistant" onPress={() => setOpen(true)} />
<DocyrusRNAssistantModal
visible={open}
onClose={() => setOpen(false)}
apiConfig={assistantConfig}
agentId={process.env.EXPO_PUBLIC_ASSISTANT_AGENT_ID || ''}
dataSourceId={process.env.EXPO_PUBLIC_ASSISTANT_DATA_SOURCE_ID}
credentials={{
token: session.accessToken,
userId: session.userId
}}
userId={session.userId}
showHeader
modalAnimationType="slide"
/>
</>
);
}Bottom Sheet Usage
Use this when the assistant should open from a bottom menu or action-sheet style trigger.
import { useState } from 'react';
import {
DocyrusRNAssistantSheet,
createDocyrusRNAssistantConfig
} from '@docyrus/rn-assistant';
const assistantConfig = createDocyrusRNAssistantConfig({
baseUrl: process.env.EXPO_PUBLIC_API_BASE_URL || ''
});
export function AssistantBottomSheet() {
const [open, setOpen] = useState(false);
return (
<>
<Button title="Open Assistant Sheet" onPress={() => setOpen(true)} />
<DocyrusRNAssistantSheet
visible={open}
onClose={() => setOpen(false)}
sheetDetent="large"
apiConfig={assistantConfig}
agentId={process.env.EXPO_PUBLIC_ASSISTANT_AGENT_ID || ''}
dataSourceId={process.env.EXPO_PUBLIC_ASSISTANT_DATA_SOURCE_ID}
credentials={{
token: session.accessToken,
userId: session.userId
}}
userId={session.userId}
showHeader
/>
</>
);
}One Component, Multiple Presentation Modes
If you want to switch presentation with a prop:
import { DocyrusRNAssistant } from '@docyrus/rn-assistant';
<DocyrusRNAssistant
presentation="embedded"
apiConfig={assistantConfig}
agentId={agentId}
dataSourceId={dataSourceId}
credentials={{ token, userId }}
/>;import { DocyrusRNAssistant } from '@docyrus/rn-assistant';
<DocyrusRNAssistant
presentation="modal"
visible={isOpen}
onClose={() => setIsOpen(false)}
modalAnimationType="slide"
apiConfig={assistantConfig}
agentId={agentId}
dataSourceId={dataSourceId}
credentials={{ token, userId }}
/>;import { DocyrusRNAssistant } from '@docyrus/rn-assistant';
<DocyrusRNAssistant
presentation="sheet"
visible={isOpen}
onClose={() => setIsOpen(false)}
sheetDetent="large"
apiConfig={assistantConfig}
agentId={agentId}
dataSourceId={dataSourceId}
credentials={{ token, userId }}
/>;Authentication Model
The assistant package does not implement the host app login screen. Recommended flow:
- Host app signs the user in.
- Host app receives
accessTokenanduserId. - Host app passes them to the assistant through
credentialsanduserId.
Example:
<DocyrusRNAssistantEmbedded
apiConfig={assistantConfig}
agentId={agentId}
dataSourceId={dataSourceId}
credentials={{
token: session.accessToken,
userId: session.userId
}}
userId={session.userId}
/>If you do not pass a valid token:
- UI may still render
- authenticated chat and session requests may fail
- deployment loading may fail if the token does not include required AI scopes
API Config Helper
The default helper is for the Docyrus backend contract:
import { createDocyrusRNAssistantConfig } from '@docyrus/rn-assistant';
const assistantConfig = createDocyrusRNAssistantConfig({
baseUrl: 'https://alpha-api.docyrus.com/v1',
token: accessToken
});It prepares:
- Docyrus endpoint paths
- Docyrus response unwrapping with
transformResponse - optional
Authorizationheader iftokenis provided
Default endpoints included by the helper:
- deployment:
/ai/agent-deployments/base/:agentId - chat:
/ai/agents/:agentId/chat - sessions:
/apps/base/data-sources/thread/items - messages:
/apps/base/data-sources/message/items - create thread:
/apps/base/data-sources/thread/items - delete session:
/apps/base/data-sources/thread/items/:sessionId - transcribe:
/ai/transcribe
Custom Backend Config
If another app uses the same UI package with different endpoints, pass a custom apiConfig object:
import { type AIAPIConfig } from '@docyrus/rn-assistant';
const assistantConfig: AIAPIConfig = {
baseUrl: 'https://my-api.example.com',
transformResponse: (response) => response.result,
endpoints: {
deployment: '/assistant/deployments/:agentId',
chat: '/assistant/chat/:agentId',
sessions: '/assistant/sessions',
messages: '/assistant/messages',
createThread: '/assistant/sessions',
deleteSession: '/assistant/sessions/:sessionId',
transcribe: '/assistant/transcribe'
},
headers: {
Authorization: `Bearer ${accessToken}`,
'x-app-name': 'my-rn-app'
}
};Main Props
Required:
apiConfigagentId
Usually required in real usage:
dataSourceIdcredentials.tokencredentials.userIduserId
Common optional props:
deploymentIdheadersinitialModeonErrorshowHeaderonCloseenableVoiceenableAttachmentallowedAttachmentTypesmaxAttachmentSizemaxAttachmentsshowModelSelectorInInputthemepresentationvisiblemodalAnimationTypesheetDetentcontainerStyle
Theming
The package includes its own theme layer. Override only the values you need:
<DocyrusRNAssistant
apiConfig={assistantConfig}
agentId={agentId}
credentials={{ token, userId }}
theme={{
colors: {
primary: '#0f766e',
primaryForeground: '#ffffff',
background: '#f8fafc'
}
}}
/>The default theme follows device light and dark appearance automatically.
Public Exports
Components:
DocyrusRNAssistantDocyrusRNAssistantEmbeddedDocyrusRNAssistantModalDocyrusRNAssistantSheetDocyrusRNAssistantProvider
Config and types:
createDocyrusRNAssistantConfigcreateDocyrusAPIConfigAIAPIConfig
Hooks:
useAssistantuseAgentModelsuseVoiceRecorderuseAttachmentPicker
Compatibility aliases:
DocyAssistantDocyAssistantProps
