@capgo/capacitor-llm 8.0.19 → 8.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.
@@ -1 +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 const engine = options.engine ?? 'auto';\n const normalizedPath = options.path.toLowerCase();\n const wantsApple = engine === 'apple' || (engine === 'auto' && normalizedPath === 'apple intelligence');\n const wantsExecuTorch =\n engine === 'executorch' || (engine === 'auto' && (options.tokenizerPath || normalizedPath.endsWith('.pte')));\n\n if (wantsApple) {\n throw new Error('Apple Intelligence is only available on native iOS.');\n }\n\n if (wantsExecuTorch) {\n throw new Error('ExecuTorch is only available on native iOS and Android.');\n }\n\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 async getPluginVersion(): Promise<{ version: string }> {\n return { version: 'web' };\n }\n}\n"]}
1
+ {"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AA4BvE,MAAM,OAAO,WAAY,SAAQ,SAAS;IAA1C;;QACU,QAAG,GAAwB,IAAI,CAAC;QAChC,iBAAY,GAA6B,IAAI,GAAG,EAAE,CAAC;QACnD,cAAS,GAAG,YAAY,CAAC;QACzB,cAAS,GAAG,EAAE,CAAC;QACf,cAAS,GAAG,MAAM,CAAC;IAmO7B,CAAC;IAjOC,KAAK,CAAC,YAAY;QAChB,OAAO,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC;IACvC,CAAC;IAED,KAAK,CAAC,UAAU;QACd,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;YACd,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;QAC5D,CAAC;QAED,MAAM,MAAM,GAAG,QAAQ,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;QAE/E,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,EAAE;YAC5B,EAAE,EAAE,MAAM;YACV,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,QAAQ,EAAE,IAAI;YACd,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,OAAO,EAAE,EAAE;SACZ,CAAC,CAAC;QAEH,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC;IACxB,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,OAA4C;QAC5D,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACtD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,gBAAgB,OAAO,CAAC,MAAM,YAAY,CAAC,CAAC;QAC9D,CAAC;QAED,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;YACtB,MAAM,IAAI,KAAK,CAAC,gBAAgB,OAAO,CAAC,MAAM,gBAAgB,CAAC,CAAC;QAClE,CAAC;QAED,IAAI,WAAW,GAAG,KAAK,CAAC;QACxB,IAAI,YAAY,GAAG,EAAE,CAAC;QAEtB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;YAE1D,MAAM,aAAa,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,MAAM,EAAE,CAAC,eAAe,EAAE,IAAI,EAAE,EAAE;gBACzF,IAAI,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;oBAC7B,OAAO;gBACT,CAAC;gBAED,WAAW,GAAG,IAAI,CAAC;gBACnB,YAAY,IAAI,eAAe,CAAC;gBAEhC,IAAI,CAAC,eAAe,CAAC,YAAY,EAAE;oBACjC,IAAI,EAAE,eAAe;oBACrB,MAAM,EAAE,OAAO,CAAC,MAAM;oBACtB,OAAO,EAAE,IAAI;iBACK,CAAC,CAAC;YACxB,CAAC,CAAC,CAAC;YAEH,IAAI,CAAC,WAAW,IAAI,aAAa,EAAE,CAAC;gBAClC,YAAY,GAAG,aAAa,CAAC;gBAC7B,IAAI,CAAC,eAAe,CAAC,YAAY,EAAE;oBACjC,IAAI,EAAE,aAAa;oBACnB,MAAM,EAAE,OAAO,CAAC,MAAM;oBACtB,OAAO,EAAE,IAAI;iBACK,CAAC,CAAC;YACxB,CAAC;YAED,OAAO,CAAC,OAAO,CAAC,IAAI,CAClB,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,EAC1C,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,IAAI,aAAa,EAAE,CAC1D,CAAC;YAEF,oBAAoB;YACpB,IAAI,CAAC,eAAe,CAAC,YAAY,EAAE;gBACjC,MAAM,EAAE,OAAO,CAAC,MAAM;aACJ,CAAC,CAAC;QACxB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,4BAA4B,EAAE,KAAK,CAAC,CAAC;YACnD,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACvE,IAAI,WAAW,EAAE,CAAC;gBAChB,IAAI,CAAC,eAAe,CAAC,iBAAiB,EAAE;oBACtC,MAAM,EAAE,OAAO,CAAC,MAAM;oBACtB,KAAK,EAAE,OAAO;iBACS,CAAC,CAAC;gBAC3B,OAAO;YACT,CAAC;YAED,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,OAAqB;QAClC,IAAI,CAAC;YACH,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAEzB,mBAAmB;YACnB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;YAC3B,IAAI,CAAC,eAAe,CAAC,iBAAiB,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAA0B,CAAC,CAAC;YAE/F,2BAA2B;YAC3B,MAAM,MAAM,GAAQ;gBAClB,WAAW,EAAE;oBACX,cAAc,EAAE,OAAO,CAAC,IAAI;iBAC7B;gBACD,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,IAAI;gBACpC,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,EAAE;gBACxB,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,GAAG;gBACvC,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,CAAC;aACpC,CAAC;YAEF,MAAM,KAAK,GAAG,MAAM,eAAe,CAAC,aAAa,CAC/C,iEAAiE,CAClE,CAAC;YACF,sBAAsB;YACtB,IAAI,CAAC,GAAG,GAAG,MAAM,YAAY,CAAC,iBAAiB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;YAC/D,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;YAC9B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;YAChD,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC;YAE1B,mBAAmB;YACnB,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC;YACzB,IAAI,CAAC,eAAe,CAAC,iBAAiB,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAA0B,CAAC,CAAC;QACjG,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACzB,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC;YACzB,IAAI,CAAC,eAAe,CAAC,iBAAiB,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAA0B,CAAC,CAAC;YAC/F,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,OAA6B;;QAC/C,IAAI,CAAC;YACH,6FAA6F;YAC7F,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE;gBACxC,MAAM,EAAE,KAAK;gBACb,OAAO,EAAE;oBACP,cAAc,EAAE,0BAA0B;iBAC3C;aACF,CAAC,CAAC;YAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,IAAI,KAAK,CAAC,6BAA6B,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;YACtE,CAAC;YAED,MAAM,aAAa,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;YAC7D,MAAM,UAAU,GAAG,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YAE3E,kCAAkC;YAClC,MAAM,MAAM,GAAG,MAAA,QAAQ,CAAC,IAAI,0CAAE,SAAS,EAAE,CAAC;YAC1C,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;YACxD,CAAC;YAED,MAAM,MAAM,GAAiB,EAAE,CAAC;YAChC,IAAI,eAAe,GAAG,CAAC,CAAC;YAExB,OAAO,IAAI,EAAE,CAAC;gBACZ,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;gBAE5C,IAAI,IAAI;oBAAE,MAAM;gBAEhB,IAAI,KAAK,EAAE,CAAC;oBACV,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;oBACnB,eAAe,IAAI,KAAK,CAAC,MAAM,CAAC;gBAClC,CAAC;gBAED,kBAAkB;gBAClB,MAAM,QAAQ,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,eAAe,GAAG,UAAU,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;gBACvE,IAAI,CAAC,eAAe,CAAC,kBAAkB,EAAE;oBACvC,QAAQ;oBACR,UAAU;oBACV,eAAe;iBACS,CAAC,CAAC;YAC9B,CAAC;YAED,qDAAqD;YACrD,sEAAsE;YACtE,MAAM,MAAM,GAAwB;gBAClC,IAAI,EAAE,OAAO,CAAC,GAAG;aAClB,CAAC;YAEF,oCAAoC;YACpC,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;gBACzB,yCAAyC;gBACzC,MAAM,CAAC,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;YAC9C,CAAC;YAED,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,0BAA0B,EAAE,KAAK,CAAC,CAAC;YACjD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED,KAAK,CAAC,gBAAgB;QACpB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC5B,CAAC;IAEO,iBAAiB;;QACvB,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC;QAC1B,MAAA,IAAI,CAAC,GAAG,0CAAE,KAAK,EAAE,CAAC;QAClB,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC;QAChB,IAAI,CAAC,SAAS,GAAG,EAAE,CAAC;QACpB,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC;IAC1B,CAAC;IAEO,gBAAgB,CAAC,OAAqB;;QAC5C,IAAI,MAAA,OAAO,CAAC,SAAS,0CAAE,IAAI,EAAE,EAAE,CAAC;YAC9B,OAAO,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAChD,CAAC;QAED,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;QAChD,OAAO,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;IACtD,CAAC;IAEO,WAAW,CAAC,OAAoB,EAAE,OAAe;QACvD,IAAI,CAAC,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC,EAAE,CAAC;YACzC,OAAO,OAAO,CAAC;QACjB,CAAC;QAED,MAAM,OAAO,GAAG,CAAC,GAAG,OAAO,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,MAAe,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;QAClF,OAAO,GAAG,OAAO;aACd,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,kBAAkB,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,OAAO,eAAe,CAAC;aAC1E,IAAI,CAAC,IAAI,CAAC,0BAA0B,CAAC;IAC1C,CAAC;IAEO,qBAAqB,CAAC,OAAoB;QAChD,OAAO,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,OAAO,CAAC,SAAS,KAAK,UAAU,CAAC;IAC9E,CAAC;CACF","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 GenerationErrorEvent,\n DownloadProgressEvent,\n ReadinessChangeEvent,\n} from './definitions';\n\ninterface ChatTurn {\n role: 'user' | 'model';\n content: string;\n}\n\ninterface ChatSession {\n id: string;\n llm: LlmInference;\n isActive: boolean;\n modelPath: string;\n modelType: string;\n history: ChatTurn[];\n}\n\nexport class CapgoLLMWeb extends WebPlugin implements LLMPlugin {\n private llm: LlmInference | null = null;\n private chatSessions: Map<string, ChatSession> = new Map();\n private readiness = 'not-loaded';\n private modelPath = '';\n private modelType = 'task';\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 modelPath: this.modelPath,\n modelType: this.modelType,\n history: [],\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 let hasStreamed = false;\n let responseText = '';\n\n try {\n const prompt = this.buildPrompt(session, options.message);\n\n const finalResponse = await session.llm.generateResponse(prompt, (partialResponse, done) => {\n if (done || !partialResponse) {\n return;\n }\n\n hasStreamed = true;\n responseText += partialResponse;\n\n this.notifyListeners('textFromAi', {\n text: partialResponse,\n chatId: options.chatId,\n isChunk: true,\n } as TextFromAiEvent);\n });\n\n if (!hasStreamed && finalResponse) {\n responseText = finalResponse;\n this.notifyListeners('textFromAi', {\n text: finalResponse,\n chatId: options.chatId,\n isChunk: true,\n } as TextFromAiEvent);\n }\n\n session.history.push(\n { role: 'user', content: options.message },\n { role: 'model', content: responseText || finalResponse },\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 const message = error instanceof Error ? error.message : String(error);\n if (hasStreamed) {\n this.notifyListeners('generationError', {\n chatId: options.chatId,\n error: message,\n } as GenerationErrorEvent);\n return;\n }\n\n throw error;\n }\n }\n\n async setModel(options: ModelOptions): Promise<void> {\n try {\n this.closeCurrentModel();\n\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 this.modelPath = options.path;\n this.modelType = this.resolveModelType(options);\n this.chatSessions.clear();\n\n // Update readiness\n this.readiness = 'ready';\n this.notifyListeners('readinessChange', { readiness: this.readiness } as ReadinessChangeEvent);\n } catch (error) {\n this.closeCurrentModel();\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 async getPluginVersion(): Promise<{ version: string }> {\n return { version: 'web' };\n }\n\n private closeCurrentModel(): void {\n this.chatSessions.clear();\n this.llm?.close();\n this.llm = null;\n this.modelPath = '';\n this.modelType = 'task';\n }\n\n private resolveModelType(options: ModelOptions): string {\n if (options.modelType?.trim()) {\n return options.modelType.trim().toLowerCase();\n }\n\n const extension = options.path.split('.').pop();\n return extension ? extension.toLowerCase() : 'task';\n }\n\n private buildPrompt(session: ChatSession, message: string): string {\n if (!this.usesGemmaChatTemplate(session)) {\n return message;\n }\n\n const history = [...session.history, { role: 'user' as const, content: message }];\n return `${history\n .map((turn) => `<start_of_turn>${turn.role}\\n${turn.content}<end_of_turn>`)\n .join('\\n')}\\n<start_of_turn>model\\n`;\n }\n\n private usesGemmaChatTemplate(session: ChatSession): boolean {\n return /gemma/i.test(session.modelPath) || session.modelType === 'litertlm';\n }\n}\n"]}
@@ -7,19 +7,14 @@ const CapgoLLM = core.registerPlugin('CapgoLLM', {
7
7
  web: () => Promise.resolve().then(function () { return web; }).then((m) => new m.CapgoLLMWeb()),
8
8
  });
