@alia.onl/sdk 13.0.0 → 13.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # @alia.onl/sdk
2
2
 
3
+ ## 13.1.0
4
+
5
+ The chat works in any app without host setup it did not document in code:
6
+
7
+ - **The avatar loads.** The chat mounts Bloom's `AgentAvatarProvider` itself, pointing at Alia's
8
+ shared runtime (`ALIA_CHARACTER_RUNTIME_URL`, served with CORS open); a host that serves its own
9
+ passes `characterRuntimeUrl`. Before, an app that had not hosted the 214 MB runtime showed
10
+ Bloom's "unavailable" state.
11
+ - **The empty chat greets.** With no `welcomeGreeting` it greets the signed-in person by name
12
+ (`labels.greeting` / `labels.greetingNamed`). Before, it drew nothing.
13
+
3
14
  ## 13.0.0
4
15
 
5
16
  Fixes found by driving the sheet end to end (the sheet shows plans, links citations, nests lists):
package/README.md CHANGED
@@ -25,20 +25,18 @@ the default in Expo SDK 53+), because every icon import is a subpath.
25
25
  The chat is built from Bloom (`@oxy.so/bloom`, a peer dependency): mount Bloom's
26
26
  `BloomProvider` above it, with the one `KeyboardProvider` your app already has.
27
27
 
28
- Alia's avatar is Bloom's 3D character (`AgentAvatar`), which draws through a
29
- runtime Bloom ships as static files (about 11 MB). Serve the package's
30
- `assets/character-runtime/` directory unchanged and give the URL of `runtime.mjs`
31
- to Bloom's provider, once, near the root:
32
-
33
- ```tsx
34
- import { AgentAvatarProvider } from '@oxy.so/bloom/agent-avatar';
35
-
36
- <AgentAvatarProvider runtimeUrl="/bloom-character/runtime.mjs">…</AgentAvatarProvider>
37
- ```
38
-
39
- Without it the avatar shows Bloom's "unavailable" state. Native avatars run in a
28
+ Alia's avatar is Bloom's 3D character (`AgentAvatar`). It draws through a runtime of
29
+ static files (about 214 MB), which the chat loads from Alia's own origin
30
+ (`ALIA_CHARACTER_RUNTIME_URL`, served with CORS open), so the app hosts nothing and mounts
31
+ no avatar provider. An app with a strict CSP allows `https://alia.onl` in `script-src` and
32
+ `connect-src` (and `'wasm-unsafe-eval'`). To serve your own copy instead, serve the Bloom
33
+ package's `assets/character-runtime/` directory unchanged and pass the URL of `runtime.mjs`
34
+ as `characterRuntimeUrl` to `AliaChatSheet` or `AliaChatScreen`; native avatars run in a
40
35
  WebView, so there the URL must be absolute and reachable from the device.
41
36
 
37
+ The empty chat greets the signed-in person by name ("Hi Nate, what's on your mind?"); pass
38
+ `welcomeGreeting` to say something else, or `labels.greeting` / `labels.greetingNamed` to translate it.
39
+
42
40
  Failures (a voice call that cannot start, a dictation error) are shown with Bloom's `toast`,
43
41
  so the app needs a `ToastOutlet` (`OxyProvider` mounts one), or pass `onError` to handle them.
44
42
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alia.onl/sdk",
3
- "version": "13.0.0",
3
+ "version": "13.1.0",
4
4
  "description": "Alia AI chat SDK — reusable chat UI, voice, and streaming components for Oxy apps",
5
5
  "main": "src/index.ts",
6
6
  "react-native": "src/index.ts",
@@ -32,7 +32,7 @@
32
32
  "dependencies": {
33
33
  "clsx": "^2.1.1",
34
34
  "react-native-markdown-display": "^7.0.2",
35
- "tailwind-merge": "^3.6.0",
35
+ "tailwind-merge": "^3.7.0",
36
36
  "zustand": "^5.0.15"
37
37
  },
