@omniyat/aimodule 1.0.2 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,26 +1,17 @@
1
- # 🤖 @brinda_yawa/ai-module
1
+ # 🤖 @omniyat/aimodule
2
2
 
3
3
  A unified Node.js module for AI-powered invoice extraction and task generation using Google's Gemini models.
4
4
 
5
- ## ✨ Features
6
-
7
- - 🧾 **Invoice Extraction** - Extract structured data from PDF and image invoices
8
- - ✅ **Task Generation** - Generate structured task lists from intervention descriptions
9
- - 🖼️ **Multi-modal Support** - Handles images (PNG, JPG, JPEG, WEBP) and audio files
10
- - 🎯 **Structured Output** - Returns clean, structured JSON data
11
- - 🔑 **Single Initialization** - One `init()` call configures all services
12
- - 🧩 **Modular Design** - Access each service independently via `AiModule.invoices` or `AiModule.tasks`
13
-
14
5
  ## 📦 Installation
15
6
 
16
7
  ```bash
17
- npm install @brinda_yawa/ai-module
8
+ npm install @omniyat/aimodule
18
9
  ```
19
10
 
20
11
  ## 🚀 Quick Start
21
12
 
22
13
  ```javascript
23
- import AiModule from '@brinda_yawa/ai-module';
14
+ import AiModule from '@omniyat/aimodule';
24
15
  import fs from 'fs';
25
16
 
26
17
  // Initialize the module once
@@ -39,142 +30,4 @@ const tasks = await AiModule.tasks.generateTasks(
39
30
  'Pneu crevé',
40
31
  'Intervention de dépannage suite à un pneu crevé...'
41
32
  );
42
- ```
43
-
44
- ## 📖 API Reference
45
-
46
- ### `AiModule.init(options)`
47
-
48
- Initializes all services with the provided configuration. Must be called before using any service.
49
-
50
- | Parameter | Type | Required | Default | Description |
51
- |-----------|------|----------|---------|-------------|
52
- | `apiKey` | `string` | ✅ | — | Your Google Gemini API key |
53
- | `model` | `string` | ❌ | `gemini-2.5-flash` | Gemini model to use |
54
-
55
- ```javascript
56
- AiModule.init({ apiKey: process.env.GEMINI_API_KEY });
57
- ```
58
-
59
- ---
60
-
61
- ### `AiModule.invoices`
62
-
63
- Access the invoice extraction service.
64
-
65
- #### `AiModule.invoices.extractFromBase64(base64Data)`
66
-
67
- Extracts structured invoice data from a base64-encoded file.
68
-
69
- | Parameter | Type | Required | Description |
70
- |-----------|------|----------|-------------|
71
- | `base64Data` | `string` | ✅ | Base64 string (with or without `data:...;base64,` prefix) |
72
-
73
- **Returns:** `Promise<Object | null>`
74
-
75
- ```javascript
76
- const buffer = fs.readFileSync('invoice.pdf');
77
- const base64 = buffer.toString('base64');
78
-
79
- const result = await AiModule.invoices.extractFromBase64(base64);
80
- console.log(result);
81
- // {
82
- // invoiceNumber: "INV-2024-001",
83
- // date: "2024-01-15",
84
- // total: 1250.00,
85
- // vendor: { name: "...", address: "..." },
86
- // items: [...]
87
- // }
88
- ```
89
-
90
- **Supported formats:** PDF, PNG, JPG, JPEG, WEBP
91
-
92
- ---
93
-
94
- ### `AiModule.tasks`
95
-
96
- Access the task generation service.
97
-
98
- #### `AiModule.tasks.generateTasks(title, description, joinedImage?, joinedAudio?)`
99
-
100
- Generates a structured list of tasks from an intervention description.
101
-
102
- | Parameter | Type | Required | Description |
103
- |-----------|------|----------|-------------|
104
- | `title` | `string` | ✅ | Short title of the intervention |
105
- | `description` | `string` | ✅ | Detailed description of the intervention |
106
- | `joinedImage` | `{ buffer: Buffer, extension: string }` | ❌ | Optional image file |
107
- | `joinedAudio` | `{ buffer: Buffer, extension: string }` | ❌ | Optional audio file |
108
-
109
- **Returns:** `Promise<Array<{ title: string, description: string }>>`
110
-
111
- ```javascript
112
- // Text only
113
- const tasks = await AiModule.tasks.generateTasks(
114
- 'Vidange moteur',
115
- 'Vidange complète du moteur avec remplacement du filtre à huile.'
116
- );
117
-
118
- // With an image
119
- const imageBuffer = fs.readFileSync('photo.webp');
120
- const tasks = await AiModule.tasks.generateTasks(
121
- 'Pneu crevé',
122
- 'Intervention suite à un pneu crevé...',
123
- { buffer: imageBuffer, extension: '.webp' }
124
- );
125
-
126
- console.log(tasks);
127
- // [
128
- // { title: "Diagnostic", description: "Inspecter le pneumatique..." },
129
- // { title: "Réparation", description: "Poser une mèche ou remplacer..." },
130
- // ...
131
- // ]
132
- ```
133
-
134
- **Supported image formats:** PNG, JPG, JPEG, WEBP
135
- **Supported audio formats:** MP3, WAV
136
-
137
- ---
138
-
139
- ## 🗂️ Module Structure
140
-
141
- ```
142
- ai-module/
143
- ├── index.js # AiModule entry point
144
- ├── services/
145
- │ ├── InvoiceExtractor.js # Invoice extraction logic
146
- │ └── TasksGenerator.js # Task generation logic
147
- └── utils/
148
- └── util.js # Shared utilities (prompts, mime types...)
149
- ```
150
-
151
- ## 🔑 Environment Variables
152
-
153
- It is recommended to store your API key in a `.env` file:
154
-
155
- ```env
156
- GEMINI_API_KEY=your_api_key_here
157
- ```
158
-
159
- ```javascript
160
- import dotenv from 'dotenv';
161
- dotenv.config();
162
-
163
- AiModule.init({ apiKey: process.env.GEMINI_API_KEY });
164
- ```
165
-
166
- ## ⚠️ Error Handling
167
-
168
- ```javascript
169
- try {
170
- AiModule.init({ apiKey: process.env.GEMINI_API_KEY });
171
-
172
- const tasks = await AiModule.tasks.generateTasks(title, description);
173
- } catch (error) {
174
- if (error.message.includes('not initialized')) {
175
- console.error('Call AiModule.init() before using any service.');
176
- } else {
177
- console.error('Unexpected error:', error.message);
178
- }
179
- }
180
33
  ```
