npm package: @onlive.ai/common-121
Description: > Shared foundation package for the Onlive 121 ecosystem — services, utilities, UI components, and themes for building interactive chat, flow, and video meeting applications.
Latest version: 0.2.196

# @onlive.ai/common-121

> Shared foundation package for the Onlive 121 ecosystem — services, utilities, UI components, and themes for building interactive chat, flow, and video meeting applications.

[![npm version](https://img.shields.io/npm/v/@onlive.ai/flow-client)](https://www.npmjs.com/package/@onlive.ai/flow-client)
[![TypeScript](https://img.shields.io/badge/TypeScript-5.7-blue?logo=typescript)](https://www.typescriptlang.org/)
[![Lit](https://img.shields.io/badge/Lit-3.x-purple?logo=lit)](https://lit.dev/)
[![React](https://img.shields.io/badge/React-19.x-61DAFB?logo=react)](https://react.dev/)

## Installation

```bash
npm install @onlive.ai/common-121
# or
pnpm add @onlive.ai/common-121
```

**Prerequisites**: Node.js 18+, TypeScript 5.7+

---

## Package Structure

```
common-121/
├── services/        # Core application services
├── utils/           # Framework-agnostic utility functions
├── components/      # Lit web components (OSBAsset, OSBSideBar, OSBUpload)
├── react/           # React wrapper components
├── themes/          # CSS themes (light, dark, brand-specific)
└── types/           # Shared TypeScript type definitions
```

---

## Services

### AudioService

Singleton service for managing audio notifications during calls and interactions. Preloads sounds on initialization.

```typescript
import { AudioService } from "@onlive.ai/common-121/services/audio.service.js";

const audio = AudioService.getInstance();

audio.playRinging();      // Play ringing tone (looped by default)
audio.playIncoming();     // Play incoming call tone (looped by default)
audio.playSound("ringing", false);  // Play a named sound, no loop
audio.stopCurrentSound(); // Stop whatever is currently playing
```

### FirebaseApi

Low-level wrapper around the Firebase Realtime Database SDK. Provides a typed interface for reading, writing, and subscribing to database nodes.

```typescript
import { FirebaseApi, type FirebaseConfig } from "@onlive.ai/common-121/services/firebase/firebase-api.js";

const config: FirebaseConfig = {
  apiKey: "...",
  authDomain: "...",
  databaseURL: "...",
  projectId: "...",
  storageBucket: "...",
  messagingSenderId: "...",
  appId: "...",
};

const firebase = new FirebaseApi({ config });

// Get a reference and read data
const snapshot = await firebase.get(firebase.ref("rooms/room-id"));

// Subscribe to child additions
firebase.onChildAdded(firebase.ref("requests"), (key, data, snap) => {
  console.log("New request:", key, data);
});
```

### ConversationService

Manages the full lifecycle of a LiveKit-powered conversation room, including connection, messaging, typing indicators, media tracks, and agent interactions.

```typescript
import { ConversationServiceFactory } from "@onlive.ai/common-121/services/conversation/index.js";

const service = ConversationServiceFactory.create(options);

// Connect and join a room
await service.quickStart({ installationId: "...", language: "en" });

// Send a message
service.sendMessage("Hello!");

// Listen for incoming messages
service.onMessage((message) => {
  console.log("Received:", message);
});
```

### SessionService

Manages persistent chat sessions via cookies, with support for role-based sessions (agent vs. guest).

```typescript
import { SessionService } from "@onlive.ai/common-121/services/session.service.js";

if (!SessionService.hasSession()) {
  const session = SessionService.getSession({ role: "guest" });
  console.log("Session created:", session.externalId);
}
```

### DeepLinkService

Parses and manages Onlive-specific deep link parameters (`ol*` prefix) from the current page URL.

```typescript
import { DeepLinkService } from "@onlive.ai/common-121/services/deep-link.service.js";

const deepLink = new DeepLinkService();

if (deepLink.has("action")) {
  const action = deepLink.get("action");
  deepLink.clean(); // Remove ol* params from the URL
}
```

---

## Utilities

All utilities are tree-shakeable and framework-agnostic unless noted.

| Utility | Description |
|---|---|
| `adopt-styles` | Adopts CSS `CSSStyleSheet` into a shadow root |
| `apply-optional-styles` | Conditionally applies styles based on a predicate |
| `browser-preferences` | Detects browser preferences (reduced motion, color scheme) |
| `classify-media` | Classifies a URL or MIME type into a media category |
| `decorators` | Lit element decorators and helpers |
| `detected-lang` | Detects the user's preferred language from browser/DOM signals |
| `fullscreen` | Fullscreen API helpers with cross-browser support |
| `insert-script` | Dynamically inserts a `<script>` tag with dedup protection |
| `is-map-compatible` | Checks if a value is safe to use as a `Map` key |
| `markdown` | Parses Markdown to sanitized HTML, safe for Lit `unsafeHTML` |
| `merge` | Deep merges objects recursively (objects merged, arrays overwritten) |
| `multiband-track-volume` | Analyzes audio track volume across frequency bands |
| `onlive-url-params` | Reads and writes Onlive-specific URL query parameters |
| `pretty-distance` | Formats a geographic distance into a human-readable string |
| `pretty-time` | Formats a duration (seconds) into `mm:ss` or `hh:mm:ss` |
| `random-string` | Generates a cryptographically-random alphanumeric string |
| `resource-type` | Determines the resource type of a URL (image, video, document…) |
| `round-number` | Rounds a number to a given number of decimal places |
| `safe-html` | Tags template literal for safe HTML rendering in Lit |
| `sanitize` | Sanitizes an HTML string with DOMPurify |
| `spread` | Spreads an object as Lit element attributes/properties |
| `watch` | Observes reactive property changes in Lit elements |

### Usage examples

```typescript
import { markdown } from "@onlive.ai/common-121/utils/markdown.js";
import { merge } from "@onlive.ai/common-121/utils/merge.js";
import { sanitize } from "@onlive.ai/common-121/utils/sanitize.js";
import { randomString } from "@onlive.ai/common-121/utils/random-string.js";

// Parse Markdown safely (returns a Lit TemplateResult)
const content = markdown("# Hello **World**");

// Deep merge configuration objects
const config = merge(defaults, userConfig);

// Sanitize arbitrary HTML input
const clean = sanitize(userProvidedHtml);

// Generate a random ID
const id = randomString(16);
```

---

## Components

### Lit Web Components

```typescript
import { OSBAsset } from "@onlive.ai/common-121/components/asset/asset.js";
import { OSBSideBar } from "@onlive.ai/common-121/components/side-bar/side-bar.js";
import { OSBUpload } from "@onlive.ai/common-121/components/upload/upload.js";
```

Or import everything from the package root:

```typescript
import { OSBAsset, OSBSideBar, OSBUpload } from "@onlive.ai/common-121";
```

### React Components

React wrappers are provided for all Lit components via `@lit/react`:

```typescript
import { Asset } from "@onlive.ai/common-121/react/components/asset/Asset.js";
import { SideBar } from "@onlive.ai/common-121/react/components/side-bar/SideBar.js";
import { Upload } from "@onlive.ai/common-121/react/components/upload/Upload.js";

// Use as standard React components
function MyApp() {
  return <Asset src="https://cdn.example.com/image.jpg" />;
}
```

---

## Themes

Themes are CSS files applied directly to Lit components via `adoptedStyleSheets` or `<link>` tags. Two base themes and fourteen brand themes are included.

### Base themes

```typescript
import lightTheme from "@onlive.ai/common-121/themes/light.css" assert { type: "css" };
import darkTheme from "@onlive.ai/common-121/themes/dark.css" assert { type: "css" };

document.adoptedStyleSheets = [lightTheme];
```

### Brand themes

| Theme file | Brand |
|---|---|
| `themes/custom/onlive.theme.css` | Onlive (default brand) |
| `themes/custom/onlive-ai.theme.css` | Onlive AI |
| `themes/custom/audi.theme.css` | Audi |
| `themes/custom/audi-dark.theme.css` | Audi (dark variant) |
| `themes/custom/cupra.theme.css` | Cupra |
| `themes/custom/cupra-diagonal.theme.css` | Cupra Diagonal |
| `themes/custom/cupra-events.theme.css` | Cupra Events |
| `themes/custom/seat-cupra.theme.css` | SEAT/Cupra |
| `themes/custom/hyundai.theme.css` | Hyundai |
| `themes/custom/magimix.theme.css` | Magimix |
| `themes/custom/australia.theme.css` | Australia market |
| `themes/custom/cuernavaca.theme.css` | Cuernavaca market |
| `themes/custom/germany.theme.css` | Germany market |
| `themes/custom/italy.theme.css` | Italy market |

---

## Types

```typescript
import type { TrackingOptions } from "@onlive.ai/common-121/types/tracking-options.js";
import type { DeepLinkParams } from "@onlive.ai/common-121/types/deep-link.types.js";
```

**`TrackingOptions<T>`** — Configuration for the analytics tracking layer:

| Property | Type | Description |
|---|---|---|
| `enabled` | `boolean` | Enable or disable tracking |
| `apiUrl` | `string` | Base URL for the tracking API |
| `data` | `Partial<T>` | Additional event payload data |
| `removeExtraneousValues` | `boolean` | Strip non-essential fields from events |
| `allowBotTraffic` | `boolean` | Include bot-originated traffic in tracking |
| `adapters` | `string[]` | List of tracking adapter identifiers |
| `emitters.windowEvent` | `boolean` | Emit as `window` custom events |
| `emitters.dataLayer` | `boolean` | Push to GTM `dataLayer` |
| `emitters.windowPostMessage` | `boolean` | Emit via `window.postMessage` |

---

## Testing & Mocks

This package exports a full mock implementation of `ConversationService` for use in unit tests, Storybook stories, and development environments — no real LiveKit or Firebase connection required.

```typescript
import {
  MockConversationService,
  createMockConversationService,
  createConversationFixture,
  createMessageFixture,
  createRoomWithAgent,
  generateMockToken,
} from "@onlive.ai/common-121";

const mockService = createMockConversationService();

// Seed a fixture room with an agent
const room = createRoomWithAgent();

// Generate message fixtures
const messages = [
  createMessageFixture({ content: "Hello from agent" }),
  createMessageFixture({ content: "How can I help?" }),
];
```

For Storybook, use the dedicated helpers:

```typescript
import {
  getStorybookMockService,
  destroyStorybookMockService,
} from "@onlive.ai/common-121";
```

---

## Architecture

- **ESM + CJS**: Dual output for Node.js and browser environments
- **Modular imports**: Every service, utility, and component is independently importable — no side effects from unused exports
- **Full type safety**: TypeScript `.d.ts` declarations shipped alongside every module
- **Build-time minification**: All outputs are minified (whitespace, identifiers, syntax) via `tsup` + `esbuild`
- **Versioned banner**: Each built file includes a `©` copyright banner with the package version

---

## Dependencies

| Package | Version | Purpose |
|---|---|---|
| `lit` | `^3.3` | Web components framework |
| `@lit/react` | `^1.0` | React wrappers for Lit elements |
| `livekit-client` | `^2.17` | WebRTC infrastructure for real-time audio/video |
| `@livekit/components-core` | `^0.12` | LiveKit component primitives |
| `firebase` | `^11.10` | Firebase Realtime Database |
| `rxjs` | `^7.8` | Reactive programming utilities |
| `marked` | `^15.0` | Markdown parsing |
| `dompurify` | `^3.3` | HTML sanitization |
| `video.js` | `^8.23` | Video playback |
| `@onlive.ai/tracker` | `^1.0` | Onlive analytics tracking |
| `@onlive.ai/ui` | `^1.9` | Onlive UI design system |

**Peer dependencies**: `react ^19.1`

---

## Compatibility

- **Browsers**: Modern browsers with ES2020+ support (Chrome 90+, Firefox 88+, Safari 14+)
- **Node.js**: 18.x or higher (for build tooling only — not required at runtime)
- **TypeScript**: 5.7.x
- **React**: 19.x (peer dependency, optional — only required when using React components)
- **Module format**: ESM primary (`import`), CJS secondary (`require`)

---

## Related Packages

| Package | Description |
|---|---|
| [`@onlive.ai/chat`](../chat) | Chat UI components and messaging |
| [`@onlive.ai/flow`](../flow) | Interactive flow builder components |
| [`@onlive.ai/meet`](../meet) | Video conferencing components |
| [`@onlive.ai/flow-client`](../flow-client) | Flow client SDK |
| [`@onlive.ai/calendar`](../calendar) | Calendar integration components |

---

## License

This package is part of the Onlive 121 ecosystem and follows the project's licensing terms.