38
38
  "peerDependencies": {
@@ -17,6 +17,10 @@ import { imageUriToDataUrl } from '../lib/image-data-url';
17
17
  import { useAmbientWave } from '../hooks/useAmbientWave';
18
18
  import { AmbientField } from './AmbientField';
19
19
  import { QuestionCard } from './QuestionCard';
20
+ import { getAccountDisplayName } from '@oxy.so/core';
21
+ import { useOxy } from '@oxy.so/services/ui/client';
22
+ import { AgentAvatarProvider } from '@oxy.so/bloom/agent-avatar';
23
+ import { ALIA_CHARACTER_RUNTIME_URL } from '../lib/character-runtime';
20
24
  import { pendingQuestions } from '../lib/questions';
21
25
  import { AliaChatMessageList } from './AliaChatMessageList';
22
26
  import { AliaFlightsProvider, ALIA_TO_PROFILE } from '../lib/flights';
@@ -84,7 +88,7 @@ export interface AliaChatContentProps {
84
88
  apiUrl?: string;
85
89
  /** Error handler (e.g. toast) */
86
90
  onError?: (message: string) => void;
87
- // Welcome message
91
+ /** The empty chat's greeting; omitted, Alia greets the signed-in person by name (`labels`). */
88
92
  welcomeGreeting?: string;
89
93
  welcomeSubtitle?: string;
90
94
  /** The lines offered over the composer on an empty chat. */
@@ -137,6 +141,8 @@ export interface AliaChatContentProps {
137
141
  onStopReady?: (stop: (() => void) | null) => void;
138
142
  /** Overrides for the chat's own copy; anything omitted is English. */
139
143
  labels?: Partial<AliaChatLabels>;
144
+ /** Where the 3D avatar's runtime is served from; omitted, Alia's shared copy (`ALIA_CHARACTER_RUNTIME_URL`). */
145
+ characterRuntimeUrl?: string;
140
146
  }
141
147
 
142
148
  /** The add menu: photos are the one attachment the chat API carries (`image_url` parts). */
@@ -399,14 +405,17 @@ function AliaChatContentBody({
399
405
  return 'writing';
400
406
  }, [messages, isStreaming, isVoiceActive, voiceAgentState]);
401
407
 
408
+ const { user } = useOxy();
409
+ const greeting =
410
+ welcomeGreeting ?? (user ? labels.greetingNamed(getAccountDisplayName(user)) : labels.greeting);
402
411
  const welcomeComponent = useMemo(() => {
403
- if (!welcomeGreeting || messages.length > 0) return undefined;
412
+ if (messages.length > 0) return undefined;
404
413
  return (
405
414
  <View className="flex-1 items-center justify-center px-4 py-10">
406
- <AliaWelcomeMessage greeting={welcomeGreeting} subtitle={welcomeSubtitle} />
415
+ <AliaWelcomeMessage greeting={greeting} subtitle={welcomeSubtitle} />
407
416
  </View>
408
417
  );
409
- }, [welcomeGreeting, welcomeSubtitle, messages.length]);
418
+ }, [greeting, welcomeSubtitle, messages.length]);
410
419
 
411
420
  // ── Ambient wave — one persistent overlay across idle/voice/TTS/STT ──
