@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 +11 -0
- package/README.md +10 -12
- package/package.json +2 -2
- package/src/components/AliaChatContent.tsx +23 -8
- package/src/components/AliaChatScreen.tsx +4 -0
- package/src/components/AliaChatSheet.tsx +4 -0
- package/src/index.ts +1 -0
- package/src/lib/character-runtime.ts +10 -0
- package/src/lib/labels.tsx +7 -0
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`)
|
|
29
|
-
|
|
30
|
-
`
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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 (
|
|
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={
|
|
415
|
+
<AliaWelcomeMessage greeting={greeting} subtitle={welcomeSubtitle} />
|
|
407
416
|
</View>
|
|
408
417
|
);
|
|
409
|
-
}, [
|
|
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({
|
|
575
|
+
export function AliaChatContent({
|
|
576
|
+
labels,
|
|
577
|
+
characterRuntimeUrl = ALIA_CHARACTER_RUNTIME_URL,
|
|
578
|
+
...props
|
|
579
|
+
}: AliaChatContentProps) {
|
|
567
580
|
return (
|
|
568
|
-
<
|
|
569
|
-
<
|
|
570
|
-
|
|
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';
|
package/src/lib/labels.tsx
CHANGED
|
@@ -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',
|