VoiceAssist Docs

Shared Packages

Documentation for the shared packages used across the VoiceAssist frontend apps.

draft2025-12-05

@voiceassist/api-client

Type-safe HTTP client for VoiceAssist backend services.

Installation

pnpm add @voiceassist/api-client

Features

  • Type-safe API calls with TypeScript
  • Automatic retry with exponential backoff
  • JWT authentication with automatic token refresh
  • Distributed tracing with correlation IDs
  • Configurable timeout and error handling

Usage

import { VoiceAssistApiClient } from "@voiceassist/api-client"; const client = new VoiceAssistApiClient({ baseURL: "https://assist.asimo.io/api", timeout: 30000, getAccessToken: () => localStorage.getItem("accessToken"), onUnauthorized: () => { // Handle token expiry window.location.href = "/login"; }, enableRetry: true, retryConfig: { maxRetries: 3, baseDelay: 1000, }, });

API Methods

Authentication

// Login const tokens = await client.login({ email, password }); // Register const user = await client.register({ email, password, full_name }); // Logout await client.logout(); // Refresh token const newTokens = await client.refreshToken(refreshToken); // Get current user const user = await client.getCurrentUser();

Conversations

// List conversations const conversations = await client.getConversations(page, pageSize); // Create conversation const conversation = await client.createConversation("My Conversation"); // Get conversation const conversation = await client.getConversation(id); // Update conversation const updated = await client.updateConversation(id, { title: "New Title" }); // Delete conversation await client.deleteConversation(id);

Messages

// Get messages const messages = await client.getMessages(conversationId, page, pageSize); // Send message const message = await client.sendMessage(conversationId, "Hello"); // Send idempotent message (safe to retry) const message = await client.sendIdempotentMessage(conversationId, clientMessageId, "Hello");

Voice

// Transcribe audio const text = await client.transcribeAudio(audioBlob); // Text-to-speech const audioBlob = await client.synthesizeSpeech(text, voiceId); // Create realtime voice session const session = await client.createRealtimeSession({ conversation_id: conversationId, voice: "alloy", language: "en", });

Knowledge Base

// Search const results = await client.searchKnowledgeBase(query, limit); // List documents const docs = await client.getDocuments(page, pageSize); // Upload document const doc = await client.uploadDocument(file, category);

Admin

// System metrics const metrics = await client.getSystemMetrics(); // Audit logs const logs = await client.getAuditLogs(page, pageSize); // Feature flags const flags = await client.getFeatureFlags(); await client.toggleFeatureFlag(flagName); // Cache management const stats = await client.getCacheStats(); await client.clearCache();

Retry Configuration

The client includes built-in retry logic with exponential backoff:

import { withRetry, createRetryWrapper } from "@voiceassist/api-client"; // Manual retry const result = await withRetry( () => fetchData(), { maxRetries: 3, baseDelay: 1000 }, (attempt, error) => console.log(`Retry ${attempt}`, error), ); // Create reusable wrapper const fetchWithRetry = createRetryWrapper(fetchData, { maxRetries: 3 });

Development

# Build pnpm build # Watch mode pnpm dev # Type check pnpm type-check

Dependencies

  • axios - HTTP client
  • @voiceassist/types - Shared type definitions

@voiceassist/config

Shared configuration files for VoiceAssist applications.

Installation

pnpm add @voiceassist/config

Contents

This package provides shared configuration for:

  • ESLint - Code linting rules
  • Tailwind CSS - Styling configuration with design tokens
  • TypeScript - Compiler configurations
  • i18n - Internationalization settings

Usage

ESLint

Extend the shared ESLint configuration in your .eslintrc.js:

module.exports = { extends: ["@voiceassist/config/eslint"], // Add project-specific overrides };

Tailwind CSS

Use the shared Tailwind configuration in your tailwind.config.js:

const sharedConfig = require("@voiceassist/config/tailwind"); /** @type {import('tailwindcss').Config} */ module.exports = { presets: [sharedConfig], content: ["./src/**/*.{js,ts,jsx,tsx}", "../../packages/ui/src/**/*.{js,ts,jsx,tsx}"], // Project-specific customizations };

The Tailwind config includes:

  • Color system from @voiceassist/design-tokens
  • Typography scale
  • Spacing system
  • Border radius tokens
  • Shadow system
  • Dark mode support via class strategy

TypeScript

Extend one of the base TypeScript configurations:

Base configuration (tsconfig.base.json):

{ "extends": "@voiceassist/config/tsconfig.base.json", "compilerOptions": { "outDir": "./dist" }, "include": ["src"] }

React configuration (tsconfig.react.json):

{ "extends": "@voiceassist/config/tsconfig.react.json", "compilerOptions": { "outDir": "./dist" }, "include": ["src"] }

i18n

Use the shared i18n configuration:

import { i18nConfig } from "@voiceassist/config/i18n"; // Configure your i18n library with these settings

Configuration Details

Tailwind CSS Tokens

The Tailwind configuration integrates with design tokens:

// Available color scales colors: { primary, // Blue palette secondary, // Purple palette neutral, // Gray palette success, // Green palette error, // Red palette warning, // Yellow palette info, // Cyan palette } // Semantic colors background: { primary, secondary, tertiary, elevated, inverse } text: { primary, secondary, tertiary, disabled, inverse, link } border: { default, subtle, strong, focus }

Dark Mode

Dark mode is configured using the class strategy:

darkMode: ["class", '[data-theme="dark"]'];

Use with ThemeProvider from @voiceassist/ui.

Dependencies

  • @voiceassist/design-tokens - Design token definitions

@voiceassist/design-tokens

Design tokens package for VoiceAssist applications. Provides a centralized, type-safe design system with colors, typography, spacing, and other visual primitives.

Installation

This package is part of the VoiceAssist monorepo and is automatically available to all apps via pnpm workspaces.

# In any app or package pnpm add @voiceassist/design-tokens

Usage

Colors

import { colors } from "@voiceassist/design-tokens"; // Primary brand color const primary = colors.primary[500]; // #0080FF // Semantic colors const success = colors.success[500]; // #00C369 const error = colors.error[500]; // #FF0000 // Background colors const bg = colors.background.primary; // #FFFFFF

Typography

import { typography } from "@voiceassist/design-tokens"; // Font families const sansFont = typography.fontFamily.sans; const monoFont = typography.fontFamily.mono; // Font sizes const bodySize = typography.fontSize.base; // 1rem (16px) const headingSize = typography.fontSize["3xl"]; // 1.875rem (30px) // Font weights const bold = typography.fontWeight.bold; // 700

Spacing

import { spacing, borderRadius, shadows, zIndex } from "@voiceassist/design-tokens"; // Spacing (4px/8px grid) const sm = spacing[2]; // 0.5rem (8px) const md = spacing[4]; // 1rem (16px) const lg = spacing[8]; // 2rem (32px) // Border radius const rounded = borderRadius.md; // 0.375rem (6px) // Shadows const cardShadow = shadows.md; // Z-index const modalZ = zIndex.modal; // 1400

Design Principles

Color Palette

  • Medical Blue (#0080FF): Primary brand color, evokes trust and professionalism
  • Medical Teal (#00AFAF): Secondary color, provides visual interest
  • Professional Grays: Neutral tones for text and backgrounds
  • Semantic Colors: Success (green), error (red), warning (amber), info (blue)

Typography

  • System Fonts: Native fonts for optimal performance and familiarity
  • Rem Units: All font sizes use rem for accessibility
  • Clear Hierarchy: 10 predefined sizes from xs (12px) to 7xl (72px)

Spacing

  • 4px/8px Grid: All spacing follows a consistent grid
  • Rem Units: Ensures accessibility with user font-size preferences
  • Generous Scale: Ranges from 2px (0.5) to 384px (96)

Tailwind Integration

These tokens are designed to integrate seamlessly with Tailwind CSS. See the @voiceassist/config package for the Tailwind configuration.

Themed usage

Use the designSystem export for a WCAG-conscious bundle of light/dark palettes, elevation, focus, and spacing tokens:

import { designSystem } from "@voiceassist/design-tokens"; const cardBackground = designSystem.light.colors.surface.card; // WCAG AA on text.primary const focusRing = designSystem.light.focus.strong; // 3px blue outline const darkShadow = designSystem.dark.elevation.lg;

All text/background pairs in the palette have been verified for WCAG 2.1 AA contrast, and focus ring tokens are 3px/2px outlines for keyboard visibility.

TypeScript Support

All tokens are fully typed with TypeScript for autocomplete and type safety:

import type { ColorCategory, FontSize, SpacingToken } from "@voiceassist/design-tokens"; const category: ColorCategory = "primary"; const size: FontSize = "lg";

Module Exports

The package provides individual module exports for tree-shaking:

// Import everything import { colors, typography, spacing } from "@voiceassist/design-tokens"; // Or import specific modules import { lightColors, darkColors } from "@voiceassist/design-tokens/colors"; import { typography } from "@voiceassist/design-tokens/typography"; import { spacing } from "@voiceassist/design-tokens/spacing"; import { animations, transitions } from "@voiceassist/design-tokens/animations"; import { breakpoints, mediaQueries } from "@voiceassist/design-tokens/breakpoints"; import { shadows, zIndex } from "@voiceassist/design-tokens/elevation";

Development

# Build pnpm build # Watch mode pnpm dev # Type check pnpm type-check

Contributing

When adding new tokens:

  1. Follow the existing naming conventions
  2. Maintain the 4px/8px grid for spacing
  3. Update TypeScript types
  4. Document new tokens in this README
  5. Rebuild the package: pnpm build

@voiceassist/telemetry

Shared telemetry utilities for VoiceAssist applications. Provides unified error tracking, performance monitoring, and logging.

Installation

pnpm add @voiceassist/telemetry

Features

  • Sentry integration for error tracking
  • Web Vitals monitoring (CLS, FCP, FID, INP, LCP, TTFB)
  • Grafana Loki integration for log aggregation
  • Unified telemetry client interface

Usage

Basic Setup

import { createTelemetryClient } from "@voiceassist/telemetry"; const telemetry = createTelemetryClient({ sentryDsn: process.env.SENTRY_DSN, grafanaUrl: process.env.GRAFANA_LOKI_URL, grafanaToken: process.env.GRAFANA_TOKEN, release: "1.0.0", environment: "production", app: "web-app", context: { userId: currentUser?.id, }, });

Error Tracking

// Capture errors try { await riskyOperation(); } catch (error) { telemetry.captureError(error, { component: "ChatPanel", action: "sendMessage", }); } // Capture messages telemetry.captureMessage("User completed onboarding", "info");

Web Vitals

// Initialize web vitals tracking // Call this once in your app entry point telemetry.trackWebVitals();

This automatically tracks:

MetricDescription
CLSCumulative Layout Shift
FCPFirst Contentful Paint
FIDFirst Input Delay
INPInteraction to Next Paint
LCPLargest Contentful Paint
TTFBTime to First Byte

Flushing Before Page Unload

// Ensure all events are sent before page unload window.addEventListener("beforeunload", async () => { await telemetry.flush(); });

Configuration Options

interface TelemetryOptions { // Sentry DSN for error tracking sentryDsn?: string; // Grafana Loki URL for log aggregation grafanaUrl?: string; // Auth token for Grafana grafanaToken?: string; // Release version release?: string; // Environment (production, staging, development) environment?: string; // Application name app?: string; // Additional context for all events context?: Record<string, unknown>; }

API Reference

TelemetryClient

interface TelemetryClient { // Capture an error with optional context captureError: (error: unknown, context?: Record<string, unknown>) => void; // Capture a message with severity level captureMessage: (message: string, level?: SeverityLevel) => void; // Start tracking Web Vitals trackWebVitals: () => void; // Flush pending events (returns true if successful) flush: () => Promise<boolean>; }

Severity Levels

  • fatal - Application crash
  • error - Error conditions
  • warning - Warning conditions
  • info - Informational messages
  • debug - Debug information

Integration with React

// App.tsx import { createTelemetryClient } from '@voiceassist/telemetry'; import { useEffect } from 'react'; const telemetry = createTelemetryClient({ sentryDsn: import.meta.env.VITE_SENTRY_DSN, environment: import.meta.env.MODE, app: 'web-app', }); function App() { useEffect(() => { telemetry.trackWebVitals(); }, []); return <YourApp />; }

Dependencies

  • @sentry/browser - Error tracking
  • web-vitals - Core Web Vitals measurement

Development

# Build pnpm build # Watch mode pnpm dev

@voiceassist/types

Shared TypeScript type definitions for VoiceAssist applications.

Installation

pnpm add @voiceassist/types

Overview

This package provides centralized type definitions used across all VoiceAssist frontend applications and the API client. It ensures type consistency between the web app, admin panel, and documentation site.

Type Categories

User & Authentication

import type { User, UserRole, AuthTokens, LoginRequest, LoginResponse, TokenResponse } from "@voiceassist/types"; // User roles type UserRole = "admin" | "physician" | "staff" | "patient";

Chat & Conversations

import type { Message, Conversation, Citation, Branch, CreateBranchRequest } from "@voiceassist/types"; // Message with optional citations and attachments interface Message { id: string; conversationId?: string; role: "user" | "assistant" | "system"; content: string; citations?: Citation[]; attachments?: string[]; timestamp: number; parentId?: string; // For branching branchId?: string; }

Clinical Context (HIPAA-compliant)

import type { ClinicalContext, ClinicalContextCreate, ClinicalContextUpdate, Vitals } from "@voiceassist/types"; interface Vitals { temperature?: number; // Celsius heartRate?: number; // BPM bloodPressure?: string; // "120/80" respiratoryRate?: number; spo2?: number; // Percentage }

Knowledge Base

import type { Document, DocumentStatus, SearchResult, KnowledgeBaseEntry } from "@voiceassist/types"; type DocumentStatus = "pending" | "processing" | "indexed" | "failed";

Folders & Organization

import type { Folder, CreateFolderRequest, UpdateFolderRequest } from "@voiceassist/types";

Sharing

import type { ShareRequest, ShareResponse, ShareLink } from "@voiceassist/types";

Attachments

import type { Attachment, AttachmentUploadResponse, UploadProgress } from "@voiceassist/types";

Voice

import type { VoiceConfig, TranscriptionResult } from "@voiceassist/types";

WebSocket Events

import type { WebSocketEvent, WebSocketEventType, WebSocketError, WebSocketErrorCode, ConnectionStatus, ChatStreamChunk, } from "@voiceassist/types"; type WebSocketEventType = | "delta" | "chunk" | "message.done" | "user_message.created" | "history" | "connected" | "error" | "ping" | "pong"; type ConnectionStatus = "connecting" | "connected" | "reconnecting" | "disconnected" | "failed";

API Responses

import type { ApiResponse, ApiError, ApiMeta, PaginatedResponse } from "@voiceassist/types"; // Standard API envelope interface ApiResponse<T = unknown> { success: boolean; data?: T; error?: ApiError; meta?: ApiMeta; }

Admin Types

import type { SystemMetrics, AuditLogEntry } from "@voiceassist/types";

Utility Types

import type { Nullable, Optional, DeepPartial } from "@voiceassist/types"; // Helper types type Nullable<T> = T | null; type Optional<T> = T | undefined; type DeepPartial<T> = { [P in keyof T]?: DeepPartial<T[P]> };

Usage Example

import type { User, Conversation, Message } from "@voiceassist/types"; function displayConversation(conversation: Conversation, messages: Message[]) { console.log(`Conversation: ${conversation.title}`); messages.forEach((msg) => { console.log(`[${msg.role}]: ${msg.content}`); }); } async function getCurrentUser(): Promise<User> { const response = await fetch("/api/users/me"); return response.json(); }

Development

# Build pnpm build # Watch mode pnpm dev # Type check pnpm type-check

@voiceassist/ui

Shared React component library for VoiceAssist applications. Built with Radix UI primitives and Tailwind CSS.

Installation

pnpm add @voiceassist/ui

Peer Dependencies

pnpm add react react-dom react-i18next

Features

  • Accessible components built on Radix UI
  • Consistent styling with Tailwind CSS
  • Dark mode support via ThemeProvider
  • Medical-specific components (HIPAA-compliant)
  • Storybook documentation
  • Comprehensive test coverage

Components

Core Components

import { Button, Input, Label, Card, Badge, Avatar, Spinner, Skeleton, IconButton } from "@voiceassist/ui";

Layout Components

import { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent } from "@voiceassist/ui";

Form Components

import { Input, Label, Select, SelectTrigger, SelectContent, SelectItem } from "@voiceassist/ui";

Overlay Components

import { Dialog, DialogTrigger, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, } from "@voiceassist/ui";

Data Display

import { Table, TableHeader, TableBody, TableRow, TableHead, TableCell, Badge, Avatar, AvatarGroup, } from "@voiceassist/ui";

Feedback Components

import { FeedbackRating, FeedbackForm, Spinner, SpinnerOverlay, Skeleton } from "@voiceassist/ui";

Medical Components

import { VitalSignCard, MedicationList, MedicationItem, AlertBanner } from "@voiceassist/ui";

Providers

import { ThemeProvider, useTheme } from "@voiceassist/ui";

Usage Examples

Button

import { Button } from '@voiceassist/ui'; <Button variant="default" size="md"> Click me </Button> <Button variant="destructive" size="sm"> Delete </Button> <Button variant="outline" disabled> Disabled </Button>

Card

import { Card, CardHeader, CardTitle, CardContent } from "@voiceassist/ui"; <Card> <CardHeader> <CardTitle>Patient Summary</CardTitle> </CardHeader> <CardContent> <p>Content goes here</p> </CardContent> </Card>;

Dialog

import { Dialog, DialogTrigger, DialogContent, DialogHeader, DialogTitle, Button } from "@voiceassist/ui"; <Dialog> <DialogTrigger asChild> <Button>Open Dialog</Button> </DialogTrigger> <DialogContent> <DialogHeader> <DialogTitle>Confirm Action</DialogTitle> </DialogHeader> <p>Are you sure you want to proceed?</p> </DialogContent> </Dialog>;

ThemeProvider

import { ThemeProvider, useTheme } from "@voiceassist/ui"; function App() { return ( <ThemeProvider defaultTheme="system"> <YourApp /> </ThemeProvider> ); } function ThemeToggle() { const { theme, setTheme } = useTheme(); return <button onClick={() => setTheme(theme === "dark" ? "light" : "dark")}>Toggle Theme</button>; }

Medical Components

import { VitalSignCard, AlertBanner } from '@voiceassist/ui'; <VitalSignCard label="Heart Rate" value={72} unit="bpm" status="normal" /> <AlertBanner severity="warning" title="Drug Interaction" message="Potential interaction between medications" actions={[ { label: 'Review', onClick: () => {} } ]} />

Utilities

cn() - Class Name Utility

import { cn } from "@voiceassist/ui"; // Merge Tailwind classes with conflict resolution const className = cn("px-4 py-2", isActive && "bg-primary text-white", className);

Development

# Build pnpm build # Watch mode pnpm dev # Type check pnpm type-check # Run tests pnpm test # Run tests in watch mode pnpm test:watch # Run Storybook pnpm storybook # Build Storybook pnpm build-storybook

Storybook

View component documentation and interactive examples:

pnpm storybook

Opens at http://localhost:6006

Testing

Components include comprehensive tests using Vitest and Testing Library:

# Run all tests pnpm test # Run with coverage pnpm test:coverage # Interactive UI pnpm test:ui

Dependencies

  • @radix-ui/* - Accessible UI primitives
  • @voiceassist/design-tokens - Design tokens
  • class-variance-authority - Variant management
  • clsx + tailwind-merge - Class name utilities

@voiceassist/utils

Shared utility functions for VoiceAssist applications.

Installation

pnpm add @voiceassist/utils

Features

  • String manipulation utilities
  • Date/time formatting
  • Array helpers
  • Object utilities
  • Validation functions
  • PHI detection for HIPAA compliance
  • Debounce and throttle

Utilities

String Utilities

import { capitalize, truncate, kebabCase, camelCase } from "@voiceassist/utils"; capitalize("hello"); // 'Hello' truncate("Long text here", 8); // 'Long ...' kebabCase("myVariable"); // 'my-variable' camelCase("my-variable"); // 'myVariable'

Date/Time Utilities

import { formatDate, relativeTime } from "@voiceassist/utils"; formatDate(new Date(), "short"); // '11/27/2025' formatDate(new Date(), "long"); // 'November 27, 2025, 10:30 AM' relativeTime(new Date(Date.now() - 3600000)); // '1 hour ago' relativeTime(new Date(Date.now() - 120000)); // '2 minutes ago'

Array Utilities

import { chunk, unique, shuffle } from "@voiceassist/utils"; chunk([1, 2, 3, 4, 5], 2); // [[1, 2], [3, 4], [5]] unique([1, 2, 2, 3, 3, 3]); // [1, 2, 3] shuffle([1, 2, 3, 4, 5]); // Random order

Object Utilities

import { deepClone, pick, omit } from "@voiceassist/utils"; const obj = { a: 1, b: 2, c: 3 }; deepClone(obj); // New object with same values pick(obj, ["a", "b"]); // { a: 1, b: 2 } omit(obj, ["c"]); // { a: 1, b: 2 }

Validation Utilities

import { isValidEmail, isValidUrl, isEmpty } from "@voiceassist/utils"; isValidEmail("user@example.com"); // true isValidUrl("https://asimo.io"); // true isEmpty(null); // true isEmpty(""); // true isEmpty([]); // true isEmpty({}); // true isEmpty("hello"); // false

Formatting Utilities

import { formatBytes, formatNumber } from "@voiceassist/utils"; formatBytes(1024); // '1 KB' formatBytes(1048576); // '1 MB' formatBytes(1073741824); // '1 GB' formatNumber(1234567); // '1,234,567'

Debounce & Throttle

import { debounce, throttle } from "@voiceassist/utils"; // Debounce - wait 300ms after last call const debouncedSearch = debounce((query: string) => { fetchResults(query); }, 300); // Throttle - max once per 100ms const throttledScroll = throttle(() => { updateScrollPosition(); }, 100);

PHI Detection (HIPAA Compliance)

import { containsPHI, redactPHI } from "@voiceassist/utils"; // Check if text contains potential PHI containsPHI("SSN: 123-45-6789"); // true containsPHI("Hello world"); // false // Redact PHI from text redactPHI("Call me at 555-123-4567"); // 'Call me at [REDACTED_PHONE]' redactPHI("SSN: 123-45-6789, DOB: 01/15/1990"); // 'SSN: [REDACTED_SSN], DOB: [REDACTED_DOB]'

Detected PHI patterns:

  • Social Security Numbers (SSN)
  • Phone numbers
  • Email addresses
  • Medical Record Numbers (MRN)
  • Dates of birth (DOB)

API Reference

String Functions

FunctionDescription
capitalize(str)Capitalize first letter
truncate(str, maxLength)Truncate with ellipsis
kebabCase(str)Convert to kebab-case
camelCase(str)Convert to camelCase

Date Functions

FunctionDescription
formatDate(date, format)Format date ('short' or 'long')
relativeTime(date)Relative time string

Array Functions

FunctionDescription
chunk(array, size)Split into chunks
unique(array)Remove duplicates
shuffle(array)Random shuffle

Object Functions

FunctionDescription
deepClone(obj)Deep clone object
pick(obj, keys)Pick specific keys
omit(obj, keys)Omit specific keys

Validation Functions

FunctionDescription
isValidEmail(email)Validate email format
isValidUrl(url)Validate URL format
isEmpty(value)Check if empty

Formatting Functions

FunctionDescription
formatBytes(bytes)Human-readable file size
formatNumber(num)Number with separators

Rate Limiting

FunctionDescription
debounce(fn, wait)Debounce function calls
throttle(fn, limit)Throttle function calls

PHI Functions

FunctionDescription
containsPHI(text)Check for PHI
redactPHI(text)Redact PHI from text

Development

# Build pnpm build # Watch mode pnpm dev # Type check pnpm type-check # Run tests pnpm test