9
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
10
  class CapgoLLMWeb extends core.WebPlugin {
18
11
  constructor() {
19
12
  super(...arguments);
20
13
  this.llm = null;
21
14
  this.chatSessions = new Map();
22
15
  this.readiness = 'not-loaded';
16
+ this.modelPath = '';
17
+ this.modelType = 'task';
23
18
  }
24
19
  async getReadiness() {
25
20
  return { readiness: this.readiness };
@@ -33,11 +28,13 @@ class CapgoLLMWeb extends core.WebPlugin {
33
28
  id: chatId,
34
29
  llm: this.llm,
35
30
  isActive: true,
31
+ modelPath: this.modelPath,
32
+ modelType: this.modelType,
33
+ history: [],
36
34
  });
37
35
  return { id: chatId };
38
36
  }
39
37
  async sendMessage(options) {
40
- var _a, e_1, _b, _c;
41
38
  const session = this.chatSessions.get(options.chatId);
42
39
  if (!session) {
43
40
  throw new Error(`Chat session ${options.chatId} not found`);
@@ -45,29 +42,31 @@ class CapgoLLMWeb extends core.WebPlugin {
45
42
  if (!session.isActive) {
46
43
  throw new Error(`Chat session ${options.chatId} is not active`);
47
44
  }
45
+ let hasStreamed = false;
46
+ let responseText = '';
48
47
  try {
49
- // Generate response using MediaPipe GenAI streaming API
50
- const response = session.llm.generateResponseStream(options.message);
51
- try {
52
- for (var _d = true, response_1 = __asyncValues(response), response_1_1; response_1_1 = await response_1.next(), _a = response_1_1.done, !_a; _d = true) {
53
- _c = response_1_1.value;
54
- _d = false;
55
- const partialResponse = _c;
56
- // Send incremental text
57
- this.notifyListeners('textFromAi', {
58
- text: partialResponse,
59
- chatId: options.chatId,
60
- isChunk: true,
61
- });
48
+ const prompt = this.buildPrompt(session, options.message);
49
+ const finalResponse = await session.llm.generateResponse(prompt, (partialResponse, done) => {
50
+ if (done || !partialResponse) {
51
+ return;
62
52
  }
53
+ hasStreamed = true;
54
+ responseText += partialResponse;
55
+ this.notifyListeners('textFromAi', {
56
+ text: partialResponse,
57
+ chatId: options.chatId,
58
+ isChunk: true,
59
+ });
60
+ });
61
+ if (!hasStreamed && finalResponse) {
62
+ responseText = finalResponse;
63
+ this.notifyListeners('textFromAi', {
64
+ text: finalResponse,
65
+ chatId: options.chatId,
66
+ isChunk: true,
67
+ });
63
68
  }
64
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
65
- finally {
66
- try {
67
- if (!_d && !_a && (_b = response_1.return)) await _b.call(response_1);
68
- }
69
- finally { if (e_1) throw e_1.error; }
70
- }
69
+ session.history.push({ role: 'user', content: options.message }, { role: 'model', content: responseText || finalResponse });
71
70
  // Notify completion
72
71
  this.notifyListeners('aiFinished', {
73
72
  chatId: options.chatId,
@@ -75,22 +74,20 @@ class CapgoLLMWeb extends core.WebPlugin {
75
74
  }
76
75
  catch (error) {
77
76
  console.error('Error generating response:', error);
77
+ const message = error instanceof Error ? error.message : String(error);
78
+ if (hasStreamed) {
79
+ this.notifyListeners('generationError', {
80
+ chatId: options.chatId,
81
+ error: message,
82
+ });
83
+ return;
84
+ }
78
85
  throw error;
79
86
  }
80
87
  }
81
88
  async setModel(options) {
82
- var _a;
83
- const engine = (_a = options.engine) !== null && _a !== void 0 ? _a : 'auto';
84
- const normalizedPath = options.path.toLowerCase();
85
- const wantsApple = engine === 'apple' || (engine === 'auto' && normalizedPath === 'apple intelligence');
86
- const wantsExecuTorch = engine === 'executorch' || (engine === 'auto' && (options.tokenizerPath || normalizedPath.endsWith('.pte')));
87
- if (wantsApple) {
88
- throw new Error('Apple Intelligence is only available on native iOS.');
89
- }
90
- if (wantsExecuTorch) {
91
- throw new Error('ExecuTorch is only available on native iOS and Android.');
92
- }
93
89
  try {
90
+ this.closeCurrentModel();
94
91
  // Update readiness
95
92
  this.readiness = 'loading';
96
93
  this.notifyListeners('readinessChange', { readiness: this.readiness });
@@ -107,11 +104,15 @@ class CapgoLLMWeb extends core.WebPlugin {
107
104
  const genai = await tasksGenai.FilesetResolver.forGenAiTasks('https://cdn.jsdelivr.net/npm/@mediapipe/tasks-genai@latest/wasm');
108
105
  // Create LLM instance
109
106
  this.llm = await tasksGenai.LlmInference.createFromOptions(genai, config);
107
+ this.modelPath = options.path;
108
+ this.modelType = this.resolveModelType(options);
109
+ this.chatSessions.clear();
110
110
  // Update readiness
111
111
  this.readiness = 'ready';
112
112
  this.notifyListeners('readinessChange', { readiness: this.readiness });
113
113
  }
114
114
  catch (error) {
115
+ this.closeCurrentModel();
115
116
  this.readiness = 'error';
116
117
  this.notifyListeners('readinessChange', { readiness: this.readiness });
117
118
  throw error;
@@ -175,6 +176,34 @@ class CapgoLLMWeb extends core.WebPlugin {
175
176
  async getPluginVersion() {
176
177
  return { version: 'web' };
177
178
  }
179
+ closeCurrentModel() {
180
+ var _a;
181
+ this.chatSessions.clear();
182
+ (_a = this.llm) === null || _a === void 0 ? void 0 : _a.close();
183
+ this.llm = null;
184
+ this.modelPath = '';
185
+ this.modelType = 'task';
186
+ }
187
+ resolveModelType(options) {
188
+ var _a;
189
+ if ((_a = options.modelType) === null || _a === void 0 ? void 0 : _a.trim()) {
190
+ return options.modelType.trim().toLowerCase();
191
+ }
192
+ const extension = options.path.split('.').pop();
193
+ return extension ? extension.toLowerCase() : 'task';
194
+ }
195
+ buildPrompt(session, message) {
196
+ if (!this.usesGemmaChatTemplate(session)) {
197
+ return message;
198
+ }
199
+ const history = [...session.history, { role: 'user', content: message }];
200
+ return `${history
201
+ .map((turn) => `<start_of_turn>${turn.role}\n${turn.content}<end_of_turn>`)
202
+ .join('\n')}\n<start_of_turn>model\n`;
203
+ }
204
+ usesGemmaChatTemplate(session) {
205
+ return /gemma/i.test(session.modelPath) || session.modelType === 'litertlm';
206
+ }
178
207
  }
179
208
 
180
209
  var web = /*#__PURE__*/Object.freeze({
@@ -1 +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 _a, e_1, _b, _c;\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 _d = true, response_1 = __asyncValues(response), response_1_1; response_1_1 = await response_1.next(), _a = response_1_1.done, !_a; _d = true) {\n _c = response_1_1.value;\n _d = false;\n const partialResponse = _c;\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 (!_d && !_a && (_b = response_1.return)) await _b.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 var _a;\n const engine = (_a = options.engine) !== null && _a !== void 0 ? _a : 'auto';\n const normalizedPath = options.path.toLowerCase();\n const wantsApple = engine === 'apple' || (engine === 'auto' && normalizedPath === 'apple intelligence');\n const wantsExecuTorch = engine === 'executorch' || (engine === 'auto' && (options.tokenizerPath || normalizedPath.endsWith('.pte')));\n if (wantsApple) {\n throw new Error('Apple Intelligence is only available on native iOS.');\n }\n if (wantsExecuTorch) {\n throw new Error('ExecuTorch is only available on native iOS and Android.');\n }\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 async getPluginVersion() {\n return { version: 'web' };\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","this","WebPlugin","FilesetResolver","LlmInference"],"mappings":";;;;;AACK,MAAC,QAAQ,GAAGA,mBAAc,CAAC,UAAU,EAAE;AAC5C,IAAI,GAAG,EAAE,MAAM,mDAAe,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;AAC/D,CAAC;;ACHD,IAAI,aAAa,GAAG,CAACC,UAAI,IAAIA,UAAI,CAAC,aAAa,KAAK,UAAU,CAAC,EAAE;AACjE,IAAI,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,MAAM,IAAI,SAAS,CAAC,sCAAsC,CAAC;AAC1F,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC;AACtC,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,OAAO,QAAQ,KAAK,UAAU,GAAG,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC,GAAG,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,GAAG,YAAY,EAAE,OAAO,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AACpN,IAAI,SAAS,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,EAAE,EAAE,OAAO,IAAI,OAAO,CAAC,UAAU,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACnK,IAAI,SAAS,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;AAC/H,CAAC;AAGM,MAAM,WAAW,SAASC,cAAS,CAAC;AAC3C,IAAI,WAAW,GAAG;AAClB,QAAQ,KAAK,CAAC,GAAG,SAAS,CAAC;AAC3B,QAAQ,IAAI,CAAC,GAAG,GAAG,IAAI;AACvB,QAAQ,IAAI,CAAC,YAAY,GAAG,IAAI,GAAG,EAAE;AACrC,QAAQ,IAAI,CAAC,SAAS,GAAG,YAAY;AACrC,IAAI;AACJ,IAAI,MAAM,YAAY,GAAG;AACzB,QAAQ,OAAO,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE;AAC5C,IAAI;AACJ,IAAI,MAAM,UAAU,GAAG;AACvB,QAAQ,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE;AACvB,YAAY,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC;AACrE,QAAQ;AACR,QAAQ,MAAM,MAAM,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AACtF,QAAQ,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,EAAE;AACtC,YAAY,EAAE,EAAE,MAAM;AACtB,YAAY,GAAG,EAAE,IAAI,CAAC,GAAG;AACzB,YAAY,QAAQ,EAAE,IAAI;AAC1B,SAAS,CAAC;AACV,QAAQ,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE;AAC7B,IAAI;AACJ,IAAI,MAAM,WAAW,CAAC,OAAO,EAAE;AAC/B,QAAQ,IAAI,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE;AAC3B,QAAQ,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC;AAC7D,QAAQ,IAAI,CAAC,OAAO,EAAE;AACtB,YAAY,MAAM,IAAI,KAAK,CAAC,CAAC,aAAa,EAAE,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;AACvE,QAAQ;AACR,QAAQ,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE;AAC/B,YAAY,MAAM,IAAI,KAAK,CAAC,CAAC,aAAa,EAAE,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;AAC3E,QAAQ;AACR,QAAQ,IAAI;AACZ;AACA,YAAY,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,OAAO,CAAC,OAAO,CAAC;AAChF,YAAY,IAAI;AAChB,gBAAgB,KAAK,IAAI,EAAE,GAAG,IAAI,EAAE,UAAU,GAAG,aAAa,CAAC,QAAQ,CAAC,EAAE,YAAY,EAAE,YAAY,GAAG,MAAM,UAAU,CAAC,IAAI,EAAE,EAAE,EAAE,GAAG,YAAY,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE,GAAG,IAAI,EAAE;AACxK,oBAAoB,EAAE,GAAG,YAAY,CAAC,KAAK;AAC3C,oBAAoB,EAAE,GAAG,KAAK;AAC9B,oBAAoB,MAAM,eAAe,GAAG,EAAE;AAC9C;AACA,oBAAoB,IAAI,CAAC,eAAe,CAAC,YAAY,EAAE;AACvD,wBAAwB,IAAI,EAAE,eAAe;AAC7C,wBAAwB,MAAM,EAAE,OAAO,CAAC,MAAM;AAC9C,wBAAwB,OAAO,EAAE,IAAI;AACrC,qBAAqB,CAAC;AACtB,gBAAgB;AAChB,YAAY;AACZ,YAAY,OAAO,KAAK,EAAE,EAAE,GAAG,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;AACpD,oBAAoB;AACpB,gBAAgB,IAAI;AACpB,oBAAoB,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,UAAU,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC;AACzF,gBAAgB;AAChB,wBAAwB,EAAE,IAAI,GAAG,EAAE,MAAM,GAAG,CAAC,KAAK,CAAC,CAAC;AACpD,YAAY;AACZ;AACA,YAAY,IAAI,CAAC,eAAe,CAAC,YAAY,EAAE;AAC/C,gBAAgB,MAAM,EAAE,OAAO,CAAC,MAAM;AACtC,aAAa,CAAC;AACd,QAAQ;AACR,QAAQ,OAAO,KAAK,EAAE;AACtB,YAAY,OAAO,CAAC,KAAK,CAAC,4BAA4B,EAAE,KAAK,CAAC;AAC9D,YAAY,MAAM,KAAK;AACvB,QAAQ;AACR,IAAI;AACJ,IAAI,MAAM,QAAQ,CAAC,OAAO,EAAE;AAC5B,QAAQ,IAAI,EAAE;AACd,QAAQ,MAAM,MAAM,GAAG,CAAC,EAAE,GAAG,OAAO,CAAC,MAAM,MAAM,IAAI,IAAI,EAAE,KAAK,MAAM,GAAG,EAAE,GAAG,MAAM;AACpF,QAAQ,MAAM,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE;AACzD,QAAQ,MAAM,UAAU,GAAG,MAAM,KAAK,OAAO,KAAK,MAAM,KAAK,MAAM,IAAI,cAAc,KAAK,oBAAoB,CAAC;AAC/G,QAAQ,MAAM,eAAe,GAAG,MAAM,KAAK,YAAY,KAAK,MAAM,KAAK,MAAM,KAAK,OAAO,CAAC,aAAa,IAAI,cAAc,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;AAC5I,QAAQ,IAAI,UAAU,EAAE;AACxB,YAAY,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC;AAClF,QAAQ;AACR,QAAQ,IAAI,eAAe,EAAE;AAC7B,YAAY,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC;AACtF,QAAQ;AACR,QAAQ,IAAI;AACZ;AACA,YAAY,IAAI,CAAC,SAAS,GAAG,SAAS;AACtC,YAAY,IAAI,CAAC,eAAe,CAAC,iBAAiB,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC;AAClF;AACA,YAAY,MAAM,MAAM,GAAG;AAC3B,gBAAgB,WAAW,EAAE;AAC7B,oBAAoB,cAAc,EAAE,OAAO,CAAC,IAAI;AAChD,iBAAiB;AACjB,gBAAgB,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,IAAI;AACpD,gBAAgB,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,EAAE;AACxC,gBAAgB,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,GAAG;AACvD,gBAAgB,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,CAAC;AACnD,aAAa;AACb,YAAY,MAAM,KAAK,GAAG,MAAMC,0BAAe,CAAC,aAAa,CAAC,iEAAiE,CAAC;AAChI;AACA,YAAY,IAAI,CAAC,GAAG,GAAG,MAAMC,uBAAY,CAAC,iBAAiB,CAAC,KAAK,EAAE,MAAM,CAAC;AAC1E;AACA,YAAY,IAAI,CAAC,SAAS,GAAG,OAAO;AACpC,YAAY,IAAI,CAAC,eAAe,CAAC,iBAAiB,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC;AAClF,QAAQ;AACR,QAAQ,OAAO,KAAK,EAAE;AACtB,YAAY,IAAI,CAAC,SAAS,GAAG,OAAO;AACpC,YAAY,IAAI,CAAC,eAAe,CAAC,iBAAiB,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC;AAClF,YAAY,MAAM,KAAK;AACvB,QAAQ;AACR,IAAI;AACJ,IAAI,MAAM,aAAa,CAAC,OAAO,EAAE;AACjC,QAAQ,IAAI,EAAE;AACd,QAAQ,IAAI;AACZ;AACA,YAAY,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE;AACtD,gBAAgB,MAAM,EAAE,KAAK;AAC7B,gBAAgB,OAAO,EAAE;AACzB,oBAAoB,cAAc,EAAE,0BAA0B;AAC9D,iBAAiB;AACjB,aAAa,CAAC;AACd,YAAY,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE;AAC9B,gBAAgB,MAAM,IAAI,KAAK,CAAC,CAAC,0BAA0B,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC;AACnF,YAAY;AACZ,YAAY,MAAM,aAAa,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;AACxE,YAAY,MAAM,UAAU,GAAG,aAAa,GAAG,QAAQ,CAAC,aAAa,EAAE,EAAE,CAAC,GAAG,SAAS;AACtF;AACA,YAAY,MAAM,MAAM,GAAG,CAAC,EAAE,GAAG,QAAQ,CAAC,IAAI,MAAM,IAAI,IAAI,EAAE,KAAK,KAAK,CAAC,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,EAAE;AACnG,YAAY,IAAI,CAAC,MAAM,EAAE;AACzB,gBAAgB,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC;AACrE,YAAY;AACZ,YAAY,MAAM,MAAM,GAAG,EAAE;AAC7B,YAAY,IAAI,eAAe,GAAG,CAAC;AACnC,YAAY,OAAO,IAAI,EAAE;AACzB,gBAAgB,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE;AAC3D,gBAAgB,IAAI,IAAI;AACxB,oBAAoB;AACpB,gBAAgB,IAAI,KAAK,EAAE;AAC3B,oBAAoB,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;AACtC,oBAAoB,eAAe,IAAI,KAAK,CAAC,MAAM;AACnD,gBAAgB;AAChB;AACA,gBAAgB,MAAM,QAAQ,GAAG,UAAU,GAAG,CAAC,eAAe,GAAG,UAAU,IAAI,GAAG,GAAG,CAAC;AACtF,gBAAgB,IAAI,CAAC,eAAe,CAAC,kBAAkB,EAAE;AACzD,oBAAoB,QAAQ;AAC5B,oBAAoB,UAAU;AAC9B,oBAAoB,eAAe;AACnC,iBAAiB,CAAC;AAClB,YAAY;AACZ;AACA;AACA,YAAY,MAAM,MAAM,GAAG;AAC3B,gBAAgB,IAAI,EAAE,OAAO,CAAC,GAAG;AACjC,aAAa;AACb;AACA,YAAY,IAAI,OAAO,CAAC,YAAY,EAAE;AACtC;AACA,gBAAgB,MAAM,CAAC,aAAa,GAAG,OAAO,CAAC,YAAY;AAC3D,YAAY;AACZ,YAAY,OAAO,MAAM;AACzB,QAAQ;AACR,QAAQ,OAAO,KAAK,EAAE;AACtB,YAAY,OAAO,CAAC,KAAK,CAAC,0BAA0B,EAAE,KAAK,CAAC;AAC5D,YAAY,MAAM,KAAK;AACvB,QAAQ;AACR,IAAI;AACJ,IAAI,MAAM,gBAAgB,GAAG;AAC7B,QAAQ,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE;AACjC,IAAI;AACJ;;;;;;;;;"}
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","import { 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 this.modelPath = '';\n this.modelType = 'task';\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 modelPath: this.modelPath,\n modelType: this.modelType,\n history: [],\n });\n return { id: chatId };\n }\n async sendMessage(options) {\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 let hasStreamed = false;\n let responseText = '';\n try {\n const prompt = this.buildPrompt(session, options.message);\n const finalResponse = await session.llm.generateResponse(prompt, (partialResponse, done) => {\n if (done || !partialResponse) {\n return;\n }\n hasStreamed = true;\n responseText += partialResponse;\n this.notifyListeners('textFromAi', {\n text: partialResponse,\n chatId: options.chatId,\n isChunk: true,\n });\n });\n if (!hasStreamed && finalResponse) {\n responseText = finalResponse;\n this.notifyListeners('textFromAi', {\n text: finalResponse,\n chatId: options.chatId,\n isChunk: true,\n });\n }\n session.history.push({ role: 'user', content: options.message }, { role: 'model', content: responseText || finalResponse });\n // Notify completion\n this.notifyListeners('aiFinished', {\n chatId: options.chatId,\n });\n }\n catch (error) {\n console.error('Error generating response:', error);\n const message = error instanceof Error ? error.message : String(error);\n if (hasStreamed) {\n this.notifyListeners('generationError', {\n chatId: options.chatId,\n error: message,\n });\n return;\n }\n throw error;\n }\n }\n async setModel(options) {\n try {\n this.closeCurrentModel();\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 this.modelPath = options.path;\n this.modelType = this.resolveModelType(options);\n this.chatSessions.clear();\n // Update readiness\n this.readiness = 'ready';\n this.notifyListeners('readinessChange', { readiness: this.readiness });\n }\n catch (error) {\n this.closeCurrentModel();\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 async getPluginVersion() {\n return { version: 'web' };\n }\n closeCurrentModel() {\n var _a;\n this.chatSessions.clear();\n (_a = this.llm) === null || _a === void 0 ? void 0 : _a.close();\n this.llm = null;\n this.modelPath = '';\n this.modelType = 'task';\n }\n resolveModelType(options) {\n var _a;\n if ((_a = options.modelType) === null || _a === void 0 ? void 0 : _a.trim()) {\n return options.modelType.trim().toLowerCase();\n }\n const extension = options.path.split('.').pop();\n return extension ? extension.toLowerCase() : 'task';\n }\n buildPrompt(session, message) {\n if (!this.usesGemmaChatTemplate(session)) {\n return message;\n }\n const history = [...session.history, { role: 'user', content: message }];\n return `${history\n .map((turn) => `<start_of_turn>${turn.role}\\n${turn.content}<end_of_turn>`)\n .join('\\n')}\\n<start_of_turn>model\\n`;\n }\n usesGemmaChatTemplate(session) {\n return /gemma/i.test(session.modelPath) || session.modelType === 'litertlm';\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin","FilesetResolver","LlmInference"],"mappings":"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"}
package/dist/plugin.js CHANGED
@@ -5,19 +5,14 @@ var capacitorLLM = (function (exports, core, tasksGenai) {
5
5
  web: () => Promise.resolve().then(function () { return web; }).then((m) => new m.CapgoLLMWeb()),
6
6
  });
7
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
8
  class CapgoLLMWeb extends core.WebPlugin {
16
9
  constructor() {
17
10
  super(...arguments);
18
11
  this.llm = null;
19
12
  this.chatSessions = new Map();
20
13
  this.readiness = 'not-loaded';
14
+ this.modelPath = '';
15
+ this.modelType = 'task';
21
16
  }
22
17
  async getReadiness() {
23
18
  return { readiness: this.readiness };
@@ -31,11 +26,13 @@ var capacitorLLM = (function (exports, core, tasksGenai) {
31
26
  id: chatId,
32
27
  llm: this.llm,
33
28
  isActive: true,
29
+ modelPath: this.modelPath,
30
+ modelType: this.modelType,
31
+ history: [],
34
32
  });
35
33
  return { id: chatId };
36
34
  }
37
35
  async sendMessage(options) {
38
- var _a, e_1, _b, _c;
39
36
  const session = this.chatSessions.get(options.chatId);
40
37
  if (!session) {
41
38
  throw new Error(`Chat session ${options.chatId} not found`);
@@ -43,29 +40,31 @@ var capacitorLLM = (function (exports, core, tasksGenai) {
43
40
  if (!session.isActive) {
44
41
  throw new Error(`Chat session ${options.chatId} is not active`);
45
42
  }
43
+ let hasStreamed = false;
44
+ let responseText = '';
46
45
  try {
47
- // Generate response using MediaPipe GenAI streaming API
48
- const response = session.llm.generateResponseStream(options.message);
49
- try {
50
- for (var _d = true, response_1 = __asyncValues(response), response_1_1; response_1_1 = await response_1.next(), _a = response_1_1.done, !_a; _d = true) {
51
- _c = response_1_1.value;
52
- _d = false;
53
- const partialResponse = _c;
54
- // Send incremental text
55
- this.notifyListeners('textFromAi', {
56
- text: partialResponse,
57
- chatId: options.chatId,
58
- isChunk: true,
59
- });
46
+ const prompt = this.buildPrompt(session, options.message);
47
+ const finalResponse = await session.llm.generateResponse(prompt, (partialResponse, done) => {
48
+ if (done || !partialResponse) {
49
+ return;
60
50
  }
51
+ hasStreamed = true;
52
+ responseText += partialResponse;
53
+ this.notifyListeners('textFromAi', {
54
+ text: partialResponse,
55
+ chatId: options.chatId,
56
+ isChunk: true,
57
+ });
58
+ });
59
+ if (!hasStreamed && finalResponse) {
60
+ responseText = finalResponse;
61
+ this.notifyListeners('textFromAi', {
62
+ text: finalResponse,
63
+ chatId: options.chatId,
64
+ isChunk: true,
65
+ });
61
66
  }
62
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
63
- finally {
64
- try {
65
- if (!_d && !_a && (_b = response_1.return)) await _b.call(response_1);
66
- }
67
- finally { if (e_1) throw e_1.error; }
68
- }
67
+ session.history.push({ role: 'user', content: options.message }, { role: 'model', content: responseText || finalResponse });
69
68
  // Notify completion
70
69
  this.notifyListeners('aiFinished', {
71
70
  chatId: options.chatId,
@@ -73,22 +72,20 @@ var capacitorLLM = (function (exports, core, tasksGenai) {
73
72
  }
74
73
  catch (error) {
75
74
  console.error('Error generating response:', error);
75
+ const message = error instanceof Error ? error.message : String(error);
76
+ if (hasStreamed) {
77
+ this.notifyListeners('generationError', {
78
+ chatId: options.chatId,
79
+ error: message,
80
+ });
81
+ return;
82
+ }
76
83
  throw error;
77
84
  }
78
85
  }
79
86
  async setModel(options) {
80
- var _a;
81
- const engine = (_a = options.engine) !== null && _a !== void 0 ? _a : 'auto';
82
- const normalizedPath = options.path.toLowerCase();
83
- const wantsApple = engine === 'apple' || (engine === 'auto' && normalizedPath === 'apple intelligence');
84
- const wantsExecuTorch = engine === 'executorch' || (engine === 'auto' && (options.tokenizerPath || normalizedPath.endsWith('.pte')));
85
- if (wantsApple) {
86
- throw new Error('Apple Intelligence is only available on native iOS.');
87
- }
88
- if (wantsExecuTorch) {
89
- throw new Error('ExecuTorch is only available on native iOS and Android.');
90
- }
91
87
  try {
88
+ this.closeCurrentModel();
92
89
  // Update readiness
93
90
  this.readiness = 'loading';
94
91
  this.notifyListeners('readinessChange', { readiness: this.readiness });
@@ -105,11 +102,15 @@ var capacitorLLM = (function (exports, core, tasksGenai) {
105
102
  const genai = await tasksGenai.FilesetResolver.forGenAiTasks('https://cdn.jsdelivr.net/npm/@mediapipe/tasks-genai@latest/wasm');
106
103
  // Create LLM instance
107
104
  this.llm = await tasksGenai.LlmInference.createFromOptions(genai, config);
105
+ this.modelPath = options.path;
106
+ this.modelType = this.resolveModelType(options);
107
+ this.chatSessions.clear();
108
108
  // Update readiness
109
109
  this.readiness = 'ready';
110
110
  this.notifyListeners('readinessChange', { readiness: this.readiness });
111
111
  }
112
112
  catch (error) {
113
+ this.closeCurrentModel();
113
114
  this.readiness = 'error';
114
115
  this.notifyListeners('readinessChange', { readiness: this.readiness });
115
116
  throw error;
@@ -173,6 +174,34 @@ var capacitorLLM = (function (exports, core, tasksGenai) {
173
174
  async getPluginVersion() {
174
175
  return { version: 'web' };
175
176
  }
177
+ closeCurrentModel() {
178
+ var _a;
179
+ this.chatSessions.clear();
180
+ (_a = this.llm) === null || _a === void 0 ? void 0 : _a.close();
181
+ this.llm = null;
182
+ this.modelPath = '';
183
+ this.modelType = 'task';
184
+ }
185
+ resolveModelType(options) {
186
+ var _a;
187
+ if ((_a = options.modelType) === null || _a === void 0 ? void 0 : _a.trim()) {
188
+ return options.modelType.trim().toLowerCase();
189
+ }
190
+ const extension = options.path.split('.').pop();
191
+ return extension ? extension.toLowerCase() : 'task';
192
+ }
193
+ buildPrompt(session, message) {
194
+ if (!this.usesGemmaChatTemplate(session)) {
195
+ return message;
196
+ }
197
+ const history = [...session.history, { role: 'user', content: message }];
198
+ return `${history
199
+ .map((turn) => `<start_of_turn>${turn.role}\n${turn.content}<end_of_turn>`)
200
+ .join('\n')}\n<start_of_turn>model\n`;
201
+ }
202
+ usesGemmaChatTemplate(session) {
203
+ return /gemma/i.test(session.modelPath) || session.modelType === 'litertlm';
204
+ }
176
205
  }
177
206
 
178
207
  var web = /*#__PURE__*/Object.freeze({
@@ -1 +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 _a, e_1, _b, _c;\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 _d = true, response_1 = __asyncValues(response), response_1_1; response_1_1 = await response_1.next(), _a = response_1_1.done, !_a; _d = true) {\n _c = response_1_1.value;\n _d = false;\n const partialResponse = _c;\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 (!_d && !_a && (_b = response_1.return)) await _b.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 var _a;\n const engine = (_a = options.engine) !== null && _a !== void 0 ? _a : 'auto';\n const normalizedPath = options.path.toLowerCase();\n const wantsApple = engine === 'apple' || (engine === 'auto' && normalizedPath === 'apple intelligence');\n const wantsExecuTorch = engine === 'executorch' || (engine === 'auto' && (options.tokenizerPath || normalizedPath.endsWith('.pte')));\n if (wantsApple) {\n throw new Error('Apple Intelligence is only available on native iOS.');\n }\n if (wantsExecuTorch) {\n throw new Error('ExecuTorch is only available on native iOS and Android.');\n }\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 async getPluginVersion() {\n return { version: 'web' };\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","this","WebPlugin","FilesetResolver","LlmInference"],"mappings":"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"}
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","import { 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 this.modelPath = '';\n this.modelType = 'task';\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 modelPath: this.modelPath,\n modelType: this.modelType,\n history: [],\n });\n return { id: chatId };\n }\n async sendMessage(options) {\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 let hasStreamed = false;\n let responseText = '';\n try {\n const prompt = this.buildPrompt(session, options.message);\n const finalResponse = await session.llm.generateResponse(prompt, (partialResponse, done) => {\n if (done || !partialResponse) {\n return;\n }\n hasStreamed = true;\n responseText += partialResponse;\n this.notifyListeners('textFromAi', {\n text: partialResponse,\n chatId: options.chatId,\n isChunk: true,\n });\n });\n if (!hasStreamed && finalResponse) {\n responseText = finalResponse;\n this.notifyListeners('textFromAi', {\n text: finalResponse,\n chatId: options.chatId,\n isChunk: true,\n });\n }\n session.history.push({ role: 'user', content: options.message }, { role: 'model', content: responseText || finalResponse });\n // Notify completion\n this.notifyListeners('aiFinished', {\n chatId: options.chatId,\n });\n }\n catch (error) {\n console.error('Error generating response:', error);\n const message = error instanceof Error ? error.message : String(error);\n if (hasStreamed) {\n this.notifyListeners('generationError', {\n chatId: options.chatId,\n error: message,\n });\n return;\n }\n throw error;\n }\n }\n async setModel(options) {\n try {\n this.closeCurrentModel();\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 this.modelPath = options.path;\n this.modelType = this.resolveModelType(options);\n this.chatSessions.clear();\n // Update readiness\n this.readiness = 'ready';\n this.notifyListeners('readinessChange', { readiness: this.readiness });\n }\n catch (error) {\n this.closeCurrentModel();\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 async getPluginVersion() {\n return { version: 'web' };\n }\n closeCurrentModel() {\n var _a;\n this.chatSessions.clear();\n (_a = this.llm) === null || _a === void 0 ? void 0 : _a.close();\n this.llm = null;\n this.modelPath = '';\n this.modelType = 'task';\n }\n resolveModelType(options) {\n var _a;\n if ((_a = options.modelType) === null || _a === void 0 ? void 0 : _a.trim()) {\n return options.modelType.trim().toLowerCase();\n }\n const extension = options.path.split('.').pop();\n return extension ? extension.toLowerCase() : 'task';\n }\n buildPrompt(session, message) {\n if (!this.usesGemmaChatTemplate(session)) {\n return message;\n }\n const history = [...session.history, { role: 'user', content: message }];\n return `${history\n .map((turn) => `<start_of_turn>${turn.role}\\n${turn.content}<end_of_turn>`)\n .join('\\n')}\\n<start_of_turn>model\\n`;\n }\n usesGemmaChatTemplate(session) {\n return /gemma/i.test(session.modelPath) || session.modelType === 'litertlm';\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin","FilesetResolver","LlmInference"],"mappings":"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"}