412
421
  const wave = useAmbientWave({
@@ -563,10 +572,16 @@ function AliaChatContentBody({
563
572
  }
564
573
 
565
574
  /** The chat: header, thread and composer, with the host's labels in reach of all of it. */
566
- export function AliaChatContent({ labels, ...props }: AliaChatContentProps) {
575
+ export function AliaChatContent({
576
+ labels,
577
+ characterRuntimeUrl = ALIA_CHARACTER_RUNTIME_URL,
578
+ ...props
579
+ }: AliaChatContentProps) {
567
580
  return (
568
- <AliaChatLabelsProvider labels={labels}>
569
- <AliaChatContentBody {...props} />
570
- </AliaChatLabelsProvider>
581
+ <AgentAvatarProvider runtimeUrl={characterRuntimeUrl}>
582
+ <AliaChatLabelsProvider labels={labels}>
583
+ <AliaChatContentBody {...props} />
584
+ </AliaChatLabelsProvider>
585
+ </AgentAvatarProvider>
571
586
  );
572
587
  }
@@ -62,6 +62,8 @@ export interface AliaChatScreenProps {
62
62
  voiceSession?: VoiceSessionComponent;
63
63
  /** Overrides for the chat's own copy (header, composer, plan, research…); omitted, English. */
64
64
  labels?: Partial<AliaChatLabels>;
65
+ /** Where the 3D avatar's runtime is served from; omitted, Alia's shared copy (`ALIA_CHARACTER_RUNTIME_URL`). */
66
+ characterRuntimeUrl?: string;
65
67
  }
66
68
 
67
69
  export function AliaChatScreen({
@@ -82,6 +84,7 @@ export function AliaChatScreen({
82
84
  isDarkMode,
83
85
  voiceSession,
84
86
  labels,
87
+ characterRuntimeUrl,
85
88
  }: AliaChatScreenProps) {
86
89
  const insets = useSafeAreaInsets();
87
90
  // The screen owns the whole window, so it keeps its composer out of both
@@ -129,6 +132,7 @@ export function AliaChatScreen({
129
132
  isDarkMode={isDarkMode}
130
133
  voiceSession={voiceSession}
131
134
  labels={labels}
135
+ characterRuntimeUrl={characterRuntimeUrl}
132
136
  header={header}
133
137
  />
134
138
  </KeyboardAvoidingView>
@@ -52,6 +52,8 @@ export interface AliaChatSheetProps {
52
52
  voiceSession?: VoiceSessionComponent;
53
53
  /** Overrides for the chat's own copy (header, composer, plan, research…); omitted, English. */
54
54
  labels?: Partial<AliaChatLabels>;
55
+ /** Where the 3D avatar's runtime is served from; omitted, Alia's shared copy (`ALIA_CHARACTER_RUNTIME_URL`). */
56
+ characterRuntimeUrl?: string;
55
57
  /** Draws the header's share button once there is a conversation; omitted, no share button. */
56
58
  onShare?: () => void;
57
59
  /** More rows for the header's menu (`DropdownMenuItem`s from `@oxy.so/bloom/dropdown-menu`). */
@@ -78,6 +80,7 @@ export const AliaChatSheet = forwardRef<AliaChatSheetRef, AliaChatSheetProps>(
78
80
  isDarkMode,
79
81
  voiceSession,
80
82
  labels,
83
+ characterRuntimeUrl,
81
84
  onShare,
82
85
  headerMenu,
83
86
  },
@@ -159,6 +162,7 @@ export const AliaChatSheet = forwardRef<AliaChatSheetRef, AliaChatSheetProps>(
159
162
  voiceSession,
160
163
  bottomInset: detached ? 0 : bottom,
161
164
  labels,
165
+ characterRuntimeUrl,
162
166
  };
163
167
 
164
168
  return (
package/src/index.ts CHANGED
@@ -10,6 +10,7 @@ export { AliaChatScreen } from './components/AliaChatScreen';
10
10
  export type { AliaChatScreenProps } from './components/AliaChatScreen';
11
11
 
12
12
  // ── Chat UI components ──
13
+ export { ALIA_CHARACTER_RUNTIME_URL } from './lib/character-runtime';
13
14
  export { DEFAULT_LABELS } from './lib/labels';
14
15
  export type { AliaChatLabels } from './lib/labels';
15
16
  export { VoiceModeIcon } from './components/VoiceModeIcon';
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Where the 3D character runtime (Alia's avatar) is served from when the host does not say.
3
+ *
4
+ * The runtime is ~214 MB of engine and data, so the chat loads it from Alia's own web origin
5
+ * instead of asking every app to host a copy. That origin serves it with CORS open
6
+ * (`packages/app/worker/index.js`), which a cross-origin module import needs; an app with a
7
+ * strict CSP allows it in `script-src` and `connect-src`. A host that serves its own copy
8
+ * passes `characterRuntimeUrl`.
9
+ */
10
+ export const ALIA_CHARACTER_RUNTIME_URL = 'https://alia.onl/bloom-character/runtime.mjs';
@@ -15,6 +15,11 @@ export interface AliaChatLabels {
15
15
  addPhotos: string;
16
16
  startVoice: string;
17
17
  voiceFailed: string;
18
+ // Welcome
19
+ /** The empty chat's greeting for a signed-out visitor. */
20
+ greeting: string;
21
+ /** The empty chat's greeting for a named person. */
22
+ greetingNamed: (name: string) => string;
18
23
  // Messages
19
24
  copy: string;
20
25
  helpful: string;
@@ -51,6 +56,8 @@ export const DEFAULT_LABELS: AliaChatLabels = {
51
56
  addPhotos: 'Photos',
52
57
  startVoice: 'Start voice',
53
58
  voiceFailed: "Couldn't start the voice call",
59
+ greeting: "Hi, what's on your mind?",
60
+ greetingNamed: (name) => `Hi ${name}, what's on your mind?`,
54
61
  copy: 'Copy',
55
62
  helpful: 'Helpful response',
56
63
  unhelpful: 'Unhelpful response',