@mobileai/react-native 0.8.8 → 0.9.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/lib/module/components/AIAgent.js +76 -61
- package/lib/module/components/AIAgent.js.map +1 -1
- package/lib/module/components/AgentChatBar.js +10 -19
- package/lib/module/components/AgentChatBar.js.map +1 -1
- package/lib/module/components/AgentOverlay.js +10 -11
- package/lib/module/components/AgentOverlay.js.map +1 -1
- package/lib/module/core/AgentRuntime.js +1 -1
- package/lib/module/core/AgentRuntime.js.map +1 -1
- package/lib/module/providers/GeminiProvider.js +41 -3
- package/lib/module/providers/GeminiProvider.js.map +1 -1
- package/lib/typescript/src/components/AIAgent.d.ts.map +1 -1
- package/lib/typescript/src/components/AgentChatBar.d.ts.map +1 -1
- package/lib/typescript/src/components/AgentOverlay.d.ts.map +1 -1
- package/lib/typescript/src/providers/GeminiProvider.d.ts +5 -0
- package/lib/typescript/src/providers/GeminiProvider.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/AIAgent.tsx +82 -66
- package/src/components/AgentChatBar.tsx +5 -12
- package/src/components/AgentOverlay.tsx +6 -6
- package/src/core/AgentRuntime.ts +1 -1
- package/src/providers/GeminiProvider.ts +41 -2
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { View, Text, StyleSheet, ActivityIndicator, TouchableOpacity } from 'react-native';
|
|
7
|
+
import { CloseIcon } from './Icons';
|
|
7
8
|
|
|
8
9
|
interface AgentOverlayProps {
|
|
9
10
|
visible: boolean;
|
|
@@ -25,7 +26,7 @@ export function AgentOverlay({ visible, statusText, onCancel }: AgentOverlayProp
|
|
|
25
26
|
style={styles.cancelButton}
|
|
26
27
|
hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }}
|
|
27
28
|
>
|
|
28
|
-
<
|
|
29
|
+
<CloseIcon size={12} color="#fff" />
|
|
29
30
|
</TouchableOpacity>
|
|
30
31
|
)}
|
|
31
32
|
</View>
|
|
@@ -50,11 +51,13 @@ const styles = StyleSheet.create({
|
|
|
50
51
|
paddingHorizontal: 16,
|
|
51
52
|
paddingVertical: 10,
|
|
52
53
|
borderRadius: 20,
|
|
54
|
+
maxWidth: '85%',
|
|
53
55
|
},
|
|
54
56
|
text: {
|
|
55
57
|
color: '#fff',
|
|
56
58
|
fontSize: 14,
|
|
57
59
|
fontWeight: '500',
|
|
60
|
+
flexShrink: 1,
|
|
58
61
|
},
|
|
59
62
|
cancelButton: {
|
|
60
63
|
marginLeft: 4,
|
|
@@ -64,10 +67,7 @@ const styles = StyleSheet.create({
|
|
|
64
67
|
backgroundColor: 'rgba(255, 255, 255, 0.2)',
|
|
65
68
|
alignItems: 'center',
|
|
66
69
|
justifyContent: 'center',
|
|
67
|
-
|
|
68
|
-
cancelText: {
|
|
69
|
-
color: '#fff',
|
|
70
|
-
fontSize: 12,
|
|
71
|
-
fontWeight: '700',
|
|
70
|
+
flexShrink: 0,
|
|
72
71
|
},
|
|
73
72
|
});
|
|
73
|
+
|
package/src/core/AgentRuntime.ts
CHANGED
|
@@ -1254,7 +1254,7 @@ ${screen.elementsText}
|
|
|
1254
1254
|
// Dynamic status update based on tool being executed + Reasoning
|
|
1255
1255
|
const statusLabel = this.getToolStatusLabel(toolCall.name, toolCall.args);
|
|
1256
1256
|
// Prefer the human-readable plan over the raw tool status if available to avoid double statuses
|
|
1257
|
-
const statusDisplay = reasoning.plan
|
|
1257
|
+
const statusDisplay = reasoning.plan || statusLabel;
|
|
1258
1258
|
this.config.onStatusUpdate?.(statusDisplay);
|
|
1259
1259
|
|
|
1260
1260
|
// Find and execute the tool
|
|
@@ -102,9 +102,8 @@ export class GeminiProvider implements AIProvider {
|
|
|
102
102
|
} catch (error: any) {
|
|
103
103
|
logger.error('GeminiProvider', 'Request failed:', error.message);
|
|
104
104
|
|
|
105
|
-
// Preserve HTTP error format for backward compatibility with tests
|
|
106
105
|
if (error.status) {
|
|
107
|
-
throw new Error(
|
|
106
|
+
throw new Error(this.formatProviderError(error.status, error.message));
|
|
108
107
|
}
|
|
109
108
|
throw error;
|
|
110
109
|
}
|
|
@@ -315,4 +314,44 @@ export class GeminiProvider implements AIProvider {
|
|
|
315
314
|
|
|
316
315
|
return { promptTokens, completionTokens, totalTokens, estimatedCostUSD };
|
|
317
316
|
}
|
|
317
|
+
|
|
318
|
+
// ─── Error Formatting ──────────────────────────────────────
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Converts raw API errors into clean, user-friendly messages.
|
|
322
|
+
* Parses JSON error bodies and maps HTTP codes to plain language.
|
|
323
|
+
*/
|
|
324
|
+
private formatProviderError(status: number, rawMessage: string): string {
|
|
325
|
+
// Try to extract the human-readable message from JSON body
|
|
326
|
+
let humanMessage = '';
|
|
327
|
+
try {
|
|
328
|
+
const parsed = JSON.parse(rawMessage);
|
|
329
|
+
humanMessage = parsed?.error?.message || parsed?.message || '';
|
|
330
|
+
} catch {
|
|
331
|
+
// rawMessage may contain JSON embedded in a string like "503: {json}"
|
|
332
|
+
const jsonMatch = rawMessage.match(/\{[\s\S]*\}/);
|
|
333
|
+
if (jsonMatch) {
|
|
334
|
+
try {
|
|
335
|
+
const parsed = JSON.parse(jsonMatch[0]);
|
|
336
|
+
humanMessage = parsed?.error?.message || parsed?.message || '';
|
|
337
|
+
} catch { /* ignore */ }
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// Map status codes to friendly descriptions
|
|
342
|
+
switch (status) {
|
|
343
|
+
case 429:
|
|
344
|
+
return humanMessage || 'Too many requests. Please wait a moment and try again.';
|
|
345
|
+
case 503:
|
|
346
|
+
return humanMessage || 'The AI service is temporarily unavailable. Please try again shortly.';
|
|
347
|
+
case 500:
|
|
348
|
+
return humanMessage || 'The AI service encountered an internal error. Please try again.';
|
|
349
|
+
case 401:
|
|
350
|
+
return 'Authentication failed. Please check your API key.';
|
|
351
|
+
case 403:
|
|
352
|
+
return 'Access denied. Your API key may not have the required permissions.';
|
|
353
|
+
default:
|
|
354
|
+
return humanMessage || `Something went wrong (${status}). Please try again.`;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
318
357
|
}
|