package/dist/index.cjs CHANGED
@@ -297,4 +297,4 @@ async function(e,t,n){const o=new Ye;let i;i=n.data instanceof Blob?JSON.parse(a
297
297
  * @license
298
298
  * Copyright 2025 Google LLC
299
299
  * SPDX-License-Identifier: Apache-2.0
300
- */e.ApiError=pn,e.Batches=Gt,e.Caches=Yt,e.CancelTuningJobResponse=Ue,e.Chat=on,e.Chats=nn,e.ComputeTokensResponse=Pe,e.ContentReferenceImage=class{toReferenceImageAPI(){return{referenceType:"REFERENCE_TYPE_CONTENT",referenceImage:this.referenceImage,referenceId:this.referenceId}}},e.ControlReferenceImage=class{toReferenceImageAPI(){return{referenceType:"REFERENCE_TYPE_CONTROL",referenceImage:this.referenceImage,referenceId:this.referenceId,controlImageConfig:this.config}}},e.CountTokensResponse=Ne,e.CreateFileResponse=je,e.DeleteCachedContentResponse=xe,e.DeleteFileResponse=Ve,e.DeleteModelResponse=we,e.EditImageResponse=Ae,e.EmbedContentResponse=_e,e.Files=An,e.FunctionResponse=class{},e.FunctionResponseBlob=class{},e.FunctionResponseFileData=class{},e.FunctionResponsePart=class{},e.GenerateContentResponse=Ie,e.GenerateContentResponsePromptFeedback=class{},e.GenerateContentResponseUsageMetadata=class{},e.GenerateImagesResponse=Se,e.GenerateVideosOperation=Me,e.GenerateVideosResponse=class{},e.GoogleGenAI=class{get interactions(){var e;if(void 0!==this._interactions)return this._interactions;if(console.warn("GoogleGenAI.interactions: Interactions usage is experimental and may change in future versions."),this.vertexai)throw new Error("This version of the GenAI SDK does not support Vertex AI API for interactions.");const t=this.httpOptions;(null==t?void 0:t.extraBody)&&console.warn("GoogleGenAI.interactions: Client level httpOptions.extraBody is not supported by the interactions client and will be ignored.");const n=new Fo({baseURL:this.apiClient.getBaseUrl(),apiKey:this.apiKey,apiVersion:this.apiClient.getApiVersion(),clientAdapter:this.apiClient,defaultHeaders:this.apiClient.getDefaultHeaders(),timeout:null==t?void 0:t.timeout,maxRetries:null===(e=null==t?void 0:t.retryOptions)||void 0===e?void 0:e.attempts});return this._interactions=n.interactions,this._interactions}constructor(e){var t;if(null==e.apiKey)throw new Error(`An API Key must be set when running in an unspecified environment.\n + ${gn().message}`);this.vertexai=null!==(t=e.vertexai)&&void 0!==t&&t,this.apiKey=e.apiKey,this.apiVersion=e.apiVersion,this.httpOptions=e.httpOptions;const n=new dr(this.apiKey);this.apiClient=new fn({auth:n,apiVersion:this.apiVersion,apiKey:this.apiKey,vertexai:this.vertexai,httpOptions:this.httpOptions,userAgentExtra:"gl-node/cross",uploader:new En,downloader:new yn}),this.models=new Xi(this.apiClient),this.live=new Bi(this.apiClient,n,new _n),this.chats=new nn(this.models,this.apiClient),this.batches=new Gt(this.apiClient),this.caches=new Yt(this.apiClient),this.files=new An(this.apiClient),this.operations=new Qi(this.apiClient),this.authTokens=new nr(this.apiClient),this.tunings=new cr(this.apiClient),this.fileSearchStores=new Rn(this.apiClient)}},e.HttpResponse=Te,e.ImportFileOperation=Fe,e.ImportFileResponse=class{},e.InlinedEmbedContentResponse=class{},e.InlinedResponse=class{},e.ListBatchJobsResponse=Je,e.ListCachedContentsResponse=Le,e.ListDocumentsResponse=ke,e.ListFileSearchStoresResponse=qe,e.ListFilesResponse=He,e.ListModelsResponse=Re,e.ListTuningJobsResponse=De,e.Live=Bi,e.LiveClientToolResponse=class{},e.LiveMusicServerMessage=Ye,e.LiveSendToolResponseParameters=class{constructor(){this.functionResponses=[]}},e.LiveServerMessage=$e,e.MaskReferenceImage=class{toReferenceImageAPI(){return{referenceType:"REFERENCE_TYPE_MASK",referenceImage:this.referenceImage,referenceId:this.referenceId,maskImageConfig:this.config}}},e.Models=Xi,e.Operations=Qi,e.Pager=qt,e.RawReferenceImage=class{toReferenceImageAPI(){return{referenceType:"REFERENCE_TYPE_RAW",referenceImage:this.referenceImage,referenceId:this.referenceId}}},e.RecontextImageResponse=Oe,e.RegisterFilesResponse=Be,e.ReplayResponse=class{},e.SegmentImageResponse=be,e.Session=$i,e.SingleEmbedContentResponse=class{},e.StyleReferenceImage=class{toReferenceImageAPI(){return{referenceType:"REFERENCE_TYPE_STYLE",referenceImage:this.referenceImage,referenceId:this.referenceId,styleImageConfig:this.config}}},e.SubjectReferenceImage=class{toReferenceImageAPI(){return{referenceType:"REFERENCE_TYPE_SUBJECT",referenceImage:this.referenceImage,referenceId:this.referenceId,subjectImageConfig:this.config}}},e.Tokens=nr,e.UploadToFileSearchStoreOperation=Ke,e.UploadToFileSearchStoreResponse=class{},e.UploadToFileSearchStoreResumableResponse=Ge,e.UpscaleImageResponse=Ce,e.createFunctionResponsePartFromBase64=function(e,t){return{inlineData:{data:e,mimeType:t}}},e.createFunctionResponsePartFromUri=function(e,t){return{fileData:{fileUri:e,mimeType:t}}},e.createModelContent=function(e){return{role:"model",parts:Ee(e)}},e.createPartFromBase64=function(e,t,n){return Object.assign({inlineData:{data:e,mimeType:t}},n&&{mediaResolution:{level:n}})},e.createPartFromCodeExecutionResult=function(e,t){return{codeExecutionResult:{outcome:e,output:t}}},e.createPartFromExecutableCode=function(e,t){return{executableCode:{code:e,language:t}}},e.createPartFromFunctionCall=function(e,t){return{functionCall:{name:e,args:t}}},e.createPartFromFunctionResponse=function(e,t,n,o=[]){return{functionResponse:Object.assign({id:e,name:t,response:n},o.length>0&&{parts:o})}},e.createPartFromText=ye,e.createPartFromUri=function(e,t,n){return Object.assign({fileData:{fileUri:e,mimeType:t}},n&&{mediaResolution:{level:n}})},e.createUserContent=function(e){return{role:"user",parts:Ee(e)}},e.mcpToTool=function(...e){if(Li=!0,0===e.length)throw new Error("No MCP clients provided");const t=e[e.length-1];return null!==(n=t)&&"object"==typeof n&&"listTools"in n&&"function"==typeof n.listTools?Hi.create(e,{}):Hi.create(e.slice(0,e.length-1),t);var n},e.setDefaultBaseUrls=function(e){e.geminiUrl,e.vertexUrl}}(y)),y}function A(){if(c)return u;return c=1,u={getExtractionPrompt:function(){return'\nTu es un moteur d\'extraction et de classification spécialisé dans les factures du secteur mécanique automobile.\n\nTa tâche est d’analyser le texte fourni.\n\nIMPORTANT :\n- Si le document n’est PAS clairement une facture, retourne STRICTEMENT : null\n- Sinon retourne UNIQUEMENT un JSON valide correspondant au schéma.\nLe JSON doit respecter STRICTEMENT cette structure :\n\n{\n "reference": string | null,\n "date": string | null,\n "supplier": string | null,\n "customer": string | null,\n "totalAmount": number | null,\n "currency": string | null,\n "address": string | null,\n "items": [\n {\n "description": string,\n "quantity": number | null,\n "unitPrice": number | null,\n "totalPrice": number | null,\n "category": string | null\n }\n ],\n "taxAmount": number | null,\n "language": string | null\n}\n\nCATEGORIES AUTORISÉES (liste fermée) :\n\n- carrosserie\n- depannage\n- entretien_preventif\n- reparation_curative\n- diagnostic_electronique\n- autre\n\nRÈGLES DE CLASSIFICATION :\n\nAnalyse la description de chaque article et classe-le dans UNE SEULE catégorie :\n\n- carrosserie → peinture, tôle, choc, pare-chocs, aile, redressage\n- depannage → remorquage, dépannage route, batterie à plat\n- entretien_preventif → vidange, filtres, révision, entretien périodique\n- reparation_curative → remplacement pièce, réparation moteur, frein, embrayage\n- diagnostic_electronique → valise, scanner OBD, diagnostic calculateur\n\nSi aucune catégorie ne correspond clairement → "autre".\n\nRÈGLES GÉNÉRALES :\n\n1. Retourne UNIQUEMENT :\n - soit null\n - soit un JSON valide.\n2. Aucun texte explicatif.\n3. Aucun markdown.\n4. Si une donnée est absente → null.\n5. Les montants doivent être des NOMBRES.\n6. Utilise "." comme séparateur décimal.\n7. Date format YYYY-MM-DD ou null.\n8. Devise normalisée (EUR, USD, MAD...).\n9. Ne déduis aucune information absente explicitement.\n10. Une seule catégorie par item.\n\nAnalyse maintenant le texte suivant :\n'},getTasksCreationPrompt:function(e,t){return`\n CONTEXTE: Creation de tâches dans une solution de fleet management system.\n Tu es le responsable de park en maintenance de flottes(automobiles, camions, vehicules). \n Les taches sont le moyen de communiquer entre les personnes impliquées dans la gestion de resolution de l'intervention.\n Tu reçois les signalement des chauffeurs sur l'état de leurs véhicules. \n\n À partir de l'intervention, génère un tableau JSON de tâches détaillées et structurées.\n Tu pourrais recevoir un audio ou une photo descriptive de l'intervention ou de la panne.\n Il faudra les analyser pour en extraire des informations utiles à la création des tâches.\n Genere uniquement des taches principales relatives à la resolution de l'intervention.'\n \n **Titre :** ${e}\n **Description :** ${t}\n Réponds UNIQUEMENT avec un tableau JSON valide (sans markdown, sans explication), en suivant exactement ce format :\n [\n {\n "title": "Titre de la tâche",\n "description": "Description détaillée",\n "category": "catégorie de la tache(exemple: mécanique, electric, pneumatique,..)"\n }\n ]`},cleanJsonResponse:function(e){return e.replace(/```json/g,"").replace(/```/g,"").trim()},getMimeType:function(e){return{jpg:"image/jpeg",jpeg:"image/jpeg",png:"image/png",webp:"image/webp",mp3:"audio/mpeg",wav:"audio/wav"}[e.replace(".","").toLowerCase()]}}}var C=t(function(){if(g)return m;g=1;const{GoogleGenAI:t}=S(),{extractFromBase64:n}=function(){if(d)return p;d=1;const t=e,{getExtractionPrompt:n}=A();return p={extractFromBase64:async function(e,o,i){if(!i)return null;if(!e)throw new Error("InvoiceExtractor not initialized. Call init() first.");let r,s=i;const l=i.match(/^data:(.*);base64,(.*)$/);if(l)r=l[1],s=l[2];else{const e=Buffer.from(i,"base64"),n=await t(e);if(!n)throw new Error("Unable to detect file type");r=n.mime}const a=await e.models.generateContent({model:o,contents:[{role:"user",parts:[{inlineData:{mimeType:r,data:s}},{text:n()}]}]});if(!a?.text)return null;const u=a.text.replace(/```json|```/g,"").trim();return JSON.parse(u)}}}(),{generateTasks:o}=function(){if(f)return h;f=1;const{cleanJsonResponse:e,getMimeType:t,getTasksCreationPrompt:n}=A();return h={generateTasks:async function(o,i,r,s,l,a){if(!r||!s)throw new Error("Le titre et la description sont obligatoires.");if(!o)throw new Error("TasksGenerator not initialized. Call init() first.");const u=[];l&&u.push({inlineData:{mimeType:t(l.extension),data:Buffer.from(l.buffer).toString("base64")}}),a&&u.push({inlineData:{mimeType:t(a.extension),data:Buffer.from(a.buffer).toString("base64")}}),u.push({text:n(r,s)});const c=await o.models.generateContent({model:i,contents:[{role:"user",parts:u}],generationConfig:{maxOutputTokens:2048,temperature:.2}}),p=c.candidates?.[0]?.content?.parts?.[0]?.text?.trim();if(!p)throw new Error("Réponse vide du modèle.");const d=JSON.parse(e(p));if(!Array.isArray(d))throw new Error("La réponse n'est pas un tableau JSON.");return d}}}();return m=new class{#e;#t;init({apiKey:e,model:n}={}){const o=e??process.env.AI_API_KEY,i=n??process.env.AI_MODEL??"gemini-2.5-flash";if(!o)throw new Error("API key is required. Provide it via init() or AI_API_KEY env variable.");return this.#e=new t({apiKey:o}),this.#t=i,this}extract(e){if(!this.#e)throw new Error("AiModule not initialized. Call init() first.");return n(this.#e,this.#t,e)}generateTasks(e,t,n,i){if(!this.#e)throw new Error("AiModule not initialized. Call init() first.");return o(this.#e,this.#t,e,t,n,i)}}}());module.exports=C;
300
+ */e.ApiError=pn,e.Batches=Gt,e.Caches=Yt,e.CancelTuningJobResponse=Ue,e.Chat=on,e.Chats=nn,e.ComputeTokensResponse=Pe,e.ContentReferenceImage=class{toReferenceImageAPI(){return{referenceType:"REFERENCE_TYPE_CONTENT",referenceImage:this.referenceImage,referenceId:this.referenceId}}},e.ControlReferenceImage=class{toReferenceImageAPI(){return{referenceType:"REFERENCE_TYPE_CONTROL",referenceImage:this.referenceImage,referenceId:this.referenceId,controlImageConfig:this.config}}},e.CountTokensResponse=Ne,e.CreateFileResponse=je,e.DeleteCachedContentResponse=xe,e.DeleteFileResponse=Ve,e.DeleteModelResponse=we,e.EditImageResponse=Ae,e.EmbedContentResponse=_e,e.Files=An,e.FunctionResponse=class{},e.FunctionResponseBlob=class{},e.FunctionResponseFileData=class{},e.FunctionResponsePart=class{},e.GenerateContentResponse=Ie,e.GenerateContentResponsePromptFeedback=class{},e.GenerateContentResponseUsageMetadata=class{},e.GenerateImagesResponse=Se,e.GenerateVideosOperation=Me,e.GenerateVideosResponse=class{},e.GoogleGenAI=class{get interactions(){var e;if(void 0!==this._interactions)return this._interactions;if(console.warn("GoogleGenAI.interactions: Interactions usage is experimental and may change in future versions."),this.vertexai)throw new Error("This version of the GenAI SDK does not support Vertex AI API for interactions.");const t=this.httpOptions;(null==t?void 0:t.extraBody)&&console.warn("GoogleGenAI.interactions: Client level httpOptions.extraBody is not supported by the interactions client and will be ignored.");const n=new Fo({baseURL:this.apiClient.getBaseUrl(),apiKey:this.apiKey,apiVersion:this.apiClient.getApiVersion(),clientAdapter:this.apiClient,defaultHeaders:this.apiClient.getDefaultHeaders(),timeout:null==t?void 0:t.timeout,maxRetries:null===(e=null==t?void 0:t.retryOptions)||void 0===e?void 0:e.attempts});return this._interactions=n.interactions,this._interactions}constructor(e){var t;if(null==e.apiKey)throw new Error(`An API Key must be set when running in an unspecified environment.\n + ${gn().message}`);this.vertexai=null!==(t=e.vertexai)&&void 0!==t&&t,this.apiKey=e.apiKey,this.apiVersion=e.apiVersion,this.httpOptions=e.httpOptions;const n=new dr(this.apiKey);this.apiClient=new fn({auth:n,apiVersion:this.apiVersion,apiKey:this.apiKey,vertexai:this.vertexai,httpOptions:this.httpOptions,userAgentExtra:"gl-node/cross",uploader:new En,downloader:new yn}),this.models=new Xi(this.apiClient),this.live=new Bi(this.apiClient,n,new _n),this.chats=new nn(this.models,this.apiClient),this.batches=new Gt(this.apiClient),this.caches=new Yt(this.apiClient),this.files=new An(this.apiClient),this.operations=new Qi(this.apiClient),this.authTokens=new nr(this.apiClient),this.tunings=new cr(this.apiClient),this.fileSearchStores=new Rn(this.apiClient)}},e.HttpResponse=Te,e.ImportFileOperation=Fe,e.ImportFileResponse=class{},e.InlinedEmbedContentResponse=class{},e.InlinedResponse=class{},e.ListBatchJobsResponse=Je,e.ListCachedContentsResponse=Le,e.ListDocumentsResponse=ke,e.ListFileSearchStoresResponse=qe,e.ListFilesResponse=He,e.ListModelsResponse=Re,e.ListTuningJobsResponse=De,e.Live=Bi,e.LiveClientToolResponse=class{},e.LiveMusicServerMessage=Ye,e.LiveSendToolResponseParameters=class{constructor(){this.functionResponses=[]}},e.LiveServerMessage=$e,e.MaskReferenceImage=class{toReferenceImageAPI(){return{referenceType:"REFERENCE_TYPE_MASK",referenceImage:this.referenceImage,referenceId:this.referenceId,maskImageConfig:this.config}}},e.Models=Xi,e.Operations=Qi,e.Pager=qt,e.RawReferenceImage=class{toReferenceImageAPI(){return{referenceType:"REFERENCE_TYPE_RAW",referenceImage:this.referenceImage,referenceId:this.referenceId}}},e.RecontextImageResponse=Oe,e.RegisterFilesResponse=Be,e.ReplayResponse=class{},e.SegmentImageResponse=be,e.Session=$i,e.SingleEmbedContentResponse=class{},e.StyleReferenceImage=class{toReferenceImageAPI(){return{referenceType:"REFERENCE_TYPE_STYLE",referenceImage:this.referenceImage,referenceId:this.referenceId,styleImageConfig:this.config}}},e.SubjectReferenceImage=class{toReferenceImageAPI(){return{referenceType:"REFERENCE_TYPE_SUBJECT",referenceImage:this.referenceImage,referenceId:this.referenceId,subjectImageConfig:this.config}}},e.Tokens=nr,e.UploadToFileSearchStoreOperation=Ke,e.UploadToFileSearchStoreResponse=class{},e.UploadToFileSearchStoreResumableResponse=Ge,e.UpscaleImageResponse=Ce,e.createFunctionResponsePartFromBase64=function(e,t){return{inlineData:{data:e,mimeType:t}}},e.createFunctionResponsePartFromUri=function(e,t){return{fileData:{fileUri:e,mimeType:t}}},e.createModelContent=function(e){return{role:"model",parts:Ee(e)}},e.createPartFromBase64=function(e,t,n){return Object.assign({inlineData:{data:e,mimeType:t}},n&&{mediaResolution:{level:n}})},e.createPartFromCodeExecutionResult=function(e,t){return{codeExecutionResult:{outcome:e,output:t}}},e.createPartFromExecutableCode=function(e,t){return{executableCode:{code:e,language:t}}},e.createPartFromFunctionCall=function(e,t){return{functionCall:{name:e,args:t}}},e.createPartFromFunctionResponse=function(e,t,n,o=[]){return{functionResponse:Object.assign({id:e,name:t,response:n},o.length>0&&{parts:o})}},e.createPartFromText=ye,e.createPartFromUri=function(e,t,n){return Object.assign({fileData:{fileUri:e,mimeType:t}},n&&{mediaResolution:{level:n}})},e.createUserContent=function(e){return{role:"user",parts:Ee(e)}},e.mcpToTool=function(...e){if(Li=!0,0===e.length)throw new Error("No MCP clients provided");const t=e[e.length-1];return null!==(n=t)&&"object"==typeof n&&"listTools"in n&&"function"==typeof n.listTools?Hi.create(e,{}):Hi.create(e.slice(0,e.length-1),t);var n},e.setDefaultBaseUrls=function(e){e.geminiUrl,e.vertexUrl}}(y)),y}function A(){if(c)return u;return c=1,u={getExtractionPrompt:function(){return'\nTu es un moteur d\'extraction et de classification spécialisé dans les factures du secteur mécanique automobile.\n\nTa tâche est d’analyser le texte fourni.\n\nIMPORTANT :\n- Si le document n’est PAS clairement une facture, retourne STRICTEMENT : null\n- Sinon retourne UNIQUEMENT un JSON valide correspondant au schéma.\nLe JSON doit respecter STRICTEMENT cette structure :\n\n{\n "reference": string | null,\n "date": string | null,\n "supplier": string | null,\n "customer": string | null,\n "totalAmount": number | null,\n "currency": string | null,\n "address": string | null,\n "items": [\n {\n "description": string,\n "quantity": number | null,\n "unitPrice": number | null,\n "totalPrice": number | null,\n "category": string | null\n }\n ],\n "taxAmount": number | null,\n "language": string | null\n}\n\nCATEGORIES AUTORISÉES (liste fermée) :\n\n- carrosserie\n- depannage\n- entretien_preventif\n- reparation_curative\n- diagnostic_electronique\n- autre\n\nRÈGLES DE CLASSIFICATION :\n\nAnalyse la description de chaque article et classe-le dans UNE SEULE catégorie :\n\n- carrosserie → peinture, tôle, choc, pare-chocs, aile, redressage\n- depannage → remorquage, dépannage route, batterie à plat\n- entretien_preventif → vidange, filtres, révision, entretien périodique\n- reparation_curative → remplacement pièce, réparation moteur, frein, embrayage\n- diagnostic_electronique → valise, scanner OBD, diagnostic calculateur\n\nSi aucune catégorie ne correspond clairement → "autre".\n\nRÈGLES GÉNÉRALES :\n\n1. Retourne UNIQUEMENT :\n - soit null\n - soit un JSON valide.\n2. Aucun texte explicatif.\n3. Aucun markdown.\n4. Si une donnée est absente → null.\n5. Les montants doivent être des NOMBRES.\n6. Utilise "." comme séparateur décimal.\n7. Date format YYYY-MM-DD ou null.\n8. Devise normalisée (EUR, USD, MAD...).\n9. Ne déduis aucune information absente explicitement.\n10. Une seule catégorie par item.\n\nAnalyse maintenant le texte suivant :\n'},getTasksCreationPrompt:function(e,t){return`\n CONTEXTE: Creation de tâches dans une solution de fleet management system.\n Tu es le responsable de park en maintenance de flottes(automobiles, camions, vehicules). \n Les taches sont le moyen de communiquer entre les personnes impliquées dans la gestion de resolution de l'intervention.\n Tu reçois les signalement des chauffeurs sur l'état de leurs véhicules. \n\n À partir de l'intervention, génère un tableau JSON de tâches détaillées et structurées.\n Tu pourrais recevoir un audio ou une photo descriptive de l'intervention ou de la panne.\n Il faudra les analyser pour en extraire des informations utiles à la création des tâches.\n Genere uniquement des taches principales relatives à la resolution de l'intervention.'\n \n **Titre :** ${e}\n **Description :** ${t}\n Réponds UNIQUEMENT avec un tableau JSON valide (sans markdown, sans explication), en suivant exactement ce format :\n [\n {\n "title": "Titre de la tâche",\n "description": "Description détaillée",\n "category": "catégorie de la tache(exemple: mécanique, electric, pneumatique,..)"\n }\n ]`},cleanJsonResponse:function(e){return e.replace(/```json/g,"").replace(/```/g,"").trim()},getMimeType:function(e){return{jpg:"image/jpeg",jpeg:"image/jpeg",png:"image/png",webp:"image/webp",mp3:"audio/mpeg",wav:"audio/wav"}[e.replace(".","").toLowerCase()]}}}var C=t(function(){if(g)return m;g=1;const{GoogleGenAI:t}=S(),{extractFromBase64:n}=function(){if(d)return p;d=1;const{fromBuffer:t}=e,{getExtractionPrompt:n}=A();return p={extractFromBase64:async function(e,o,i){if(!i)return null;if(!e)throw new Error("InvoiceExtractor not initialized. Call init() first.");let r,s=i;const l=i.match(/^data:(.*);base64,(.*)$/);if(l)r=l[1],s=l[2];else{const e=Buffer.from(i,"base64"),n=await t(e);if(!n)throw new Error("Unable to detect file type");r=n.mime}const a=await e.models.generateContent({model:o,contents:[{role:"user",parts:[{inlineData:{mimeType:r,data:s}},{text:n()}]}]});if(!a?.text)return null;const u=a.text.replace(/```json|```/g,"").trim();return JSON.parse(u)}}}(),{generateTasks:o}=function(){if(f)return h;f=1;const{cleanJsonResponse:e,getMimeType:t,getTasksCreationPrompt:n}=A();return h={generateTasks:async function(o,i,r,s,l,a){if(!r||!s)throw new Error("Le titre et la description sont obligatoires.");if(!o)throw new Error("TasksGenerator not initialized. Call init() first.");const u=[];l&&u.push({inlineData:{mimeType:t(l.extension),data:Buffer.from(l.buffer).toString("base64")}}),a&&u.push({inlineData:{mimeType:t(a.extension),data:Buffer.from(a.buffer).toString("base64")}}),u.push({text:n(r,s)});const c=await o.models.generateContent({model:i,contents:[{role:"user",parts:u}],generationConfig:{maxOutputTokens:2048,temperature:.2}}),p=c.candidates?.[0]?.content?.parts?.[0]?.text?.trim();if(!p)throw new Error("Réponse vide du modèle.");const d=JSON.parse(e(p));if(!Array.isArray(d))throw new Error("La réponse n'est pas un tableau JSON.");return d}}}();return m=new class{#e;#t;init({apiKey:e,model:n}={}){const o=e??process.env.AI_API_KEY,i=n??process.env.AI_MODEL??"gemini-2.5-flash";if(!o)throw new Error("API key is required. Provide it via init() or AI_API_KEY env variable.");return this.#e=new t({apiKey:o}),this.#t=i,this}extract(e){if(!this.#e)throw new Error("AiModule not initialized. Call init() first.");return n(this.#e,this.#t,e)}generateTasks(e,t,n,i){if(!this.#e)throw new Error("AiModule not initialized. Call init() first.");return o(this.#e,this.#t,e,t,n,i)}}}());module.exports=C;
package/dist/index.mjs CHANGED
@@ -297,4 +297,4 @@ async function(e,t,n){const o=new Ye;let i;i=n.data instanceof Blob?JSON.parse(a
297
297
  * @license
298
298
  * Copyright 2025 Google LLC
299
299
  * SPDX-License-Identifier: Apache-2.0
300
- */e.ApiError=pn,e.Batches=Gt,e.Caches=Yt,e.CancelTuningJobResponse=Ue,e.Chat=on,e.Chats=nn,e.ComputeTokensResponse=Pe,e.ContentReferenceImage=class{toReferenceImageAPI(){return{referenceType:"REFERENCE_TYPE_CONTENT",referenceImage:this.referenceImage,referenceId:this.referenceId}}},e.ControlReferenceImage=class{toReferenceImageAPI(){return{referenceType:"REFERENCE_TYPE_CONTROL",referenceImage:this.referenceImage,referenceId:this.referenceId,controlImageConfig:this.config}}},e.CountTokensResponse=Ne,e.CreateFileResponse=je,e.DeleteCachedContentResponse=xe,e.DeleteFileResponse=Ve,e.DeleteModelResponse=we,e.EditImageResponse=Ae,e.EmbedContentResponse=_e,e.Files=An,e.FunctionResponse=class{},e.FunctionResponseBlob=class{},e.FunctionResponseFileData=class{},e.FunctionResponsePart=class{},e.GenerateContentResponse=Ie,e.GenerateContentResponsePromptFeedback=class{},e.GenerateContentResponseUsageMetadata=class{},e.GenerateImagesResponse=Se,e.GenerateVideosOperation=Me,e.GenerateVideosResponse=class{},e.GoogleGenAI=class{get interactions(){var e;if(void 0!==this._interactions)return this._interactions;if(console.warn("GoogleGenAI.interactions: Interactions usage is experimental and may change in future versions."),this.vertexai)throw new Error("This version of the GenAI SDK does not support Vertex AI API for interactions.");const t=this.httpOptions;(null==t?void 0:t.extraBody)&&console.warn("GoogleGenAI.interactions: Client level httpOptions.extraBody is not supported by the interactions client and will be ignored.");const n=new Fo({baseURL:this.apiClient.getBaseUrl(),apiKey:this.apiKey,apiVersion:this.apiClient.getApiVersion(),clientAdapter:this.apiClient,defaultHeaders:this.apiClient.getDefaultHeaders(),timeout:null==t?void 0:t.timeout,maxRetries:null===(e=null==t?void 0:t.retryOptions)||void 0===e?void 0:e.attempts});return this._interactions=n.interactions,this._interactions}constructor(e){var t;if(null==e.apiKey)throw new Error(`An API Key must be set when running in an unspecified environment.\n + ${gn().message}`);this.vertexai=null!==(t=e.vertexai)&&void 0!==t&&t,this.apiKey=e.apiKey,this.apiVersion=e.apiVersion,this.httpOptions=e.httpOptions;const n=new dr(this.apiKey);this.apiClient=new fn({auth:n,apiVersion:this.apiVersion,apiKey:this.apiKey,vertexai:this.vertexai,httpOptions:this.httpOptions,userAgentExtra:"gl-node/cross",uploader:new En,downloader:new yn}),this.models=new Xi(this.apiClient),this.live=new Bi(this.apiClient,n,new _n),this.chats=new nn(this.models,this.apiClient),this.batches=new Gt(this.apiClient),this.caches=new Yt(this.apiClient),this.files=new An(this.apiClient),this.operations=new Qi(this.apiClient),this.authTokens=new nr(this.apiClient),this.tunings=new cr(this.apiClient),this.fileSearchStores=new Rn(this.apiClient)}},e.HttpResponse=Te,e.ImportFileOperation=Fe,e.ImportFileResponse=class{},e.InlinedEmbedContentResponse=class{},e.InlinedResponse=class{},e.ListBatchJobsResponse=Je,e.ListCachedContentsResponse=Le,e.ListDocumentsResponse=ke,e.ListFileSearchStoresResponse=qe,e.ListFilesResponse=He,e.ListModelsResponse=Re,e.ListTuningJobsResponse=De,e.Live=Bi,e.LiveClientToolResponse=class{},e.LiveMusicServerMessage=Ye,e.LiveSendToolResponseParameters=class{constructor(){this.functionResponses=[]}},e.LiveServerMessage=$e,e.MaskReferenceImage=class{toReferenceImageAPI(){return{referenceType:"REFERENCE_TYPE_MASK",referenceImage:this.referenceImage,referenceId:this.referenceId,maskImageConfig:this.config}}},e.Models=Xi,e.Operations=Qi,e.Pager=qt,e.RawReferenceImage=class{toReferenceImageAPI(){return{referenceType:"REFERENCE_TYPE_RAW",referenceImage:this.referenceImage,referenceId:this.referenceId}}},e.RecontextImageResponse=Oe,e.RegisterFilesResponse=Be,e.ReplayResponse=class{},e.SegmentImageResponse=be,e.Session=$i,e.SingleEmbedContentResponse=class{},e.StyleReferenceImage=class{toReferenceImageAPI(){return{referenceType:"REFERENCE_TYPE_STYLE",referenceImage:this.referenceImage,referenceId:this.referenceId,styleImageConfig:this.config}}},e.SubjectReferenceImage=class{toReferenceImageAPI(){return{referenceType:"REFERENCE_TYPE_SUBJECT",referenceImage:this.referenceImage,referenceId:this.referenceId,subjectImageConfig:this.config}}},e.Tokens=nr,e.UploadToFileSearchStoreOperation=Ke,e.UploadToFileSearchStoreResponse=class{},e.UploadToFileSearchStoreResumableResponse=Ge,e.UpscaleImageResponse=Ce,e.createFunctionResponsePartFromBase64=function(e,t){return{inlineData:{data:e,mimeType:t}}},e.createFunctionResponsePartFromUri=function(e,t){return{fileData:{fileUri:e,mimeType:t}}},e.createModelContent=function(e){return{role:"model",parts:Ee(e)}},e.createPartFromBase64=function(e,t,n){return Object.assign({inlineData:{data:e,mimeType:t}},n&&{mediaResolution:{level:n}})},e.createPartFromCodeExecutionResult=function(e,t){return{codeExecutionResult:{outcome:e,output:t}}},e.createPartFromExecutableCode=function(e,t){return{executableCode:{code:e,language:t}}},e.createPartFromFunctionCall=function(e,t){return{functionCall:{name:e,args:t}}},e.createPartFromFunctionResponse=function(e,t,n,o=[]){return{functionResponse:Object.assign({id:e,name:t,response:n},o.length>0&&{parts:o})}},e.createPartFromText=ye,e.createPartFromUri=function(e,t,n){return Object.assign({fileData:{fileUri:e,mimeType:t}},n&&{mediaResolution:{level:n}})},e.createUserContent=function(e){return{role:"user",parts:Ee(e)}},e.mcpToTool=function(...e){if(Li=!0,0===e.length)throw new Error("No MCP clients provided");const t=e[e.length-1];return null!==(n=t)&&"object"==typeof n&&"listTools"in n&&"function"==typeof n.listTools?Hi.create(e,{}):Hi.create(e.slice(0,e.length-1),t);var n},e.setDefaultBaseUrls=function(e){e.geminiUrl,e.vertexUrl}}(y)),y}function A(){if(c)return u;return c=1,u={getExtractionPrompt:function(){return'\nTu es un moteur d\'extraction et de classification spécialisé dans les factures du secteur mécanique automobile.\n\nTa tâche est d’analyser le texte fourni.\n\nIMPORTANT :\n- Si le document n’est PAS clairement une facture, retourne STRICTEMENT : null\n- Sinon retourne UNIQUEMENT un JSON valide correspondant au schéma.\nLe JSON doit respecter STRICTEMENT cette structure :\n\n{\n "reference": string | null,\n "date": string | null,\n "supplier": string | null,\n "customer": string | null,\n "totalAmount": number | null,\n "currency": string | null,\n "address": string | null,\n "items": [\n {\n "description": string,\n "quantity": number | null,\n "unitPrice": number | null,\n "totalPrice": number | null,\n "category": string | null\n }\n ],\n "taxAmount": number | null,\n "language": string | null\n}\n\nCATEGORIES AUTORISÉES (liste fermée) :\n\n- carrosserie\n- depannage\n- entretien_preventif\n- reparation_curative\n- diagnostic_electronique\n- autre\n\nRÈGLES DE CLASSIFICATION :\n\nAnalyse la description de chaque article et classe-le dans UNE SEULE catégorie :\n\n- carrosserie → peinture, tôle, choc, pare-chocs, aile, redressage\n- depannage → remorquage, dépannage route, batterie à plat\n- entretien_preventif → vidange, filtres, révision, entretien périodique\n- reparation_curative → remplacement pièce, réparation moteur, frein, embrayage\n- diagnostic_electronique → valise, scanner OBD, diagnostic calculateur\n\nSi aucune catégorie ne correspond clairement → "autre".\n\nRÈGLES GÉNÉRALES :\n\n1. Retourne UNIQUEMENT :\n - soit null\n - soit un JSON valide.\n2. Aucun texte explicatif.\n3. Aucun markdown.\n4. Si une donnée est absente → null.\n5. Les montants doivent être des NOMBRES.\n6. Utilise "." comme séparateur décimal.\n7. Date format YYYY-MM-DD ou null.\n8. Devise normalisée (EUR, USD, MAD...).\n9. Ne déduis aucune information absente explicitement.\n10. Une seule catégorie par item.\n\nAnalyse maintenant le texte suivant :\n'},getTasksCreationPrompt:function(e,t){return`\n CONTEXTE: Creation de tâches dans une solution de fleet management system.\n Tu es le responsable de park en maintenance de flottes(automobiles, camions, vehicules). \n Les taches sont le moyen de communiquer entre les personnes impliquées dans la gestion de resolution de l'intervention.\n Tu reçois les signalement des chauffeurs sur l'état de leurs véhicules. \n\n À partir de l'intervention, génère un tableau JSON de tâches détaillées et structurées.\n Tu pourrais recevoir un audio ou une photo descriptive de l'intervention ou de la panne.\n Il faudra les analyser pour en extraire des informations utiles à la création des tâches.\n Genere uniquement des taches principales relatives à la resolution de l'intervention.'\n \n **Titre :** ${e}\n **Description :** ${t}\n Réponds UNIQUEMENT avec un tableau JSON valide (sans markdown, sans explication), en suivant exactement ce format :\n [\n {\n "title": "Titre de la tâche",\n "description": "Description détaillée",\n "category": "catégorie de la tache(exemple: mécanique, electric, pneumatique,..)"\n }\n ]`},cleanJsonResponse:function(e){return e.replace(/```json/g,"").replace(/```/g,"").trim()},getMimeType:function(e){return{jpg:"image/jpeg",jpeg:"image/jpeg",png:"image/png",webp:"image/webp",mp3:"audio/mpeg",wav:"audio/wav"}[e.replace(".","").toLowerCase()]}}}var C=t(function(){if(g)return m;g=1;const{GoogleGenAI:t}=S(),{extractFromBase64:n}=function(){if(d)return p;d=1;const t=e,{getExtractionPrompt:n}=A();return p={extractFromBase64:async function(e,o,i){if(!i)return null;if(!e)throw new Error("InvoiceExtractor not initialized. Call init() first.");let r,s=i;const l=i.match(/^data:(.*);base64,(.*)$/);if(l)r=l[1],s=l[2];else{const e=Buffer.from(i,"base64"),n=await t(e);if(!n)throw new Error("Unable to detect file type");r=n.mime}const a=await e.models.generateContent({model:o,contents:[{role:"user",parts:[{inlineData:{mimeType:r,data:s}},{text:n()}]}]});if(!a?.text)return null;const u=a.text.replace(/```json|```/g,"").trim();return JSON.parse(u)}}}(),{generateTasks:o}=function(){if(f)return h;f=1;const{cleanJsonResponse:e,getMimeType:t,getTasksCreationPrompt:n}=A();return h={generateTasks:async function(o,i,r,s,l,a){if(!r||!s)throw new Error("Le titre et la description sont obligatoires.");if(!o)throw new Error("TasksGenerator not initialized. Call init() first.");const u=[];l&&u.push({inlineData:{mimeType:t(l.extension),data:Buffer.from(l.buffer).toString("base64")}}),a&&u.push({inlineData:{mimeType:t(a.extension),data:Buffer.from(a.buffer).toString("base64")}}),u.push({text:n(r,s)});const c=await o.models.generateContent({model:i,contents:[{role:"user",parts:u}],generationConfig:{maxOutputTokens:2048,temperature:.2}}),p=c.candidates?.[0]?.content?.parts?.[0]?.text?.trim();if(!p)throw new Error("Réponse vide du modèle.");const d=JSON.parse(e(p));if(!Array.isArray(d))throw new Error("La réponse n'est pas un tableau JSON.");return d}}}();return m=new class{#e;#t;init({apiKey:e,model:n}={}){const o=e??process.env.AI_API_KEY,i=n??process.env.AI_MODEL??"gemini-2.5-flash";if(!o)throw new Error("API key is required. Provide it via init() or AI_API_KEY env variable.");return this.#e=new t({apiKey:o}),this.#t=i,this}extract(e){if(!this.#e)throw new Error("AiModule not initialized. Call init() first.");return n(this.#e,this.#t,e)}generateTasks(e,t,n,i){if(!this.#e)throw new Error("AiModule not initialized. Call init() first.");return o(this.#e,this.#t,e,t,n,i)}}}());export{C as default};
300
+ */e.ApiError=pn,e.Batches=Gt,e.Caches=Yt,e.CancelTuningJobResponse=Ue,e.Chat=on,e.Chats=nn,e.ComputeTokensResponse=Pe,e.ContentReferenceImage=class{toReferenceImageAPI(){return{referenceType:"REFERENCE_TYPE_CONTENT",referenceImage:this.referenceImage,referenceId:this.referenceId}}},e.ControlReferenceImage=class{toReferenceImageAPI(){return{referenceType:"REFERENCE_TYPE_CONTROL",referenceImage:this.referenceImage,referenceId:this.referenceId,controlImageConfig:this.config}}},e.CountTokensResponse=Ne,e.CreateFileResponse=je,e.DeleteCachedContentResponse=xe,e.DeleteFileResponse=Ve,e.DeleteModelResponse=we,e.EditImageResponse=Ae,e.EmbedContentResponse=_e,e.Files=An,e.FunctionResponse=class{},e.FunctionResponseBlob=class{},e.FunctionResponseFileData=class{},e.FunctionResponsePart=class{},e.GenerateContentResponse=Ie,e.GenerateContentResponsePromptFeedback=class{},e.GenerateContentResponseUsageMetadata=class{},e.GenerateImagesResponse=Se,e.GenerateVideosOperation=Me,e.GenerateVideosResponse=class{},e.GoogleGenAI=class{get interactions(){var e;if(void 0!==this._interactions)return this._interactions;if(console.warn("GoogleGenAI.interactions: Interactions usage is experimental and may change in future versions."),this.vertexai)throw new Error("This version of the GenAI SDK does not support Vertex AI API for interactions.");const t=this.httpOptions;(null==t?void 0:t.extraBody)&&console.warn("GoogleGenAI.interactions: Client level httpOptions.extraBody is not supported by the interactions client and will be ignored.");const n=new Fo({baseURL:this.apiClient.getBaseUrl(),apiKey:this.apiKey,apiVersion:this.apiClient.getApiVersion(),clientAdapter:this.apiClient,defaultHeaders:this.apiClient.getDefaultHeaders(),timeout:null==t?void 0:t.timeout,maxRetries:null===(e=null==t?void 0:t.retryOptions)||void 0===e?void 0:e.attempts});return this._interactions=n.interactions,this._interactions}constructor(e){var t;if(null==e.apiKey)throw new Error(`An API Key must be set when running in an unspecified environment.\n + ${gn().message}`);this.vertexai=null!==(t=e.vertexai)&&void 0!==t&&t,this.apiKey=e.apiKey,this.apiVersion=e.apiVersion,this.httpOptions=e.httpOptions;const n=new dr(this.apiKey);this.apiClient=new fn({auth:n,apiVersion:this.apiVersion,apiKey:this.apiKey,vertexai:this.vertexai,httpOptions:this.httpOptions,userAgentExtra:"gl-node/cross",uploader:new En,downloader:new yn}),this.models=new Xi(this.apiClient),this.live=new Bi(this.apiClient,n,new _n),this.chats=new nn(this.models,this.apiClient),this.batches=new Gt(this.apiClient),this.caches=new Yt(this.apiClient),this.files=new An(this.apiClient),this.operations=new Qi(this.apiClient),this.authTokens=new nr(this.apiClient),this.tunings=new cr(this.apiClient),this.fileSearchStores=new Rn(this.apiClient)}},e.HttpResponse=Te,e.ImportFileOperation=Fe,e.ImportFileResponse=class{},e.InlinedEmbedContentResponse=class{},e.InlinedResponse=class{},e.ListBatchJobsResponse=Je,e.ListCachedContentsResponse=Le,e.ListDocumentsResponse=ke,e.ListFileSearchStoresResponse=qe,e.ListFilesResponse=He,e.ListModelsResponse=Re,e.ListTuningJobsResponse=De,e.Live=Bi,e.LiveClientToolResponse=class{},e.LiveMusicServerMessage=Ye,e.LiveSendToolResponseParameters=class{constructor(){this.functionResponses=[]}},e.LiveServerMessage=$e,e.MaskReferenceImage=class{toReferenceImageAPI(){return{referenceType:"REFERENCE_TYPE_MASK",referenceImage:this.referenceImage,referenceId:this.referenceId,maskImageConfig:this.config}}},e.Models=Xi,e.Operations=Qi,e.Pager=qt,e.RawReferenceImage=class{toReferenceImageAPI(){return{referenceType:"REFERENCE_TYPE_RAW",referenceImage:this.referenceImage,referenceId:this.referenceId}}},e.RecontextImageResponse=Oe,e.RegisterFilesResponse=Be,e.ReplayResponse=class{},e.SegmentImageResponse=be,e.Session=$i,e.SingleEmbedContentResponse=class{},e.StyleReferenceImage=class{toReferenceImageAPI(){return{referenceType:"REFERENCE_TYPE_STYLE",referenceImage:this.referenceImage,referenceId:this.referenceId,styleImageConfig:this.config}}},e.SubjectReferenceImage=class{toReferenceImageAPI(){return{referenceType:"REFERENCE_TYPE_SUBJECT",referenceImage:this.referenceImage,referenceId:this.referenceId,subjectImageConfig:this.config}}},e.Tokens=nr,e.UploadToFileSearchStoreOperation=Ke,e.UploadToFileSearchStoreResponse=class{},e.UploadToFileSearchStoreResumableResponse=Ge,e.UpscaleImageResponse=Ce,e.createFunctionResponsePartFromBase64=function(e,t){return{inlineData:{data:e,mimeType:t}}},e.createFunctionResponsePartFromUri=function(e,t){return{fileData:{fileUri:e,mimeType:t}}},e.createModelContent=function(e){return{role:"model",parts:Ee(e)}},e.createPartFromBase64=function(e,t,n){return Object.assign({inlineData:{data:e,mimeType:t}},n&&{mediaResolution:{level:n}})},e.createPartFromCodeExecutionResult=function(e,t){return{codeExecutionResult:{outcome:e,output:t}}},e.createPartFromExecutableCode=function(e,t){return{executableCode:{code:e,language:t}}},e.createPartFromFunctionCall=function(e,t){return{functionCall:{name:e,args:t}}},e.createPartFromFunctionResponse=function(e,t,n,o=[]){return{functionResponse:Object.assign({id:e,name:t,response:n},o.length>0&&{parts:o})}},e.createPartFromText=ye,e.createPartFromUri=function(e,t,n){return Object.assign({fileData:{fileUri:e,mimeType:t}},n&&{mediaResolution:{level:n}})},e.createUserContent=function(e){return{role:"user",parts:Ee(e)}},e.mcpToTool=function(...e){if(Li=!0,0===e.length)throw new Error("No MCP clients provided");const t=e[e.length-1];return null!==(n=t)&&"object"==typeof n&&"listTools"in n&&"function"==typeof n.listTools?Hi.create(e,{}):Hi.create(e.slice(0,e.length-1),t);var n},e.setDefaultBaseUrls=function(e){e.geminiUrl,e.vertexUrl}}(y)),y}function A(){if(c)return u;return c=1,u={getExtractionPrompt:function(){return'\nTu es un moteur d\'extraction et de classification spécialisé dans les factures du secteur mécanique automobile.\n\nTa tâche est d’analyser le texte fourni.\n\nIMPORTANT :\n- Si le document n’est PAS clairement une facture, retourne STRICTEMENT : null\n- Sinon retourne UNIQUEMENT un JSON valide correspondant au schéma.\nLe JSON doit respecter STRICTEMENT cette structure :\n\n{\n "reference": string | null,\n "date": string | null,\n "supplier": string | null,\n "customer": string | null,\n "totalAmount": number | null,\n "currency": string | null,\n "address": string | null,\n "items": [\n {\n "description": string,\n "quantity": number | null,\n "unitPrice": number | null,\n "totalPrice": number | null,\n "category": string | null\n }\n ],\n "taxAmount": number | null,\n "language": string | null\n}\n\nCATEGORIES AUTORISÉES (liste fermée) :\n\n- carrosserie\n- depannage\n- entretien_preventif\n- reparation_curative\n- diagnostic_electronique\n- autre\n\nRÈGLES DE CLASSIFICATION :\n\nAnalyse la description de chaque article et classe-le dans UNE SEULE catégorie :\n\n- carrosserie → peinture, tôle, choc, pare-chocs, aile, redressage\n- depannage → remorquage, dépannage route, batterie à plat\n- entretien_preventif → vidange, filtres, révision, entretien périodique\n- reparation_curative → remplacement pièce, réparation moteur, frein, embrayage\n- diagnostic_electronique → valise, scanner OBD, diagnostic calculateur\n\nSi aucune catégorie ne correspond clairement → "autre".\n\nRÈGLES GÉNÉRALES :\n\n1. Retourne UNIQUEMENT :\n - soit null\n - soit un JSON valide.\n2. Aucun texte explicatif.\n3. Aucun markdown.\n4. Si une donnée est absente → null.\n5. Les montants doivent être des NOMBRES.\n6. Utilise "." comme séparateur décimal.\n7. Date format YYYY-MM-DD ou null.\n8. Devise normalisée (EUR, USD, MAD...).\n9. Ne déduis aucune information absente explicitement.\n10. Une seule catégorie par item.\n\nAnalyse maintenant le texte suivant :\n'},getTasksCreationPrompt:function(e,t){return`\n CONTEXTE: Creation de tâches dans une solution de fleet management system.\n Tu es le responsable de park en maintenance de flottes(automobiles, camions, vehicules). \n Les taches sont le moyen de communiquer entre les personnes impliquées dans la gestion de resolution de l'intervention.\n Tu reçois les signalement des chauffeurs sur l'état de leurs véhicules. \n\n À partir de l'intervention, génère un tableau JSON de tâches détaillées et structurées.\n Tu pourrais recevoir un audio ou une photo descriptive de l'intervention ou de la panne.\n Il faudra les analyser pour en extraire des informations utiles à la création des tâches.\n Genere uniquement des taches principales relatives à la resolution de l'intervention.'\n \n **Titre :** ${e}\n **Description :** ${t}\n Réponds UNIQUEMENT avec un tableau JSON valide (sans markdown, sans explication), en suivant exactement ce format :\n [\n {\n "title": "Titre de la tâche",\n "description": "Description détaillée",\n "category": "catégorie de la tache(exemple: mécanique, electric, pneumatique,..)"\n }\n ]`},cleanJsonResponse:function(e){return e.replace(/```json/g,"").replace(/```/g,"").trim()},getMimeType:function(e){return{jpg:"image/jpeg",jpeg:"image/jpeg",png:"image/png",webp:"image/webp",mp3:"audio/mpeg",wav:"audio/wav"}[e.replace(".","").toLowerCase()]}}}var C=t(function(){if(g)return m;g=1;const{GoogleGenAI:t}=S(),{extractFromBase64:n}=function(){if(d)return p;d=1;const{fromBuffer:t}=e,{getExtractionPrompt:n}=A();return p={extractFromBase64:async function(e,o,i){if(!i)return null;if(!e)throw new Error("InvoiceExtractor not initialized. Call init() first.");let r,s=i;const l=i.match(/^data:(.*);base64,(.*)$/);if(l)r=l[1],s=l[2];else{const e=Buffer.from(i,"base64"),n=await t(e);if(!n)throw new Error("Unable to detect file type");r=n.mime}const a=await e.models.generateContent({model:o,contents:[{role:"user",parts:[{inlineData:{mimeType:r,data:s}},{text:n()}]}]});if(!a?.text)return null;const u=a.text.replace(/```json|```/g,"").trim();return JSON.parse(u)}}}(),{generateTasks:o}=function(){if(f)return h;f=1;const{cleanJsonResponse:e,getMimeType:t,getTasksCreationPrompt:n}=A();return h={generateTasks:async function(o,i,r,s,l,a){if(!r||!s)throw new Error("Le titre et la description sont obligatoires.");if(!o)throw new Error("TasksGenerator not initialized. Call init() first.");const u=[];l&&u.push({inlineData:{mimeType:t(l.extension),data:Buffer.from(l.buffer).toString("base64")}}),a&&u.push({inlineData:{mimeType:t(a.extension),data:Buffer.from(a.buffer).toString("base64")}}),u.push({text:n(r,s)});const c=await o.models.generateContent({model:i,contents:[{role:"user",parts:u}],generationConfig:{maxOutputTokens:2048,temperature:.2}}),p=c.candidates?.[0]?.content?.parts?.[0]?.text?.trim();if(!p)throw new Error("Réponse vide du modèle.");const d=JSON.parse(e(p));if(!Array.isArray(d))throw new Error("La réponse n'est pas un tableau JSON.");return d}}}();return m=new class{#e;#t;init({apiKey:e,model:n}={}){const o=e??process.env.AI_API_KEY,i=n??process.env.AI_MODEL??"gemini-2.5-flash";if(!o)throw new Error("API key is required. Provide it via init() or AI_API_KEY env variable.");return this.#e=new t({apiKey:o}),this.#t=i,this}extract(e){if(!this.#e)throw new Error("AiModule not initialized. Call init() first.");return n(this.#e,this.#t,e)}generateTasks(e,t,n,i){if(!this.#e)throw new Error("AiModule not initialized. Call init() first.");return o(this.#e,this.#t,e,t,n,i)}}}());export{C as default};
package/package.json CHANGED
@@ -1,15 +1,17 @@
1
1
  {
2
2
  "name": "@omniyat/aimodule",
3
- "version": "1.0.2",
4
- "description": "A Node.js package that scans files in a specified directory, extracts text using OCR, and generates summaries using the Google GenAI API.",
3
+ "version": "1.0.4",
4
+ "description": "A Node.js package that extract invoice from file and generate tasksGoogle GenAI API.",
5
5
  "type": "commonjs",
6
- "exports": "./dist/index.cjs",
6
+ "main": "dist/index.cjs",
7
7
  "scripts": {
8
8
  "build": "rollup -c rollup.config.cjs",
9
9
  "prepare": "npm run build",
10
+ "publish": "npm publish --access=public",
10
11
  "lint": "eslint .",
11
12
  "test": "node --env-file=.env src/tests/index.js"
12
13
  },
14
+ "exports": "./dist/index.cjs",
13
15
  "files": [
14
16
  "dist"
15
17
  ],
@@ -29,7 +31,7 @@
29
31
  "@rollup/plugin-node-resolve": "^16.0.3",
30
32
  "@rollup/plugin-terser": "^0.4.4",
31
33
  "dotenv": "^17.3.1",
32
- "file-type": "^21.3.0"
34
+ "file-type": "^16.5.4"
33
35
  },
34
36
  "devDependencies": {
35
37
  "@rollup/plugin-commonjs": "^29.0.0",