@alia.onl/sdk 3.0.0 → 3.1.1
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/package.json +47 -19
- package/src/components/AliaChatContent.tsx +62 -19
- package/src/components/AliaChatMessageList.tsx +437 -280
- package/src/components/AliaChatScreen.tsx +21 -48
- package/src/components/AliaChatSheet.tsx +19 -31
- package/src/components/AliaFace.tsx +108 -58
- package/src/components/AliaWelcomeMessage.tsx +75 -0
- package/src/components/Markdown.tsx +94 -130
- package/src/components/PlanPreviewCard.tsx +76 -0
- package/src/components/Reasoning.tsx +1 -3
- package/src/components/ResearchProgressCard.tsx +158 -0
- package/src/components/ThinkingIndicator.tsx +6 -21
- package/src/components/voice/AudioWaveVisualizer.tsx +72 -22
- package/src/components/voice/VoiceControls.tsx +25 -42
- package/src/components/voice/VoiceOverlay.tsx +5 -1
- package/src/hooks/useAliaChat.ts +2 -1
- package/src/hooks/useSpeechToText.ts +21 -7
- package/src/hooks/useVoiceRoom.ts +24 -8
- package/src/index.ts +10 -3
- package/src/lib/content-utils.ts +23 -0
- package/src/lib/tool-registry.ts +55 -0
- package/src/theme.ts +2 -41
- package/src/types.ts +20 -7
- package/src/components/AliaChatInput.tsx +0 -294
- package/src/components/AliaChatSuggestions.tsx +0 -70
package/src/types.ts
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
|
+
// ── Welcome / Suggestion Types ──
|
|
2
|
+
|
|
3
|
+
export interface WelcomeSuggestion {
|
|
4
|
+
id: string;
|
|
5
|
+
title: string;
|
|
6
|
+
description: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
1
9
|
// ── Chat Message Types ──
|
|
2
10
|
|
|
11
|
+
export interface ResearchSource {
|
|
12
|
+
id: number;
|
|
13
|
+
url: string;
|
|
14
|
+
title: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
3
17
|
export interface ResearchProgress {
|
|
4
18
|
phase?: string;
|
|
5
19
|
message?: string;
|
|
@@ -7,6 +21,9 @@ export interface ResearchProgress {
|
|
|
7
21
|
sourcesFound?: number;
|
|
8
22
|
currentQuery?: string;
|
|
9
23
|
iteration?: number;
|
|
24
|
+
isComplete?: boolean;
|
|
25
|
+
sources?: ResearchSource[];
|
|
26
|
+
totalSearches?: number;
|
|
10
27
|
}
|
|
11
28
|
|
|
12
29
|
export interface PlanStep {
|
|
@@ -25,7 +42,7 @@ export interface PendingPlan {
|
|
|
25
42
|
export interface ChatMessage {
|
|
26
43
|
id: string;
|
|
27
44
|
role: 'user' | 'assistant' | 'system';
|
|
28
|
-
content: string;
|
|
45
|
+
content: string | Array<{ type: string; [key: string]: any }>;
|
|
29
46
|
toolInvocations?: ToolInvocation[];
|
|
30
47
|
createdAt: number;
|
|
31
48
|
/** Extended thinking / reasoning content */
|
|
@@ -42,6 +59,8 @@ export interface ChatMessage {
|
|
|
42
59
|
isStreaming?: boolean;
|
|
43
60
|
/** Cached TTS audio URL for read-aloud */
|
|
44
61
|
audioUrl?: string;
|
|
62
|
+
/** Delegated agent identity */
|
|
63
|
+
agentInfo?: { id: string; name: string; avatar: string | null };
|
|
45
64
|
}
|
|
46
65
|
|
|
47
66
|
export interface ToolInvocation {
|
|
@@ -53,12 +72,6 @@ export interface ToolInvocation {
|
|
|
53
72
|
toolCallId?: string;
|
|
54
73
|
}
|
|
55
74
|
|
|
56
|
-
export interface AliaChatSuggestion {
|
|
57
|
-
label: string;
|
|
58
|
-
icon?: string;
|
|
59
|
-
prompt: string;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
75
|
// ── Voice Types ──
|
|
63
76
|
|
|
64
77
|
export type RoomState = 'disconnected' | 'connecting' | 'connected' | 'error';
|
|
@@ -1,294 +0,0 @@
|
|
|
1
|
-
import React, { useState, useCallback } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
View,
|
|
4
|
-
TextInput,
|
|
5
|
-
Pressable,
|
|
6
|
-
StyleSheet,
|
|
7
|
-
ActivityIndicator,
|
|
8
|
-
Platform,
|
|
9
|
-
} from 'react-native';
|
|
10
|
-
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
11
|
-
import { useSpeechToText } from '../hooks/useSpeechToText';
|
|
12
|
-
import { useAliaColors } from '../theme';
|
|
13
|
-
|
|
14
|
-
interface AliaChatInputProps {
|
|
15
|
-
onSend: (text: string) => void;
|
|
16
|
-
isStreaming: boolean;
|
|
17
|
-
onStop: () => void;
|
|
18
|
-
onVoiceActivate: () => void;
|
|
19
|
-
apiUrl?: string;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export function AliaChatInput({
|
|
23
|
-
onSend,
|
|
24
|
-
isStreaming,
|
|
25
|
-
onStop,
|
|
26
|
-
onVoiceActivate,
|
|
27
|
-
apiUrl,
|
|
28
|
-
}: AliaChatInputProps) {
|
|
29
|
-
const [input, setInput] = useState('');
|
|
30
|
-
const colors = useAliaColors();
|
|
31
|
-
const insets = useSafeAreaInsets();
|
|
32
|
-
const isDark = colors.isDark;
|
|
33
|
-
const stt = useSpeechToText({ apiUrl });
|
|
34
|
-
|
|
35
|
-
const hasText = input.trim().length > 0;
|
|
36
|
-
const canSend = hasText && !isStreaming;
|
|
37
|
-
|
|
38
|
-
const handleSend = useCallback(() => {
|
|
39
|
-
if (!canSend) return;
|
|
40
|
-
onSend(input.trim());
|
|
41
|
-
setInput('');
|
|
42
|
-
}, [canSend, input, onSend]);
|
|
43
|
-
|
|
44
|
-
const handleMicPress = useCallback(async () => {
|
|
45
|
-
if (stt.isRecording) {
|
|
46
|
-
const text = await stt.stopAndTranscribe();
|
|
47
|
-
if (text) {
|
|
48
|
-
setInput((prev) => (prev ? `${prev} ${text}` : text));
|
|
49
|
-
}
|
|
50
|
-
} else if (!stt.isTranscribing) {
|
|
51
|
-
stt.startRecording();
|
|
52
|
-
}
|
|
53
|
-
}, [stt]);
|
|
54
|
-
|
|
55
|
-
return (
|
|
56
|
-
<View
|
|
57
|
-
style={[
|
|
58
|
-
styles.container,
|
|
59
|
-
{
|
|
60
|
-
borderTopColor: colors.border,
|
|
61
|
-
paddingBottom: Math.max(insets.bottom, 12),
|
|
62
|
-
},
|
|
63
|
-
]}
|
|
64
|
-
>
|
|
65
|
-
<TextInput
|
|
66
|
-
style={[
|
|
67
|
-
styles.input,
|
|
68
|
-
{
|
|
69
|
-
color: colors.text,
|
|
70
|
-
backgroundColor: isDark ? colors.inputBackground : colors.card,
|
|
71
|
-
},
|
|
72
|
-
]}
|
|
73
|
-
value={input}
|
|
74
|
-
onChangeText={setInput}
|
|
75
|
-
placeholder="Ask Alia..."
|
|
76
|
-
placeholderTextColor={colors.secondaryText}
|
|
77
|
-
multiline
|
|
78
|
-
maxLength={2000}
|
|
79
|
-
onSubmitEditing={handleSend}
|
|
80
|
-
blurOnSubmit={false}
|
|
81
|
-
/>
|
|
82
|
-
|
|
83
|
-
{/* STT mic button */}
|
|
84
|
-
<Pressable
|
|
85
|
-
onPress={handleMicPress}
|
|
86
|
-
disabled={stt.isTranscribing}
|
|
87
|
-
style={styles.micButton}
|
|
88
|
-
>
|
|
89
|
-
{stt.isTranscribing ? (
|
|
90
|
-
<ActivityIndicator size="small" color="#6366f1" />
|
|
91
|
-
) : stt.isRecording ? (
|
|
92
|
-
<MicOffIcon />
|
|
93
|
-
) : (
|
|
94
|
-
<MicIcon color={colors.secondaryText} />
|
|
95
|
-
)}
|
|
96
|
-
</Pressable>
|
|
97
|
-
|
|
98
|
-
{/* Three-state submit button */}
|
|
99
|
-
{isStreaming ? (
|
|
100
|
-
<Pressable
|
|
101
|
-
style={[styles.actionButton, { backgroundColor: colors.tint }]}
|
|
102
|
-
onPress={onStop}
|
|
103
|
-
>
|
|
104
|
-
<StopIcon />
|
|
105
|
-
</Pressable>
|
|
106
|
-
) : hasText ? (
|
|
107
|
-
<Pressable
|
|
108
|
-
style={[
|
|
109
|
-
styles.actionButton,
|
|
110
|
-
{ backgroundColor: colors.tint },
|
|
111
|
-
!canSend && { opacity: 0.4 },
|
|
112
|
-
]}
|
|
113
|
-
onPress={handleSend}
|
|
114
|
-
disabled={!canSend}
|
|
115
|
-
>
|
|
116
|
-
<ArrowUpIcon />
|
|
117
|
-
</Pressable>
|
|
118
|
-
) : (
|
|
119
|
-
<Pressable
|
|
120
|
-
style={[styles.actionButton, { backgroundColor: colors.tint }]}
|
|
121
|
-
onPress={onVoiceActivate}
|
|
122
|
-
>
|
|
123
|
-
<SoundIcon />
|
|
124
|
-
</Pressable>
|
|
125
|
-
)}
|
|
126
|
-
</View>
|
|
127
|
-
);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
// ── Icons (inline SVG on web, View-based on native) ──
|
|
131
|
-
|
|
132
|
-
function ArrowUpIcon() {
|
|
133
|
-
return (
|
|
134
|
-
<View style={styles.iconCenter}>
|
|
135
|
-
{Platform.OS === 'web' ? (
|
|
136
|
-
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="white" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
|
|
137
|
-
<path d="M12 19V5M5 12l7-7 7 7" />
|
|
138
|
-
</svg>
|
|
139
|
-
) : (
|
|
140
|
-
<View style={styles.arrowIconInner}>
|
|
141
|
-
<View style={[styles.arrowStem, { backgroundColor: '#FFFFFF' }]} />
|
|
142
|
-
<View style={[styles.arrowHead, { borderColor: '#FFFFFF' }]} />
|
|
143
|
-
</View>
|
|
144
|
-
)}
|
|
145
|
-
</View>
|
|
146
|
-
);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
function StopIcon() {
|
|
150
|
-
return (
|
|
151
|
-
<View style={styles.iconCenter}>
|
|
152
|
-
{Platform.OS === 'web' ? (
|
|
153
|
-
<svg width="14" height="14" viewBox="0 0 24 24" fill="white">
|
|
154
|
-
<rect x="4" y="4" width="16" height="16" rx="2" />
|
|
155
|
-
</svg>
|
|
156
|
-
) : (
|
|
157
|
-
<View style={styles.stopSquare} />
|
|
158
|
-
)}
|
|
159
|
-
</View>
|
|
160
|
-
);
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
function SoundIcon() {
|
|
164
|
-
return (
|
|
165
|
-
<View style={styles.iconCenter}>
|
|
166
|
-
{Platform.OS === 'web' ? (
|
|
167
|
-
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="white" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
168
|
-
<path d="M11 5L6 9H2v6h4l5 4V5z" />
|
|
169
|
-
<path d="M15.54 8.46a5 5 0 0 1 0 7.07" />
|
|
170
|
-
<path d="M19.07 4.93a10 10 0 0 1 0 14.14" />
|
|
171
|
-
</svg>
|
|
172
|
-
) : (
|
|
173
|
-
<View style={styles.soundBars}>
|
|
174
|
-
<View style={[styles.soundBar, styles.soundBarShort]} />
|
|
175
|
-
<View style={[styles.soundBar, styles.soundBarMed]} />
|
|
176
|
-
<View style={[styles.soundBar, styles.soundBarTall]} />
|
|
177
|
-
</View>
|
|
178
|
-
)}
|
|
179
|
-
</View>
|
|
180
|
-
);
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
function MicIcon({ color }: { color: string }) {
|
|
184
|
-
return (
|
|
185
|
-
<View style={styles.iconCenter}>
|
|
186
|
-
{Platform.OS === 'web' ? (
|
|
187
|
-
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
188
|
-
<rect x="9" y="1" width="6" height="12" rx="3" />
|
|
189
|
-
<path d="M5 10a7 7 0 0 0 14 0" />
|
|
190
|
-
<line x1="12" y1="17" x2="12" y2="21" />
|
|
191
|
-
<line x1="8" y1="21" x2="16" y2="21" />
|
|
192
|
-
</svg>
|
|
193
|
-
) : (
|
|
194
|
-
<View style={[styles.micDot, { backgroundColor: color }]} />
|
|
195
|
-
)}
|
|
196
|
-
</View>
|
|
197
|
-
);
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
function MicOffIcon() {
|
|
201
|
-
return (
|
|
202
|
-
<View style={styles.iconCenter}>
|
|
203
|
-
{Platform.OS === 'web' ? (
|
|
204
|
-
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#ef4444" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
205
|
-
<rect x="9" y="1" width="6" height="12" rx="3" />
|
|
206
|
-
<path d="M5 10a7 7 0 0 0 14 0" />
|
|
207
|
-
<line x1="12" y1="17" x2="12" y2="21" />
|
|
208
|
-
<line x1="1" y1="1" x2="23" y2="23" />
|
|
209
|
-
</svg>
|
|
210
|
-
) : (
|
|
211
|
-
<View style={[styles.micDot, { backgroundColor: '#ef4444' }]} />
|
|
212
|
-
)}
|
|
213
|
-
</View>
|
|
214
|
-
);
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
const styles = StyleSheet.create({
|
|
218
|
-
container: {
|
|
219
|
-
flexDirection: 'row',
|
|
220
|
-
alignItems: 'flex-end',
|
|
221
|
-
paddingHorizontal: 12,
|
|
222
|
-
paddingTop: 8,
|
|
223
|
-
gap: 8,
|
|
224
|
-
borderTopWidth: StyleSheet.hairlineWidth,
|
|
225
|
-
},
|
|
226
|
-
input: {
|
|
227
|
-
flex: 1,
|
|
228
|
-
fontSize: 15,
|
|
229
|
-
paddingHorizontal: 14,
|
|
230
|
-
paddingVertical: 10,
|
|
231
|
-
borderRadius: 20,
|
|
232
|
-
maxHeight: 100,
|
|
233
|
-
},
|
|
234
|
-
micButton: {
|
|
235
|
-
width: 32,
|
|
236
|
-
height: 40,
|
|
237
|
-
alignItems: 'center',
|
|
238
|
-
justifyContent: 'center',
|
|
239
|
-
},
|
|
240
|
-
actionButton: {
|
|
241
|
-
width: 40,
|
|
242
|
-
height: 40,
|
|
243
|
-
borderRadius: 20,
|
|
244
|
-
alignItems: 'center',
|
|
245
|
-
justifyContent: 'center',
|
|
246
|
-
},
|
|
247
|
-
iconCenter: {
|
|
248
|
-
width: 18,
|
|
249
|
-
height: 18,
|
|
250
|
-
alignItems: 'center',
|
|
251
|
-
justifyContent: 'center',
|
|
252
|
-
},
|
|
253
|
-
arrowIconInner: {
|
|
254
|
-
alignItems: 'center',
|
|
255
|
-
},
|
|
256
|
-
arrowStem: {
|
|
257
|
-
width: 2,
|
|
258
|
-
height: 12,
|
|
259
|
-
borderRadius: 1,
|
|
260
|
-
},
|
|
261
|
-
arrowHead: {
|
|
262
|
-
position: 'absolute',
|
|
263
|
-
top: -1,
|
|
264
|
-
width: 10,
|
|
265
|
-
height: 10,
|
|
266
|
-
borderTopWidth: 2.5,
|
|
267
|
-
borderLeftWidth: 2.5,
|
|
268
|
-
transform: [{ rotate: '45deg' }],
|
|
269
|
-
},
|
|
270
|
-
stopSquare: {
|
|
271
|
-
width: 12,
|
|
272
|
-
height: 12,
|
|
273
|
-
borderRadius: 2,
|
|
274
|
-
backgroundColor: '#FFFFFF',
|
|
275
|
-
},
|
|
276
|
-
soundBars: {
|
|
277
|
-
flexDirection: 'row',
|
|
278
|
-
alignItems: 'flex-end',
|
|
279
|
-
gap: 2,
|
|
280
|
-
},
|
|
281
|
-
soundBar: {
|
|
282
|
-
width: 3,
|
|
283
|
-
backgroundColor: '#FFFFFF',
|
|
284
|
-
borderRadius: 1.5,
|
|
285
|
-
},
|
|
286
|
-
soundBarShort: { height: 6 },
|
|
287
|
-
soundBarMed: { height: 10 },
|
|
288
|
-
soundBarTall: { height: 14 },
|
|
289
|
-
micDot: {
|
|
290
|
-
width: 12,
|
|
291
|
-
height: 12,
|
|
292
|
-
borderRadius: 6,
|
|
293
|
-
},
|
|
294
|
-
});
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';
|
|
3
|
-
import { useAliaColors } from '../theme';
|
|
4
|
-
import type { AliaChatSuggestion } from '../types';
|
|
5
|
-
|
|
6
|
-
interface AliaChatSuggestionsProps {
|
|
7
|
-
suggestions: AliaChatSuggestion[];
|
|
8
|
-
onSelect: (prompt: string) => void;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export function AliaChatSuggestions({ suggestions, onSelect }: AliaChatSuggestionsProps) {
|
|
12
|
-
const colors = useAliaColors();
|
|
13
|
-
const isDark = colors.isDark;
|
|
14
|
-
|
|
15
|
-
if (suggestions.length === 0) return null;
|
|
16
|
-
|
|
17
|
-
return (
|
|
18
|
-
<View style={styles.container}>
|
|
19
|
-
<Text style={[styles.greeting, { color: colors.tint }]}>
|
|
20
|
-
How can I help you today?
|
|
21
|
-
</Text>
|
|
22
|
-
<View style={styles.list}>
|
|
23
|
-
{suggestions.map((suggestion, i) => (
|
|
24
|
-
<TouchableOpacity
|
|
25
|
-
key={i}
|
|
26
|
-
style={[
|
|
27
|
-
styles.chip,
|
|
28
|
-
{ backgroundColor: isDark ? colors.card : colors.card },
|
|
29
|
-
]}
|
|
30
|
-
onPress={() => onSelect(suggestion.prompt)}
|
|
31
|
-
activeOpacity={0.7}
|
|
32
|
-
>
|
|
33
|
-
<Text style={[styles.chipText, { color: colors.text }]}>
|
|
34
|
-
{suggestion.label}
|
|
35
|
-
</Text>
|
|
36
|
-
</TouchableOpacity>
|
|
37
|
-
))}
|
|
38
|
-
</View>
|
|
39
|
-
</View>
|
|
40
|
-
);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const styles = StyleSheet.create({
|
|
44
|
-
container: {
|
|
45
|
-
paddingTop: 16,
|
|
46
|
-
paddingHorizontal: 16,
|
|
47
|
-
},
|
|
48
|
-
greeting: {
|
|
49
|
-
fontSize: 24,
|
|
50
|
-
fontWeight: '600',
|
|
51
|
-
lineHeight: 32,
|
|
52
|
-
marginBottom: 20,
|
|
53
|
-
paddingHorizontal: 4,
|
|
54
|
-
},
|
|
55
|
-
list: {
|
|
56
|
-
gap: 8,
|
|
57
|
-
},
|
|
58
|
-
chip: {
|
|
59
|
-
flexDirection: 'row',
|
|
60
|
-
alignItems: 'center',
|
|
61
|
-
gap: 12,
|
|
62
|
-
paddingHorizontal: 16,
|
|
63
|
-
paddingVertical: 14,
|
|
64
|
-
borderRadius: 16,
|
|
65
|
-
},
|
|
66
|
-
chipText: {
|
|
67
|
-
fontSize: 14,
|
|
68
|
-
flex: 1,
|
|
69
|
-
},
|
|
70
|
-
});
|