@capgo/capacitor-llm 7.1.2

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.
@@ -0,0 +1,156 @@
1
+ var __asyncValues = (this && this.__asyncValues) || function (o) {
2
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
3
+ var m = o[Symbol.asyncIterator], i;
4
+ return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
5
+ function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
6
+ function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
7
+ };
8
+ import { WebPlugin } from '@capacitor/core';
9
+ import { FilesetResolver, LlmInference } from '@mediapipe/tasks-genai';
10
+ export class CapgoLLMWeb extends WebPlugin {
11
+ constructor() {
12
+ super(...arguments);
13
+ this.llm = null;
14
+ this.chatSessions = new Map();
15
+ this.readiness = 'not-loaded';
16
+ }
17
+ async getReadiness() {
18
+ return { readiness: this.readiness };
19
+ }
20
+ async createChat() {
21
+ if (!this.llm) {
22
+ throw new Error('Model not loaded. Call setModel first.');
23
+ }
24
+ const chatId = `chat_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
25
+ this.chatSessions.set(chatId, {
26
+ id: chatId,
27
+ llm: this.llm,
28
+ isActive: true,
29
+ });
30
+ return { id: chatId };
31
+ }
32
+ async sendMessage(options) {
33
+ var e_1, _a;
34
+ const session = this.chatSessions.get(options.chatId);
35
+ if (!session) {
36
+ throw new Error(`Chat session ${options.chatId} not found`);
37
+ }
38
+ if (!session.isActive) {
39
+ throw new Error(`Chat session ${options.chatId} is not active`);
40
+ }
41
+ try {
42
+ // Generate response using MediaPipe GenAI streaming API
43
+ const response = session.llm.generateResponseStream(options.message);
44
+ try {
45
+ for (var response_1 = __asyncValues(response), response_1_1; response_1_1 = await response_1.next(), !response_1_1.done;) {
46
+ const partialResponse = response_1_1.value;
47
+ // Send incremental text
48
+ this.notifyListeners('textFromAi', {
49
+ text: partialResponse,
50
+ chatId: options.chatId,
51
+ isChunk: true,
52
+ });
53
+ }
54
+ }
55
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
56
+ finally {
57
+ try {
58
+ if (response_1_1 && !response_1_1.done && (_a = response_1.return)) await _a.call(response_1);
59
+ }
60
+ finally { if (e_1) throw e_1.error; }
61
+ }
62
+ // Notify completion
63
+ this.notifyListeners('aiFinished', {
64
+ chatId: options.chatId,
65
+ });
66
+ }
67
+ catch (error) {
68
+ console.error('Error generating response:', error);
69
+ throw error;
70
+ }
71
+ }
72
+ async setModel(options) {
73
+ try {
74
+ // Update readiness
75
+ this.readiness = 'loading';
76
+ this.notifyListeners('readinessChange', { readiness: this.readiness });
77
+ // Create LLM configuration
78
+ const config = {
79
+ baseOptions: {
80
+ modelAssetPath: options.path,
81
+ },
82
+ maxTokens: options.maxTokens || 2048,
83
+ topK: options.topk || 40,
84
+ temperature: options.temperature || 0.8,
85
+ randomSeed: options.randomSeed || 0,
86
+ };
87
+ const genai = await FilesetResolver.forGenAiTasks('https://cdn.jsdelivr.net/npm/@mediapipe/tasks-genai@latest/wasm');
88
+ // Create LLM instance
89
+ this.llm = await LlmInference.createFromOptions(genai, config);
90
+ // Update readiness
91
+ this.readiness = 'ready';
92
+ this.notifyListeners('readinessChange', { readiness: this.readiness });
93
+ }
94
+ catch (error) {
95
+ this.readiness = 'error';
96
+ this.notifyListeners('readinessChange', { readiness: this.readiness });
97
+ throw error;
98
+ }
99
+ }
100
+ async downloadModel(options) {
101
+ var _a;
102
+ try {
103
+ // For web, we'll simulate download by fetching and storing in IndexedDB or returning the URL
104
+ const response = await fetch(options.url, {
105
+ method: 'GET',
106
+ headers: {
107
+ 'Content-Type': 'application/octet-stream',
108
+ },
109
+ });
110
+ if (!response.ok) {
111
+ throw new Error(`Failed to download model: ${response.statusText}`);
112
+ }
113
+ const contentLength = response.headers.get('content-length');
114
+ const totalBytes = contentLength ? parseInt(contentLength, 10) : undefined;
115
+ // Read the response with progress
116
+ const reader = (_a = response.body) === null || _a === void 0 ? void 0 : _a.getReader();
117
+ if (!reader) {
118
+ throw new Error('Failed to get reader from response');
119
+ }
120
+ const chunks = [];
121
+ let downloadedBytes = 0;
122
+ while (true) {
123
+ const { done, value } = await reader.read();
124
+ if (done)
125
+ break;
126
+ if (value) {
127
+ chunks.push(value);
128
+ downloadedBytes += value.length;
129
+ }
130
+ // Notify progress
131
+ const progress = totalBytes ? (downloadedBytes / totalBytes) * 100 : 0;
132
+ this.notifyListeners('downloadProgress', {
133
+ progress,
134
+ totalBytes,
135
+ downloadedBytes,
136
+ });
137
+ }
138
+ // For web, we'll return the original URL as the path
139
+ // In a real implementation, you might want to store this in IndexedDB
140
+ const result = {
141
+ path: options.url,
142
+ };
143
+ // Handle companion file if provided
144
+ if (options.companionUrl) {
145
+ // For web, just return the companion URL
146
+ result.companionPath = options.companionUrl;
147
+ }
148
+ return result;
149
+ }
150
+ catch (error) {
151
+ console.error('Error downloading model:', error);
152
+ throw error;
153
+ }
154
+ }
155
+ }
156
+ //# sourceMappingURL=web.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"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","sourcesContent":["import { WebPlugin } from '@capacitor/core';\nimport { FilesetResolver, LlmInference } from '@mediapipe/tasks-genai';\n\nimport type {\n LLMPlugin,\n DownloadModelOptions,\n DownloadModelResult,\n ModelOptions,\n TextFromAiEvent,\n AiFinishedEvent,\n DownloadProgressEvent,\n ReadinessChangeEvent,\n} from './definitions';\n\ninterface ChatSession {\n id: string;\n llm: any;\n isActive: boolean;\n}\n\nexport class CapgoLLMWeb extends WebPlugin implements LLMPlugin {\n private llm: any = null;\n private chatSessions: Map<string, ChatSession> = new Map();\n private readiness = 'not-loaded';\n\n async getReadiness(): Promise<{ readiness: string }> {\n return { readiness: this.readiness };\n }\n\n async createChat(): Promise<{ id: string; instructions?: string }> {\n if (!this.llm) {\n throw new Error('Model not loaded. Call setModel first.');\n }\n\n const chatId = `chat_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n\n this.chatSessions.set(chatId, {\n id: chatId,\n llm: this.llm,\n isActive: true,\n });\n\n return { id: chatId };\n }\n\n async sendMessage(options: { chatId: string; message: string }): Promise<void> {\n const session = this.chatSessions.get(options.chatId);\n if (!session) {\n throw new Error(`Chat session ${options.chatId} not found`);\n }\n\n if (!session.isActive) {\n throw new Error(`Chat session ${options.chatId} is not active`);\n }\n\n try {\n // Generate response using MediaPipe GenAI streaming API\n const response = session.llm.generateResponseStream(options.message);\n\n for await (const partialResponse of response) {\n // Send incremental text\n this.notifyListeners('textFromAi', {\n text: partialResponse,\n chatId: options.chatId,\n isChunk: true,\n } as TextFromAiEvent);\n }\n\n // Notify completion\n this.notifyListeners('aiFinished', {\n chatId: options.chatId,\n } as AiFinishedEvent);\n } catch (error) {\n console.error('Error generating response:', error);\n throw error;\n }\n }\n\n async setModel(options: ModelOptions): Promise<void> {\n try {\n // Update readiness\n this.readiness = 'loading';\n this.notifyListeners('readinessChange', { readiness: this.readiness } as ReadinessChangeEvent);\n\n // Create LLM configuration\n const config: any = {\n baseOptions: {\n modelAssetPath: options.path,\n },\n maxTokens: options.maxTokens || 2048,\n topK: options.topk || 40,\n temperature: options.temperature || 0.8,\n randomSeed: options.randomSeed || 0,\n };\n\n const genai = await FilesetResolver.forGenAiTasks(\n 'https://cdn.jsdelivr.net/npm/@mediapipe/tasks-genai@latest/wasm',\n );\n // Create LLM instance\n this.llm = await LlmInference.createFromOptions(genai, config);\n\n // Update readiness\n this.readiness = 'ready';\n this.notifyListeners('readinessChange', { readiness: this.readiness } as ReadinessChangeEvent);\n } catch (error) {\n this.readiness = 'error';\n this.notifyListeners('readinessChange', { readiness: this.readiness } as ReadinessChangeEvent);\n throw error;\n }\n }\n\n async downloadModel(options: DownloadModelOptions): Promise<DownloadModelResult> {\n try {\n // For web, we'll simulate download by fetching and storing in IndexedDB or returning the URL\n const response = await fetch(options.url, {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/octet-stream',\n },\n });\n\n if (!response.ok) {\n throw new Error(`Failed to download model: ${response.statusText}`);\n }\n\n const contentLength = response.headers.get('content-length');\n const totalBytes = contentLength ? parseInt(contentLength, 10) : undefined;\n\n // Read the response with progress\n const reader = response.body?.getReader();\n if (!reader) {\n throw new Error('Failed to get reader from response');\n }\n\n const chunks: Uint8Array[] = [];\n let downloadedBytes = 0;\n\n while (true) {\n const { done, value } = await reader.read();\n\n if (done) break;\n\n if (value) {\n chunks.push(value);\n downloadedBytes += value.length;\n }\n\n // Notify progress\n const progress = totalBytes ? (downloadedBytes / totalBytes) * 100 : 0;\n this.notifyListeners('downloadProgress', {\n progress,\n totalBytes,\n downloadedBytes,\n } as DownloadProgressEvent);\n }\n\n // For web, we'll return the original URL as the path\n // In a real implementation, you might want to store this in IndexedDB\n const result: DownloadModelResult = {\n path: options.url,\n };\n\n // Handle companion file if provided\n if (options.companionUrl) {\n // For web, just return the companion URL\n result.companionPath = options.companionUrl;\n }\n\n return result;\n } catch (error) {\n console.error('Error downloading model:', error);\n throw error;\n }\n }\n}\n"]}
@@ -0,0 +1,170 @@
1
+ 'use strict';
2
+
3
+ var core = require('@capacitor/core');
4
+ var tasksGenai = require('@mediapipe/tasks-genai');
5
+
6
+ const CapgoLLM = core.registerPlugin('CapgoLLM', {
7
+ web: () => Promise.resolve().then(function () { return web; }).then((m) => new m.CapgoLLMWeb()),
8
+ });
9
+
10
+ var __asyncValues = (globalThis && globalThis.__asyncValues) || function (o) {
11
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
12
+ var m = o[Symbol.asyncIterator], i;
13
+ return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
14
+ function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
15
+ function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
16
+ };
17
+ class CapgoLLMWeb extends core.WebPlugin {
18
+ constructor() {
19
+ super(...arguments);
20
+ this.llm = null;
21
+ this.chatSessions = new Map();
22
+ this.readiness = 'not-loaded';
23
+ }
24
+ async getReadiness() {
25
+ return { readiness: this.readiness };
26
+ }
27
+ async createChat() {
28
+ if (!this.llm) {
29
+ throw new Error('Model not loaded. Call setModel first.');
30
+ }
31
+ const chatId = `chat_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
32
+ this.chatSessions.set(chatId, {
33
+ id: chatId,
34
+ llm: this.llm,
35
+ isActive: true,
36
+ });
37
+ return { id: chatId };
38
+ }
39
+ async sendMessage(options) {
40
+ var e_1, _a;
41
+ const session = this.chatSessions.get(options.chatId);
42
+ if (!session) {
43
+ throw new Error(`Chat session ${options.chatId} not found`);
44
+ }
45
+ if (!session.isActive) {
46
+ throw new Error(`Chat session ${options.chatId} is not active`);
47
+ }
48
+ try {
49
+ // Generate response using MediaPipe GenAI streaming API
50
+ const response = session.llm.generateResponseStream(options.message);
51
+ try {
52
+ for (var response_1 = __asyncValues(response), response_1_1; response_1_1 = await response_1.next(), !response_1_1.done;) {
53
+ const partialResponse = response_1_1.value;
54
+ // Send incremental text
55
+ this.notifyListeners('textFromAi', {
56
+ text: partialResponse,
57
+ chatId: options.chatId,
58
+ isChunk: true,
59
+ });
60
+ }
61
+ }
62
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
63
+ finally {
64
+ try {
65
+ if (response_1_1 && !response_1_1.done && (_a = response_1.return)) await _a.call(response_1);
66
+ }
67
+ finally { if (e_1) throw e_1.error; }
68
+ }
69
+ // Notify completion
70
+ this.notifyListeners('aiFinished', {
71
+ chatId: options.chatId,
72
+ });
73
+ }
74
+ catch (error) {
75
+ console.error('Error generating response:', error);
76
+ throw error;
77
+ }
78
+ }
79
+ async setModel(options) {
80
+ try {
81
+ // Update readiness
82
+ this.readiness = 'loading';
83
+ this.notifyListeners('readinessChange', { readiness: this.readiness });
84
+ // Create LLM configuration
85
+ const config = {
86
+ baseOptions: {
87
+ modelAssetPath: options.path,
88
+ },
89
+ maxTokens: options.maxTokens || 2048,
90
+ topK: options.topk || 40,
91
+ temperature: options.temperature || 0.8,
92
+ randomSeed: options.randomSeed || 0,
93
+ };
94
+ const genai = await tasksGenai.FilesetResolver.forGenAiTasks('https://cdn.jsdelivr.net/npm/@mediapipe/tasks-genai@latest/wasm');
95
+ // Create LLM instance
96
+ this.llm = await tasksGenai.LlmInference.createFromOptions(genai, config);
97
+ // Update readiness
98
+ this.readiness = 'ready';
99
+ this.notifyListeners('readinessChange', { readiness: this.readiness });
100
+ }
101
+ catch (error) {
102
+ this.readiness = 'error';
103
+ this.notifyListeners('readinessChange', { readiness: this.readiness });
104
+ throw error;
105
+ }
106
+ }
107
+ async downloadModel(options) {
108
+ var _a;
109
+ try {
110
+ // For web, we'll simulate download by fetching and storing in IndexedDB or returning the URL
111
+ const response = await fetch(options.url, {
112
+ method: 'GET',
113
+ headers: {
114
+ 'Content-Type': 'application/octet-stream',
115
+ },
116
+ });
117
+ if (!response.ok) {
118
+ throw new Error(`Failed to download model: ${response.statusText}`);
119
+ }
120
+ const contentLength = response.headers.get('content-length');
121
+ const totalBytes = contentLength ? parseInt(contentLength, 10) : undefined;
122
+ // Read the response with progress
123
+ const reader = (_a = response.body) === null || _a === void 0 ? void 0 : _a.getReader();
124
+ if (!reader) {
125
+ throw new Error('Failed to get reader from response');
126
+ }
127
+ const chunks = [];
128
+ let downloadedBytes = 0;
129
+ while (true) {
130
+ const { done, value } = await reader.read();
131
+ if (done)
132
+ break;
133
+ if (value) {
134
+ chunks.push(value);
135
+ downloadedBytes += value.length;
136
+ }
137
+ // Notify progress
138
+ const progress = totalBytes ? (downloadedBytes / totalBytes) * 100 : 0;
139
+ this.notifyListeners('downloadProgress', {
140
+ progress,
141
+ totalBytes,
142
+ downloadedBytes,
143
+ });
144
+ }
145
+ // For web, we'll return the original URL as the path
146
+ // In a real implementation, you might want to store this in IndexedDB
147
+ const result = {
148
+ path: options.url,
149
+ };
150
+ // Handle companion file if provided
151
+ if (options.companionUrl) {
152
+ // For web, just return the companion URL
153
+ result.companionPath = options.companionUrl;
154
+ }
155
+ return result;
156
+ }
157
+ catch (error) {
158
+ console.error('Error downloading model:', error);
159
+ throw error;
160
+ }
161
+ }
162
+ }
163
+
164
+ var web = /*#__PURE__*/Object.freeze({
165
+ __proto__: null,
166
+ CapgoLLMWeb: CapgoLLMWeb
167
+ });
168
+
169
+ exports.CapgoLLM = CapgoLLM;
170
+ //# sourceMappingURL=plugin.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.cjs.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst CapgoLLM = registerPlugin('CapgoLLM', {\n web: () => import('./web').then((m) => new m.CapgoLLMWeb()),\n});\nexport * from './definitions';\nexport { CapgoLLM };\n//# sourceMappingURL=index.js.map","var __asyncValues = (this && this.__asyncValues) || function (o) {\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\n var m = o[Symbol.asyncIterator], i;\n return m ? m.call(o) : (o = typeof __values === \"function\" ? __values(o) : o[Symbol.iterator](), i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i);\n function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }\n function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }\n};\nimport { WebPlugin } from '@capacitor/core';\nimport { FilesetResolver, LlmInference } from '@mediapipe/tasks-genai';\nexport class CapgoLLMWeb extends WebPlugin {\n constructor() {\n super(...arguments);\n this.llm = null;\n this.chatSessions = new Map();\n this.readiness = 'not-loaded';\n }\n async getReadiness() {\n return { readiness: this.readiness };\n }\n async createChat() {\n if (!this.llm) {\n throw new Error('Model not loaded. Call setModel first.');\n }\n const chatId = `chat_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n this.chatSessions.set(chatId, {\n id: chatId,\n llm: this.llm,\n isActive: true,\n });\n return { id: chatId };\n }\n async sendMessage(options) {\n var e_1, _a;\n const session = this.chatSessions.get(options.chatId);\n if (!session) {\n throw new Error(`Chat session ${options.chatId} not found`);\n }\n if (!session.isActive) {\n throw new Error(`Chat session ${options.chatId} is not active`);\n }\n try {\n // Generate response using MediaPipe GenAI streaming API\n const response = session.llm.generateResponseStream(options.message);\n try {\n for (var response_1 = __asyncValues(response), response_1_1; response_1_1 = await response_1.next(), !response_1_1.done;) {\n const partialResponse = response_1_1.value;\n // Send incremental text\n this.notifyListeners('textFromAi', {\n text: partialResponse,\n chatId: options.chatId,\n isChunk: true,\n });\n }\n }\n catch (e_1_1) { e_1 = { error: e_1_1 }; }\n finally {\n try {\n if (response_1_1 && !response_1_1.done && (_a = response_1.return)) await _a.call(response_1);\n }\n finally { if (e_1) throw e_1.error; }\n }\n // Notify completion\n this.notifyListeners('aiFinished', {\n chatId: options.chatId,\n });\n }\n catch (error) {\n console.error('Error generating response:', error);\n throw error;\n }\n }\n async setModel(options) {\n try {\n // Update readiness\n this.readiness = 'loading';\n this.notifyListeners('readinessChange', { readiness: this.readiness });\n // Create LLM configuration\n const config = {\n baseOptions: {\n modelAssetPath: options.path,\n },\n maxTokens: options.maxTokens || 2048,\n topK: options.topk || 40,\n temperature: options.temperature || 0.8,\n randomSeed: options.randomSeed || 0,\n };\n const genai = await FilesetResolver.forGenAiTasks('https://cdn.jsdelivr.net/npm/@mediapipe/tasks-genai@latest/wasm');\n // Create LLM instance\n this.llm = await LlmInference.createFromOptions(genai, config);\n // Update readiness\n this.readiness = 'ready';\n this.notifyListeners('readinessChange', { readiness: this.readiness });\n }\n catch (error) {\n this.readiness = 'error';\n this.notifyListeners('readinessChange', { readiness: this.readiness });\n throw error;\n }\n }\n async downloadModel(options) {\n var _a;\n try {\n // For web, we'll simulate download by fetching and storing in IndexedDB or returning the URL\n const response = await fetch(options.url, {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/octet-stream',\n },\n });\n if (!response.ok) {\n throw new Error(`Failed to download model: ${response.statusText}`);\n }\n const contentLength = response.headers.get('content-length');\n const totalBytes = contentLength ? parseInt(contentLength, 10) : undefined;\n // Read the response with progress\n const reader = (_a = response.body) === null || _a === void 0 ? void 0 : _a.getReader();\n if (!reader) {\n throw new Error('Failed to get reader from response');\n }\n const chunks = [];\n let downloadedBytes = 0;\n while (true) {\n const { done, value } = await reader.read();\n if (done)\n break;\n if (value) {\n chunks.push(value);\n downloadedBytes += value.length;\n }\n // Notify progress\n const progress = totalBytes ? (downloadedBytes / totalBytes) * 100 : 0;\n this.notifyListeners('downloadProgress', {\n progress,\n totalBytes,\n downloadedBytes,\n });\n }\n // For web, we'll return the original URL as the path\n // In a real implementation, you might want to store this in IndexedDB\n const result = {\n path: options.url,\n };\n // Handle companion file if provided\n if (options.companionUrl) {\n // For web, just return the companion URL\n result.companionPath = options.companionUrl;\n }\n return result;\n }\n catch (error) {\n console.error('Error downloading model:', error);\n throw error;\n }\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","this","WebPlugin","FilesetResolver","LlmInference"],"mappings":"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"}
package/dist/plugin.js ADDED
@@ -0,0 +1,172 @@
1
+ var capacitorLLM = (function (exports, core, tasksGenai) {
2
+ 'use strict';
3
+
4
+ const CapgoLLM = core.registerPlugin('CapgoLLM', {
5
+ web: () => Promise.resolve().then(function () { return web; }).then((m) => new m.CapgoLLMWeb()),
6
+ });
7
+
8
+ var __asyncValues = (globalThis && globalThis.__asyncValues) || function (o) {
9
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
10
+ var m = o[Symbol.asyncIterator], i;
11
+ return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
12
+ function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
13
+ function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
14
+ };
15
+ class CapgoLLMWeb extends core.WebPlugin {
16
+ constructor() {
17
+ super(...arguments);
18
+ this.llm = null;
19
+ this.chatSessions = new Map();
20
+ this.readiness = 'not-loaded';
21
+ }
22
+ async getReadiness() {
23
+ return { readiness: this.readiness };
24
+ }
25
+ async createChat() {
26
+ if (!this.llm) {
27
+ throw new Error('Model not loaded. Call setModel first.');
28
+ }
29
+ const chatId = `chat_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
30
+ this.chatSessions.set(chatId, {
31
+ id: chatId,
32
+ llm: this.llm,
33
+ isActive: true,
34
+ });
35
+ return { id: chatId };
36
+ }
37
+ async sendMessage(options) {
38
+ var e_1, _a;
39
+ const session = this.chatSessions.get(options.chatId);
40
+ if (!session) {
41
+ throw new Error(`Chat session ${options.chatId} not found`);
42
+ }
43
+ if (!session.isActive) {
44
+ throw new Error(`Chat session ${options.chatId} is not active`);
45
+ }
46
+ try {
47
+ // Generate response using MediaPipe GenAI streaming API
48
+ const response = session.llm.generateResponseStream(options.message);
49
+ try {
50
+ for (var response_1 = __asyncValues(response), response_1_1; response_1_1 = await response_1.next(), !response_1_1.done;) {
51
+ const partialResponse = response_1_1.value;
52
+ // Send incremental text
53
+ this.notifyListeners('textFromAi', {
54
+ text: partialResponse,
55
+ chatId: options.chatId,
56
+ isChunk: true,
57
+ });
58
+ }
59
+ }
60
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
61
+ finally {
62
+ try {
63
+ if (response_1_1 && !response_1_1.done && (_a = response_1.return)) await _a.call(response_1);
64
+ }
65
+ finally { if (e_1) throw e_1.error; }
66
+ }
67
+ // Notify completion
68
+ this.notifyListeners('aiFinished', {
69
+ chatId: options.chatId,
70
+ });
71
+ }
72
+ catch (error) {
73
+ console.error('Error generating response:', error);
74
+ throw error;
75
+ }
76
+ }
77
+ async setModel(options) {
78
+ try {
79
+ // Update readiness
80
+ this.readiness = 'loading';
81
+ this.notifyListeners('readinessChange', { readiness: this.readiness });
82
+ // Create LLM configuration
83
+ const config = {
84
+ baseOptions: {
85
+ modelAssetPath: options.path,
86
+ },
87
+ maxTokens: options.maxTokens || 2048,
88
+ topK: options.topk || 40,
89
+ temperature: options.temperature || 0.8,
90
+ randomSeed: options.randomSeed || 0,
91
+ };
92
+ const genai = await tasksGenai.FilesetResolver.forGenAiTasks('https://cdn.jsdelivr.net/npm/@mediapipe/tasks-genai@latest/wasm');
93
+ // Create LLM instance
94
+ this.llm = await tasksGenai.LlmInference.createFromOptions(genai, config);
95
+ // Update readiness
96
+ this.readiness = 'ready';
97
+ this.notifyListeners('readinessChange', { readiness: this.readiness });
98
+ }
99
+ catch (error) {
100
+ this.readiness = 'error';
101
+ this.notifyListeners('readinessChange', { readiness: this.readiness });
102
+ throw error;
103
+ }
104
+ }
105
+ async downloadModel(options) {
106
+ var _a;
107
+ try {
108
+ // For web, we'll simulate download by fetching and storing in IndexedDB or returning the URL
109
+ const response = await fetch(options.url, {
110
+ method: 'GET',
111
+ headers: {
112
+ 'Content-Type': 'application/octet-stream',
113
+ },
114
+ });
115
+ if (!response.ok) {
116
+ throw new Error(`Failed to download model: ${response.statusText}`);
117
+ }
118
+ const contentLength = response.headers.get('content-length');
119
+ const totalBytes = contentLength ? parseInt(contentLength, 10) : undefined;
120
+ // Read the response with progress
121
+ const reader = (_a = response.body) === null || _a === void 0 ? void 0 : _a.getReader();
122
+ if (!reader) {
123
+ throw new Error('Failed to get reader from response');
124
+ }
125
+ const chunks = [];
126
+ let downloadedBytes = 0;
127
+ while (true) {
128
+ const { done, value } = await reader.read();
129
+ if (done)
130
+ break;
131
+ if (value) {
132
+ chunks.push(value);
133
+ downloadedBytes += value.length;
134
+ }
135
+ // Notify progress
136
+ const progress = totalBytes ? (downloadedBytes / totalBytes) * 100 : 0;
137
+ this.notifyListeners('downloadProgress', {
138
+ progress,
139
+ totalBytes,
140
+ downloadedBytes,
141
+ });
142
+ }
143
+ // For web, we'll return the original URL as the path
144
+ // In a real implementation, you might want to store this in IndexedDB
145
+ const result = {
146
+ path: options.url,
147
+ };
148
+ // Handle companion file if provided
149
+ if (options.companionUrl) {
150
+ // For web, just return the companion URL
151
+ result.companionPath = options.companionUrl;
152
+ }
153
+ return result;
154
+ }
155
+ catch (error) {
156
+ console.error('Error downloading model:', error);
157
+ throw error;
158
+ }
159
+ }
160
+ }
161
+
162
+ var web = /*#__PURE__*/Object.freeze({
163
+ __proto__: null,
164
+ CapgoLLMWeb: CapgoLLMWeb
165
+ });
166
+
167
+ exports.CapgoLLM = CapgoLLM;
168
+
169
+ return exports;
170
+
171
+ })({}, capacitorExports, MediaPipeTasksGenAI);
172
+ //# sourceMappingURL=plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst CapgoLLM = registerPlugin('CapgoLLM', {\n web: () => import('./web').then((m) => new m.CapgoLLMWeb()),\n});\nexport * from './definitions';\nexport { CapgoLLM };\n//# sourceMappingURL=index.js.map","var __asyncValues = (this && this.__asyncValues) || function (o) {\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\n var m = o[Symbol.asyncIterator], i;\n return m ? m.call(o) : (o = typeof __values === \"function\" ? __values(o) : o[Symbol.iterator](), i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i);\n function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }\n function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }\n};\nimport { WebPlugin } from '@capacitor/core';\nimport { FilesetResolver, LlmInference } from '@mediapipe/tasks-genai';\nexport class CapgoLLMWeb extends WebPlugin {\n constructor() {\n super(...arguments);\n this.llm = null;\n this.chatSessions = new Map();\n this.readiness = 'not-loaded';\n }\n async getReadiness() {\n return { readiness: this.readiness };\n }\n async createChat() {\n if (!this.llm) {\n throw new Error('Model not loaded. Call setModel first.');\n }\n const chatId = `chat_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n this.chatSessions.set(chatId, {\n id: chatId,\n llm: this.llm,\n isActive: true,\n });\n return { id: chatId };\n }\n async sendMessage(options) {\n var e_1, _a;\n const session = this.chatSessions.get(options.chatId);\n if (!session) {\n throw new Error(`Chat session ${options.chatId} not found`);\n }\n if (!session.isActive) {\n throw new Error(`Chat session ${options.chatId} is not active`);\n }\n try {\n // Generate response using MediaPipe GenAI streaming API\n const response = session.llm.generateResponseStream(options.message);\n try {\n for (var response_1 = __asyncValues(response), response_1_1; response_1_1 = await response_1.next(), !response_1_1.done;) {\n const partialResponse = response_1_1.value;\n // Send incremental text\n this.notifyListeners('textFromAi', {\n text: partialResponse,\n chatId: options.chatId,\n isChunk: true,\n });\n }\n }\n catch (e_1_1) { e_1 = { error: e_1_1 }; }\n finally {\n try {\n if (response_1_1 && !response_1_1.done && (_a = response_1.return)) await _a.call(response_1);\n }\n finally { if (e_1) throw e_1.error; }\n }\n // Notify completion\n this.notifyListeners('aiFinished', {\n chatId: options.chatId,\n });\n }\n catch (error) {\n console.error('Error generating response:', error);\n throw error;\n }\n }\n async setModel(options) {\n try {\n // Update readiness\n this.readiness = 'loading';\n this.notifyListeners('readinessChange', { readiness: this.readiness });\n // Create LLM configuration\n const config = {\n baseOptions: {\n modelAssetPath: options.path,\n },\n maxTokens: options.maxTokens || 2048,\n topK: options.topk || 40,\n temperature: options.temperature || 0.8,\n randomSeed: options.randomSeed || 0,\n };\n const genai = await FilesetResolver.forGenAiTasks('https://cdn.jsdelivr.net/npm/@mediapipe/tasks-genai@latest/wasm');\n // Create LLM instance\n this.llm = await LlmInference.createFromOptions(genai, config);\n // Update readiness\n this.readiness = 'ready';\n this.notifyListeners('readinessChange', { readiness: this.readiness });\n }\n catch (error) {\n this.readiness = 'error';\n this.notifyListeners('readinessChange', { readiness: this.readiness });\n throw error;\n }\n }\n async downloadModel(options) {\n var _a;\n try {\n // For web, we'll simulate download by fetching and storing in IndexedDB or returning the URL\n const response = await fetch(options.url, {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/octet-stream',\n },\n });\n if (!response.ok) {\n throw new Error(`Failed to download model: ${response.statusText}`);\n }\n const contentLength = response.headers.get('content-length');\n const totalBytes = contentLength ? parseInt(contentLength, 10) : undefined;\n // Read the response with progress\n const reader = (_a = response.body) === null || _a === void 0 ? void 0 : _a.getReader();\n if (!reader) {\n throw new Error('Failed to get reader from response');\n }\n const chunks = [];\n let downloadedBytes = 0;\n while (true) {\n const { done, value } = await reader.read();\n if (done)\n break;\n if (value) {\n chunks.push(value);\n downloadedBytes += value.length;\n }\n // Notify progress\n const progress = totalBytes ? (downloadedBytes / totalBytes) * 100 : 0;\n this.notifyListeners('downloadProgress', {\n progress,\n totalBytes,\n downloadedBytes,\n });\n }\n // For web, we'll return the original URL as the path\n // In a real implementation, you might want to store this in IndexedDB\n const result = {\n path: options.url,\n };\n // Handle companion file if provided\n if (options.companionUrl) {\n // For web, just return the companion URL\n result.companionPath = options.companionUrl;\n }\n return result;\n }\n catch (error) {\n console.error('Error downloading model:', error);\n throw error;\n }\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","this","WebPlugin","FilesetResolver","LlmInference"],"mappings":"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"}