expo-ai-kit 0.1.8 → 0.1.10
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/expo-module.config.json +3 -4
- package/ios/ExpoAiKitModule.swift +90 -35
- package/package.json +3 -4
- package/src/ExpoAiKitModule.ts +19 -0
- package/src/index.ts +34 -0
- package/src/types.ts +12 -0
package/expo-module.config.json
CHANGED
|
@@ -7,7 +7,7 @@ public class ExpoAiKitModule: Module {
|
|
|
7
7
|
|
|
8
8
|
AsyncFunction("prepareModel") { (_: [String: Any]?) async throws in
|
|
9
9
|
if #available(iOS 26.0, *) {
|
|
10
|
-
_ = SystemLanguageModel.default
|
|
10
|
+
_ = SystemLanguageModel.default
|
|
11
11
|
} else {
|
|
12
12
|
//
|
|
13
13
|
}
|
|
@@ -18,39 +18,41 @@ public class ExpoAiKitModule: Module {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
AsyncFunction("sendMessage") {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
(
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
21
|
+
(
|
|
22
|
+
sessionId: String,
|
|
23
|
+
messages: [[String: Any]],
|
|
24
|
+
options: [String: Any]?
|
|
25
|
+
) async throws -> [String: Any] in
|
|
26
|
+
|
|
27
|
+
let lastUser =
|
|
28
|
+
messages
|
|
29
|
+
.reversed()
|
|
30
|
+
.first { ($0["role"] as? String) == "user" }?["content"] as? String
|
|
31
|
+
?? messages.last?["content"] as? String
|
|
32
|
+
?? ""
|
|
33
|
+
|
|
34
|
+
if #available(iOS 26.0, *) {
|
|
35
|
+
let systemPrompt =
|
|
36
|
+
(messages.first {
|
|
37
|
+
($0["role"] as? String) == "system"
|
|
38
|
+
}?["content"] as? String) ?? """
|
|
39
|
+
You are a helpful, friendly assistant.
|
|
40
|
+
Answer the user's question directly and concisely.
|
|
41
|
+
If the question is unsafe, politely refuse, otherwise just answer.
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
let session = LanguageModelSession(instructions: systemPrompt)
|
|
45
|
+
|
|
46
|
+
let response = try await session.respond(to: lastUser)
|
|
47
|
+
|
|
48
|
+
let replyText = response.content
|
|
49
|
+
|
|
50
|
+
return ["reply": replyText]
|
|
51
|
+
} else {
|
|
52
|
+
let replyText = "Mock reply (no on-device model): \(lastUser)"
|
|
53
|
+
return ["reply": replyText]
|
|
54
|
+
}
|
|
55
|
+
}
|
|
54
56
|
|
|
55
57
|
Function("isAvailable") {
|
|
56
58
|
if #available(iOS 26.0, *) {
|
|
@@ -59,6 +61,59 @@ public class ExpoAiKitModule: Module {
|
|
|
59
61
|
return false
|
|
60
62
|
}
|
|
61
63
|
}
|
|
64
|
+
|
|
65
|
+
AsyncFunction("sendPrompt") { (prompt: String) async throws -> String in
|
|
66
|
+
if #available(iOS 26.0, *) {
|
|
67
|
+
let systemPrompt = """
|
|
68
|
+
You are a helpful, knowledgeable AI assistant running privately on-device. Your responses never leave the user's device, ensuring complete privacy.
|
|
69
|
+
|
|
70
|
+
## Core Principles
|
|
71
|
+
- **Accuracy first**: Provide correct, well-reasoned information. If uncertain, say so clearly rather than guessing.
|
|
72
|
+
- **Be genuinely helpful**: Understand the user's actual intent, not just their literal words. Anticipate follow-up needs.
|
|
73
|
+
- **Respect user time**: Get to the point. Lead with the answer, then provide context if needed.
|
|
74
|
+
|
|
75
|
+
## Response Style
|
|
76
|
+
- Use clear, natural language—avoid jargon unless the user demonstrates technical familiarity
|
|
77
|
+
- Match the user's tone and complexity level
|
|
78
|
+
- For simple questions: give a direct answer (1-2 sentences)
|
|
79
|
+
- For complex topics: use structured formatting (bullet points, numbered steps, headers)
|
|
80
|
+
- When explaining concepts: use concrete examples and analogies
|
|
81
|
+
- For how-to requests: provide step-by-step instructions
|
|
82
|
+
|
|
83
|
+
## Task Capabilities
|
|
84
|
+
You can help with:
|
|
85
|
+
- **Writing**: drafting, editing, summarizing, rephrasing, tone adjustments, grammar fixes
|
|
86
|
+
- **Analysis**: breaking down complex topics, comparing options, pros/cons lists
|
|
87
|
+
- **Brainstorming**: generating ideas, creative suggestions, alternative approaches
|
|
88
|
+
- **Learning**: explaining concepts, answering questions, providing examples
|
|
89
|
+
- **Planning**: organizing tasks, creating outlines, structuring projects
|
|
90
|
+
- **Problem-solving**: debugging logic, troubleshooting issues, suggesting solutions
|
|
91
|
+
- **Calculations**: math, unit conversions, date/time calculations
|
|
92
|
+
- **Code**: explaining code, writing snippets, debugging, suggesting improvements
|
|
93
|
+
|
|
94
|
+
## Quality Standards
|
|
95
|
+
- Double-check facts and logic before responding
|
|
96
|
+
- Provide sources or reasoning when making claims
|
|
97
|
+
- Offer multiple perspectives on subjective topics
|
|
98
|
+
- Acknowledge limitations—you don't have internet access or real-time information
|
|
99
|
+
- If a request is ambiguous, ask a clarifying question or state your interpretation
|
|
100
|
+
|
|
101
|
+
## Safety Boundaries
|
|
102
|
+
- Decline requests for harmful, illegal, dangerous, or unethical content
|
|
103
|
+
- Do not help with content that could endanger safety, privacy, or wellbeing
|
|
104
|
+
- For medical symptoms: provide general info but always recommend consulting a healthcare provider
|
|
105
|
+
- For legal questions: offer general guidance but recommend consulting a qualified attorney
|
|
106
|
+
- For financial advice: share educational information but suggest consulting a financial professional
|
|
107
|
+
- Do not generate content involving minors in inappropriate contexts
|
|
108
|
+
- Do not assist with deception, manipulation, or harassment
|
|
109
|
+
"""
|
|
110
|
+
|
|
111
|
+
let session = LanguageModelSession(instructions: systemPrompt)
|
|
112
|
+
let response = try await session.respond(to: prompt)
|
|
113
|
+
return response.content
|
|
114
|
+
} else {
|
|
115
|
+
return "Mock reply (no on-device model): \(prompt)"
|
|
116
|
+
}
|
|
117
|
+
}
|
|
62
118
|
}
|
|
63
119
|
}
|
|
64
|
-
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-ai-kit",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.10",
|
|
4
4
|
"description": "Expo AI Kit module",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
@@ -8,9 +8,8 @@
|
|
|
8
8
|
"build",
|
|
9
9
|
"ios",
|
|
10
10
|
"android",
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"LICENSE"
|
|
11
|
+
"src",
|
|
12
|
+
"expo-module.config.json"
|
|
14
13
|
],
|
|
15
14
|
"scripts": {
|
|
16
15
|
"build": "expo-module build",
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { requireNativeModule } from 'expo-modules-core';
|
|
2
|
+
import type { LLMMessage, LLMOptions } from './types';
|
|
3
|
+
|
|
4
|
+
export type ExpoAiKitNativeModule = {
|
|
5
|
+
prepareModel(options?: { model?: string }): Promise<void>;
|
|
6
|
+
createSession(options?: { systemPrompt?: string }): Promise<string>;
|
|
7
|
+
sendMessage(
|
|
8
|
+
sessionId: string,
|
|
9
|
+
messages: LLMMessage[],
|
|
10
|
+
options?: LLMOptions
|
|
11
|
+
): Promise<{ reply: string }>;
|
|
12
|
+
isAvailable(): boolean;
|
|
13
|
+
sendPrompt(prompt: string): Promise<string>;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const NativeModule: ExpoAiKitNativeModule =
|
|
17
|
+
requireNativeModule<ExpoAiKitNativeModule>('ExpoAiKit');
|
|
18
|
+
|
|
19
|
+
export default NativeModule;
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import NativeModule from './ExpoAiKitModule';
|
|
2
|
+
import { Platform } from 'react-native';
|
|
3
|
+
export * from './types';
|
|
4
|
+
import type { LLMMessage, LLMOptions } from './types';
|
|
5
|
+
|
|
6
|
+
export async function prepareModel(options?: { model?: string }) {
|
|
7
|
+
return NativeModule.prepareModel(options);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export async function createSession(options?: { systemPrompt?: string }) {
|
|
11
|
+
return NativeModule.createSession(options);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export async function sendMessage(
|
|
15
|
+
sessionId: string,
|
|
16
|
+
messages: LLMMessage[],
|
|
17
|
+
options?: LLMOptions
|
|
18
|
+
) {
|
|
19
|
+
return NativeModule.sendMessage(sessionId, messages, options);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export async function isAvailable(): Promise<boolean> {
|
|
23
|
+
if (Platform.OS === 'ios' || Platform.OS === 'android') {
|
|
24
|
+
return NativeModule.isAvailable();
|
|
25
|
+
}
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export async function sendPrompt(prompt: string): Promise<string> {
|
|
30
|
+
if (Platform.OS === 'ios' || Platform.OS === 'android') {
|
|
31
|
+
return NativeModule.sendPrompt(prompt);
|
|
32
|
+
}
|
|
33
|
+
return '';
|
|
34
|
+
}
|