firebase
Version:
Firebase JavaScript library for web and Node.js
4 lines (2 loc) • 35.8 kB
JavaScript
import{_isFirebaseServerApp as e,_getProvider,getApp as t,_registerComponent as n,registerVersion as s}from"https://www.gstatic.com/firebasejs/12.1.0/firebase-app.js";class FirebaseError extends Error{constructor(e,t,n){super(t),this.code=e,this.customData=n,this.name="FirebaseError",Object.setPrototypeOf(this,FirebaseError.prototype),Error.captureStackTrace&&Error.captureStackTrace(this,ErrorFactory.prototype.create)}}class ErrorFactory{constructor(e,t,n){this.service=e,this.serviceName=t,this.errors=n}create(e,...t){const n=t[0]||{},s=`${this.service}/${e}`,r=this.errors[e],a=r?function replaceTemplate(e,t){return e.replace(o,((e,n)=>{const s=t[n];return null!=s?String(s):`<${n}?>`}))}(r,n):"Error",i=`${this.serviceName}: ${a} (${s}).`;return new FirebaseError(s,i,n)}}const o=/\{\$([^}]+)}/g;class Component{constructor(e,t,n){this.name=e,this.instanceFactory=t,this.type=n,this.multipleInstances=!1,this.serviceProps={},this.instantiationMode="LAZY",this.onInstanceCreated=null}setInstantiationMode(e){return this.instantiationMode=e,this}setMultipleInstances(e){return this.multipleInstances=e,this}setServiceProps(e){return this.serviceProps=e,this}setInstanceCreatedCallback(e){return this.onInstanceCreated=e,this}}var r;!function(e){e[e.DEBUG=0]="DEBUG",e[e.VERBOSE=1]="VERBOSE",e[e.INFO=2]="INFO",e[e.WARN=3]="WARN",e[e.ERROR=4]="ERROR",e[e.SILENT=5]="SILENT"}(r||(r={}));const a={debug:r.DEBUG,verbose:r.VERBOSE,info:r.INFO,warn:r.WARN,error:r.ERROR,silent:r.SILENT},i=r.INFO,c={[r.DEBUG]:"log",[r.VERBOSE]:"log",[r.INFO]:"info",[r.WARN]:"warn",[r.ERROR]:"error"},defaultLogHandler=(e,t,...n)=>{if(t<e.logLevel)return;const s=(new Date).toISOString(),o=c[t];if(!o)throw new Error(`Attempted to log a message with an invalid logType (value: ${t})`);console[o](`[${s}] ${e.name}:`,...n)};var d="@firebase/ai",l="2.1.0";const p="AI",h="us-central1",u=l,g=["user","model","function","system"],m={HARM_CATEGORY_HATE_SPEECH:"HARM_CATEGORY_HATE_SPEECH",HARM_CATEGORY_SEXUALLY_EXPLICIT:"HARM_CATEGORY_SEXUALLY_EXPLICIT",HARM_CATEGORY_HARASSMENT:"HARM_CATEGORY_HARASSMENT",HARM_CATEGORY_DANGEROUS_CONTENT:"HARM_CATEGORY_DANGEROUS_CONTENT"},f={BLOCK_LOW_AND_ABOVE:"BLOCK_LOW_AND_ABOVE",BLOCK_MEDIUM_AND_ABOVE:"BLOCK_MEDIUM_AND_ABOVE",BLOCK_ONLY_HIGH:"BLOCK_ONLY_HIGH",BLOCK_NONE:"BLOCK_NONE",OFF:"OFF"},E={SEVERITY:"SEVERITY",PROBABILITY:"PROBABILITY"},I={NEGLIGIBLE:"NEGLIGIBLE",LOW:"LOW",MEDIUM:"MEDIUM",HIGH:"HIGH"},R={HARM_SEVERITY_NEGLIGIBLE:"HARM_SEVERITY_NEGLIGIBLE",HARM_SEVERITY_LOW:"HARM_SEVERITY_LOW",HARM_SEVERITY_MEDIUM:"HARM_SEVERITY_MEDIUM",HARM_SEVERITY_HIGH:"HARM_SEVERITY_HIGH",HARM_SEVERITY_UNSUPPORTED:"HARM_SEVERITY_UNSUPPORTED"},O={SAFETY:"SAFETY",OTHER:"OTHER",BLOCKLIST:"BLOCKLIST",PROHIBITED_CONTENT:"PROHIBITED_CONTENT"},A={STOP:"STOP",MAX_TOKENS:"MAX_TOKENS",SAFETY:"SAFETY",RECITATION:"RECITATION",OTHER:"OTHER",BLOCKLIST:"BLOCKLIST",PROHIBITED_CONTENT:"PROHIBITED_CONTENT",SPII:"SPII",MALFORMED_FUNCTION_CALL:"MALFORMED_FUNCTION_CALL"},y={AUTO:"AUTO",ANY:"ANY",NONE:"NONE"},S={MODALITY_UNSPECIFIED:"MODALITY_UNSPECIFIED",TEXT:"TEXT",IMAGE:"IMAGE",VIDEO:"VIDEO",AUDIO:"AUDIO",DOCUMENT:"DOCUMENT"},_={TEXT:"TEXT",IMAGE:"IMAGE"},T={PREFER_ON_DEVICE:"prefer_on_device",ONLY_ON_DEVICE:"only_on_device",ONLY_IN_CLOUD:"only_in_cloud"},C={ERROR:"error",REQUEST_ERROR:"request-error",RESPONSE_ERROR:"response-error",FETCH_ERROR:"fetch-error",INVALID_CONTENT:"invalid-content",API_NOT_ENABLED:"api-not-enabled",INVALID_SCHEMA:"invalid-schema",NO_API_KEY:"no-api-key",NO_APP_ID:"no-app-id",NO_MODEL:"no-model",NO_PROJECT_ID:"no-project-id",PARSE_FAILED:"parse-failed",UNSUPPORTED:"unsupported"},N={STRING:"string",NUMBER:"number",INTEGER:"integer",BOOLEAN:"boolean",ARRAY:"array",OBJECT:"object"},w={BLOCK_LOW_AND_ABOVE:"block_low_and_above",BLOCK_MEDIUM_AND_ABOVE:"block_medium_and_above",BLOCK_ONLY_HIGH:"block_only_high",BLOCK_NONE:"block_none"},b={BLOCK_ALL:"dont_allow",ALLOW_ADULT:"allow_adult",ALLOW_ALL:"allow_all"},L={SQUARE:"1:1",LANDSCAPE_3x4:"3:4",PORTRAIT_4x3:"4:3",LANDSCAPE_16x9:"16:9",PORTRAIT_9x16:"9:16"},P={VERTEX_AI:"VERTEX_AI",GOOGLE_AI:"GOOGLE_AI"};class Backend{constructor(e){this.backendType=e}}class GoogleAIBackend extends Backend{constructor(){super(P.GOOGLE_AI)}}class VertexAIBackend extends Backend{constructor(e=h){super(P.VERTEX_AI),this.location=e||h}}class AIService{constructor(e,t,n,s){this.app=e,this.backend=t;const o=s?.getImmediate({optional:!0}),r=n?.getImmediate({optional:!0});this.auth=r||null,this.appCheck=o||null,this.location=t instanceof VertexAIBackend?t.location:""}_delete(){return Promise.resolve()}}class AIError extends FirebaseError{constructor(e,t,n){const s=`${p}: ${t} (${`${p}/${e}`})`;super(e,s),this.code=e,this.customErrorData=n,Error.captureStackTrace&&Error.captureStackTrace(this,AIError),Object.setPrototypeOf(this,AIError.prototype),this.toString=()=>s}}class AIModel{constructor(t,n){if(!t.app?.options?.apiKey)throw new AIError(C.NO_API_KEY,'The "apiKey" field is empty in the local Firebase config. Firebase AI requires this field to contain a valid API key.');if(!t.app?.options?.projectId)throw new AIError(C.NO_PROJECT_ID,'The "projectId" field is empty in the local Firebase config. Firebase AI requires this field to contain a valid project ID.');if(!t.app?.options?.appId)throw new AIError(C.NO_APP_ID,'The "appId" field is empty in the local Firebase config. Firebase AI requires this field to contain a valid app ID.');if(this._apiSettings={apiKey:t.app.options.apiKey,project:t.app.options.projectId,appId:t.app.options.appId,automaticDataCollectionEnabled:t.app.automaticDataCollectionEnabled,location:t.location,backend:t.backend},e(t.app)&&t.app.settings.appCheckToken){const e=t.app.settings.appCheckToken;this._apiSettings.getAppCheckToken=()=>Promise.resolve({token:e})}else t.appCheck&&(this._apiSettings.getAppCheckToken=()=>t.appCheck.getToken());t.auth&&(this._apiSettings.getAuthToken=()=>t.auth.getToken()),this.model=AIModel.normalizeModelName(n,this._apiSettings.backend.backendType)}static normalizeModelName(e,t){return t===P.GOOGLE_AI?AIModel.normalizeGoogleAIModelName(e):AIModel.normalizeVertexAIModelName(e)}static normalizeGoogleAIModelName(e){return`models/${e}`}static normalizeVertexAIModelName(e){let t;return t=e.includes("/")?e.startsWith("models/")?`publishers/google/${e}`:e:`publishers/google/models/${e}`,t}}const M=new class Logger{constructor(e){this.name=e,this._logLevel=i,this._logHandler=defaultLogHandler,this._userLogHandler=null}get logLevel(){return this._logLevel}set logLevel(e){if(!(e in r))throw new TypeError(`Invalid value "${e}" assigned to \`logLevel\``);this._logLevel=e}setLogLevel(e){this._logLevel="string"==typeof e?a[e]:e}get logHandler(){return this._logHandler}set logHandler(e){if("function"!=typeof e)throw new TypeError("Value assigned to `logHandler` must be a function");this._logHandler=e}get userLogHandler(){return this._userLogHandler}set userLogHandler(e){this._userLogHandler=e}debug(...e){this._userLogHandler&&this._userLogHandler(this,r.DEBUG,...e),this._logHandler(this,r.DEBUG,...e)}log(...e){this._userLogHandler&&this._userLogHandler(this,r.VERBOSE,...e),this._logHandler(this,r.VERBOSE,...e)}info(...e){this._userLogHandler&&this._userLogHandler(this,r.INFO,...e),this._logHandler(this,r.INFO,...e)}warn(...e){this._userLogHandler&&this._userLogHandler(this,r.WARN,...e),this._logHandler(this,r.WARN,...e)}error(...e){this._userLogHandler&&this._userLogHandler(this,r.ERROR,...e),this._logHandler(this,r.ERROR,...e)}}("@firebase/vertexai");var v;!function(e){e.GENERATE_CONTENT="generateContent",e.STREAM_GENERATE_CONTENT="streamGenerateContent",e.COUNT_TOKENS="countTokens",e.PREDICT="predict"}(v||(v={}));class RequestUrl{constructor(e,t,n,s,o){this.model=e,this.task=t,this.apiSettings=n,this.stream=s,this.requestOptions=o}toString(){const e=new URL(this.baseUrl);return e.pathname=`/${this.apiVersion}/${this.modelPath}:${this.task}`,e.search=this.queryParams.toString(),e.toString()}get baseUrl(){return this.requestOptions?.baseUrl||"https://firebasevertexai.googleapis.com"}get apiVersion(){return"v1beta"}get modelPath(){if(this.apiSettings.backend instanceof GoogleAIBackend)return`projects/${this.apiSettings.project}/${this.model}`;if(this.apiSettings.backend instanceof VertexAIBackend)return`projects/${this.apiSettings.project}/locations/${this.apiSettings.backend.location}/${this.model}`;throw new AIError(C.ERROR,`Invalid backend: ${JSON.stringify(this.apiSettings.backend)}`)}get queryParams(){const e=new URLSearchParams;return this.stream&&e.set("alt","sse"),e}}async function getHeaders(e){const t=new Headers;if(t.append("Content-Type","application/json"),t.append("x-goog-api-client",function getClientHeaders(){const e=[];return e.push(`gl-js/${u}`),e.push(`fire/${u}`),e.join(" ")}()),t.append("x-goog-api-key",e.apiSettings.apiKey),e.apiSettings.automaticDataCollectionEnabled&&t.append("X-Firebase-Appid",e.apiSettings.appId),e.apiSettings.getAppCheckToken){const n=await e.apiSettings.getAppCheckToken();n&&(t.append("X-Firebase-AppCheck",n.token),n.error&&M.warn(`Unable to obtain a valid App Check token: ${n.error.message}`))}if(e.apiSettings.getAuthToken){const n=await e.apiSettings.getAuthToken();n&&t.append("Authorization",`Firebase ${n.accessToken}`)}return t}async function makeRequest(e,t,n,s,o,r){const a=new RequestUrl(e,t,n,s,r);let i,c;try{const d=await async function constructRequest(e,t,n,s,o,r){const a=new RequestUrl(e,t,n,s,r);return{url:a.toString(),fetchOptions:{method:"POST",headers:await getHeaders(a),body:o}}}(e,t,n,s,o,r),l=null!=r?.timeout&&r.timeout>=0?r.timeout:18e4,p=new AbortController;if(c=setTimeout((()=>p.abort()),l),d.fetchOptions.signal=p.signal,i=await fetch(d.url,d.fetchOptions),!i.ok){let e,t="";try{const n=await i.json();t=n.error.message,n.error.details&&(t+=` ${JSON.stringify(n.error.details)}`,e=n.error.details)}catch(e){}if(403===i.status&&e&&e.some((e=>"SERVICE_DISABLED"===e.reason))&&e.some((e=>e.links?.[0]?.description.includes("Google developers console API activation"))))throw new AIError(C.API_NOT_ENABLED,`The Firebase AI SDK requires the Firebase AI API ('firebasevertexai.googleapis.com') to be enabled in your Firebase project. Enable this API by visiting the Firebase Console at https://console.firebase.google.com/project/${a.apiSettings.project}/genai/ and clicking "Get started". If you enabled this API recently, wait a few minutes for the action to propagate to our systems and then retry.`,{status:i.status,statusText:i.statusText,errorDetails:e});throw new AIError(C.FETCH_ERROR,`Error fetching from ${a}: [${i.status} ${i.statusText}] ${t}`,{status:i.status,statusText:i.statusText,errorDetails:e})}}catch(e){let t=e;throw e.code!==C.FETCH_ERROR&&e.code!==C.API_NOT_ENABLED&&e instanceof Error&&(t=new AIError(C.ERROR,`Error fetching from ${a.toString()}: ${e.message}`),t.stack=e.stack),t}finally{c&&clearTimeout(c)}return i}function createEnhancedContentResponse(e){e.candidates&&!e.candidates[0].hasOwnProperty("index")&&(e.candidates[0].index=0);const t=function addHelpers(e){return e.text=()=>{if(e.candidates&&e.candidates.length>0){if(e.candidates.length>1&&M.warn(`This response had ${e.candidates.length} candidates. Returning text from the first candidate only. Access response.candidates directly to use the other candidates.`),hadBadFinishReason(e.candidates[0]))throw new AIError(C.RESPONSE_ERROR,`Response error: ${formatBlockErrorMessage(e)}. Response body stored in error.response`,{response:e});return function getText(e){const t=[];if(e.candidates?.[0].content?.parts)for(const n of e.candidates?.[0].content?.parts)n.text&&t.push(n.text);return t.length>0?t.join(""):""}(e)}if(e.promptFeedback)throw new AIError(C.RESPONSE_ERROR,`Text not available. ${formatBlockErrorMessage(e)}`,{response:e});return""},e.inlineDataParts=()=>{if(e.candidates&&e.candidates.length>0){if(e.candidates.length>1&&M.warn(`This response had ${e.candidates.length} candidates. Returning data from the first candidate only. Access response.candidates directly to use the other candidates.`),hadBadFinishReason(e.candidates[0]))throw new AIError(C.RESPONSE_ERROR,`Response error: ${formatBlockErrorMessage(e)}. Response body stored in error.response`,{response:e});return function getInlineDataParts(e){const t=[];if(e.candidates?.[0].content?.parts)for(const n of e.candidates?.[0].content?.parts)n.inlineData&&t.push(n);return t.length>0?t:void 0}(e)}if(e.promptFeedback)throw new AIError(C.RESPONSE_ERROR,`Data not available. ${formatBlockErrorMessage(e)}`,{response:e})},e.functionCalls=()=>{if(e.candidates&&e.candidates.length>0){if(e.candidates.length>1&&M.warn(`This response had ${e.candidates.length} candidates. Returning function calls from the first candidate only. Access response.candidates directly to use the other candidates.`),hadBadFinishReason(e.candidates[0]))throw new AIError(C.RESPONSE_ERROR,`Response error: ${formatBlockErrorMessage(e)}. Response body stored in error.response`,{response:e});return function getFunctionCalls(e){const t=[];if(e.candidates?.[0].content?.parts)for(const n of e.candidates?.[0].content?.parts)n.functionCall&&t.push(n.functionCall);return t.length>0?t:void 0}(e)}if(e.promptFeedback)throw new AIError(C.RESPONSE_ERROR,`Function call not available. ${formatBlockErrorMessage(e)}`,{response:e})},e}(e);return t}const k=[A.RECITATION,A.SAFETY];function hadBadFinishReason(e){return!!e.finishReason&&k.some((t=>t===e.finishReason))}function formatBlockErrorMessage(e){let t="";if(e.candidates&&0!==e.candidates.length||!e.promptFeedback){if(e.candidates?.[0]){const n=e.candidates[0];hadBadFinishReason(n)&&(t+=`Candidate was blocked due to ${n.finishReason}`,n.finishMessage&&(t+=`: ${n.finishMessage}`))}}else t+="Response was blocked",e.promptFeedback?.blockReason&&(t+=` due to ${e.promptFeedback.blockReason}`),e.promptFeedback?.blockReasonMessage&&(t+=`: ${e.promptFeedback.blockReasonMessage}`);return t}async function handlePredictResponse(e){const t=await e.json(),n=[];let s;if(!t.predictions||0===t.predictions?.length)throw new AIError(C.RESPONSE_ERROR,"No predictions or filtered reason received from Vertex AI. Please report this issue with the full error details at https://github.com/firebase/firebase-js-sdk/issues.");for(const e of t.predictions)if(e.raiFilteredReason)s=e.raiFilteredReason;else if(e.mimeType&&e.bytesBase64Encoded)n.push({mimeType:e.mimeType,bytesBase64Encoded:e.bytesBase64Encoded});else{if(!e.mimeType||!e.gcsUri)throw new AIError(C.RESPONSE_ERROR,`Predictions array in response has missing properties. Response: ${JSON.stringify(t)}`);n.push({mimeType:e.mimeType,gcsURI:e.gcsUri})}return{images:n,filteredReason:s}}function mapGenerateContentRequest(e){if(e.safetySettings?.forEach((e=>{if(e.method)throw new AIError(C.UNSUPPORTED,"SafetySetting.method is not supported in the the Gemini Developer API. Please remove this property.")})),e.generationConfig?.topK){const t=Math.round(e.generationConfig.topK);t!==e.generationConfig.topK&&(M.warn("topK in GenerationConfig has been rounded to the nearest integer to match the format for requests to the Gemini Developer API."),e.generationConfig.topK=t)}return e}function mapGenerateContentResponse(e){return{candidates:e.candidates?mapGenerateContentCandidates(e.candidates):void 0,prompt:e.promptFeedback?mapPromptFeedback(e.promptFeedback):void 0,usageMetadata:e.usageMetadata}}function mapGenerateContentCandidates(e){const t=[];let n;return t&&e.forEach((e=>{let s;if(e.citationMetadata&&(s={citations:e.citationMetadata.citationSources}),e.safetyRatings&&(n=e.safetyRatings.map((e=>({...e,severity:e.severity??R.HARM_SEVERITY_UNSUPPORTED,probabilityScore:e.probabilityScore??0,severityScore:e.severityScore??0})))),e.content?.parts.some((e=>e?.videoMetadata)))throw new AIError(C.UNSUPPORTED,"Part.videoMetadata is not supported in the Gemini Developer API. Please remove this property.");const o={index:e.index,content:e.content,finishReason:e.finishReason,finishMessage:e.finishMessage,safetyRatings:n,citationMetadata:s,groundingMetadata:e.groundingMetadata};t.push(o)})),t}function mapPromptFeedback(e){const t=[];e.safetyRatings.forEach((e=>{t.push({category:e.category,probability:e.probability,severity:e.severity??R.HARM_SEVERITY_UNSUPPORTED,probabilityScore:e.probabilityScore??0,severityScore:e.severityScore??0,blocked:e.blocked})}));return{blockReason:e.blockReason,safetyRatings:t,blockReasonMessage:e.blockReasonMessage}}const D=/^data\: (.*)(?:\n\n|\r\r|\r\n\r\n)/;function processStream(e,t){const n=function getResponseStream(e){const t=e.getReader();return new ReadableStream({start(e){let n="";return pump();function pump(){return t.read().then((({value:t,done:s})=>{if(s)return n.trim()?void e.error(new AIError(C.PARSE_FAILED,"Failed to parse stream")):void e.close();n+=t;let o,r=n.match(D);for(;r;){try{o=JSON.parse(r[1])}catch(t){return void e.error(new AIError(C.PARSE_FAILED,`Error parsing JSON response: "${r[1]}`))}e.enqueue(o),n=n.substring(r[0].length),r=n.match(D)}return pump()}))}}})}(e.body.pipeThrough(new TextDecoderStream("utf8",{fatal:!0}))),[s,o]=n.tee();return{stream:generateResponseSequence(s,t),response:getResponsePromise(o,t)}}async function getResponsePromise(e,t){const n=[],s=e.getReader();for(;;){const{done:e,value:o}=await s.read();if(e){let e=aggregateResponses(n);return t.backend.backendType===P.GOOGLE_AI&&(e=mapGenerateContentResponse(e)),createEnhancedContentResponse(e)}n.push(o)}}async function*generateResponseSequence(e,t){const n=e.getReader();for(;;){const{value:e,done:s}=await n.read();if(s)break;let o;o=t.backend.backendType===P.GOOGLE_AI?createEnhancedContentResponse(mapGenerateContentResponse(e)):createEnhancedContentResponse(e),yield o}}function aggregateResponses(e){const t=e[e.length-1],n={promptFeedback:t?.promptFeedback};for(const t of e)if(t.candidates)for(const e of t.candidates){const t=e.index||0;if(n.candidates||(n.candidates=[]),n.candidates[t]||(n.candidates[t]={index:e.index}),n.candidates[t].citationMetadata=e.citationMetadata,n.candidates[t].finishReason=e.finishReason,n.candidates[t].finishMessage=e.finishMessage,n.candidates[t].safetyRatings=e.safetyRatings,n.candidates[t].groundingMetadata=e.groundingMetadata,e.content&&e.content.parts){n.candidates[t].content||(n.candidates[t].content={role:e.content.role||"user",parts:[]});const s={};for(const o of e.content.parts){if(void 0!==o.text){if(""===o.text)continue;s.text=o.text}if(o.functionCall&&(s.functionCall=o.functionCall),0===Object.keys(s).length)throw new AIError(C.INVALID_CONTENT,"Part should have at least one property, but there are none. This is likely caused by a malformed response from the backend.");n.candidates[t].content.parts.push(s)}}}return n}async function generateContentStream(e,t,n,s,o){let r;return r=s&&await s.isAvailable(n)?await s.generateContentStream(n):await async function generateContentStreamOnCloud(e,t,n,s){return e.backend.backendType===P.GOOGLE_AI&&(n=mapGenerateContentRequest(n)),makeRequest(t,v.STREAM_GENERATE_CONTENT,e,!0,JSON.stringify(n),s)}(e,t,n,o),processStream(r,e)}async function generateContent(e,t,n,s,o){let r;r=s&&await s.isAvailable(n)?await s.generateContent(n):await async function generateContentOnCloud(e,t,n,s){return e.backend.backendType===P.GOOGLE_AI&&(n=mapGenerateContentRequest(n)),makeRequest(t,v.GENERATE_CONTENT,e,!1,JSON.stringify(n),s)}(e,t,n,o);const a=await async function processGenerateContentResponse(e,t){const n=await e.json();return t.backend.backendType===P.GOOGLE_AI?mapGenerateContentResponse(n):n}(r,e);return{response:createEnhancedContentResponse(a)}}function formatSystemInstruction(e){if(null!=e)return"string"==typeof e?{role:"system",parts:[{text:e}]}:e.text?{role:"system",parts:[e]}:e.parts?e.role?e:{role:"system",parts:e.parts}:void 0}function formatNewContent(e){let t=[];if("string"==typeof e)t=[{text:e}];else for(const n of e)"string"==typeof n?t.push({text:n}):t.push(n);return function assignRoleToPartsAndValidateSendMessageRequest(e){const t={role:"user",parts:[]},n={role:"function",parts:[]};let s=!1,o=!1;for(const r of e)"functionResponse"in r?(n.parts.push(r),o=!0):(t.parts.push(r),s=!0);if(s&&o)throw new AIError(C.INVALID_CONTENT,"Within a single message, FunctionResponse cannot be mixed with other type of Part in the request for sending chat message.");if(!s&&!o)throw new AIError(C.INVALID_CONTENT,"No Content is provided for sending chat message.");if(s)return t;return n}(t)}function formatGenerateContentInput(e){let t;if(e.contents)t=e;else{t={contents:[formatNewContent(e)]}}return e.systemInstruction&&(t.systemInstruction=formatSystemInstruction(e.systemInstruction)),t}function createPredictRequestBody(e,{gcsURI:t,imageFormat:n,addWatermark:s,numberOfImages:o=1,negativePrompt:r,aspectRatio:a,safetyFilterLevel:i,personFilterLevel:c}){return{instances:[{prompt:e}],parameters:{storageUri:t,negativePrompt:r,sampleCount:o,aspectRatio:a,outputOptions:n,addWatermark:s,safetyFilterLevel:i,personGeneration:c,includeRaiReason:!0}}}const B=["text","inlineData","functionCall","functionResponse"],G={user:["text","inlineData"],function:["functionResponse"],model:["text","functionCall"],system:["text"]},H={user:["model"],function:["model"],model:["user","function"],system:[]};const F="SILENT_ERROR";class ChatSession{constructor(e,t,n,s,o){this.model=t,this.chromeAdapter=n,this.params=s,this.requestOptions=o,this._history=[],this._sendPromise=Promise.resolve(),this._apiSettings=e,s?.history&&(!function validateChatHistory(e){let t=null;for(const n of e){const{role:e,parts:s}=n;if(!t&&"user"!==e)throw new AIError(C.INVALID_CONTENT,`First Content should be with role 'user', got ${e}`);if(!g.includes(e))throw new AIError(C.INVALID_CONTENT,`Each item should include role field. Got ${e} but valid roles are: ${JSON.stringify(g)}`);if(!Array.isArray(s))throw new AIError(C.INVALID_CONTENT,"Content should have 'parts' but property with an array of Parts");if(0===s.length)throw new AIError(C.INVALID_CONTENT,"Each Content should have at least one part");const o={text:0,inlineData:0,functionCall:0,functionResponse:0};for(const e of s)for(const t of B)t in e&&(o[t]+=1);const r=G[e];for(const t of B)if(!r.includes(t)&&o[t]>0)throw new AIError(C.INVALID_CONTENT,`Content with role '${e}' can't contain '${t}' part`);if(t&&!H[e].includes(t.role))throw new AIError(C.INVALID_CONTENT,`Content with role '${e}' can't follow '${t.role}'. Valid previous roles: ${JSON.stringify(H)}`);t=n}}(s.history),this._history=s.history)}async getHistory(){return await this._sendPromise,this._history}async sendMessage(e){await this._sendPromise;const t=formatNewContent(e),n={safetySettings:this.params?.safetySettings,generationConfig:this.params?.generationConfig,tools:this.params?.tools,toolConfig:this.params?.toolConfig,systemInstruction:this.params?.systemInstruction,contents:[...this._history,t]};let s={};return this._sendPromise=this._sendPromise.then((()=>generateContent(this._apiSettings,this.model,n,this.chromeAdapter,this.requestOptions))).then((e=>{if(e.response.candidates&&e.response.candidates.length>0){this._history.push(t);const n={parts:e.response.candidates?.[0].content.parts||[],role:e.response.candidates?.[0].content.role||"model"};this._history.push(n)}else{const t=formatBlockErrorMessage(e.response);t&&M.warn(`sendMessage() was unsuccessful. ${t}. Inspect response object for details.`)}s=e})),await this._sendPromise,s}async sendMessageStream(e){await this._sendPromise;const t=formatNewContent(e),n={safetySettings:this.params?.safetySettings,generationConfig:this.params?.generationConfig,tools:this.params?.tools,toolConfig:this.params?.toolConfig,systemInstruction:this.params?.systemInstruction,contents:[...this._history,t]},s=generateContentStream(this._apiSettings,this.model,n,this.chromeAdapter,this.requestOptions);return this._sendPromise=this._sendPromise.then((()=>s)).catch((e=>{throw new Error(F)})).then((e=>e.response)).then((e=>{if(e.candidates&&e.candidates.length>0){this._history.push(t);const n={...e.candidates[0].content};n.role||(n.role="model"),this._history.push(n)}else{const t=formatBlockErrorMessage(e);t&&M.warn(`sendMessageStream() was unsuccessful. ${t}. Inspect response object for details.`)}})).catch((e=>{e.message!==F&&M.error(e)})),s}}async function countTokens(e,t,n,s,o){return s&&await s.isAvailable(n)?(await s.countTokens(n)).json():async function countTokensOnCloud(e,t,n,s){let o="";if(e.backend.backendType===P.GOOGLE_AI){const e=function mapCountTokensRequest(e,t){return{generateContentRequest:{model:t,...e}}}(n,t);o=JSON.stringify(e)}else o=JSON.stringify(n);return(await makeRequest(t,v.COUNT_TOKENS,e,!1,o,s)).json()}(e,t,n,o)}class GenerativeModel extends AIModel{constructor(e,t,n,s){super(e,t.model),this.chromeAdapter=s,this.generationConfig=t.generationConfig||{},this.safetySettings=t.safetySettings||[],this.tools=t.tools,this.toolConfig=t.toolConfig,this.systemInstruction=formatSystemInstruction(t.systemInstruction),this.requestOptions=n||{}}async generateContent(e){const t=formatGenerateContentInput(e);return generateContent(this._apiSettings,this.model,{generationConfig:this.generationConfig,safetySettings:this.safetySettings,tools:this.tools,toolConfig:this.toolConfig,systemInstruction:this.systemInstruction,...t},this.chromeAdapter,this.requestOptions)}async generateContentStream(e){const t=formatGenerateContentInput(e);return generateContentStream(this._apiSettings,this.model,{generationConfig:this.generationConfig,safetySettings:this.safetySettings,tools:this.tools,toolConfig:this.toolConfig,systemInstruction:this.systemInstruction,...t},this.chromeAdapter,this.requestOptions)}startChat(e){return new ChatSession(this._apiSettings,this.model,this.chromeAdapter,{tools:this.tools,toolConfig:this.toolConfig,systemInstruction:this.systemInstruction,generationConfig:this.generationConfig,safetySettings:this.safetySettings,...e},this.requestOptions)}async countTokens(e){const t=formatGenerateContentInput(e);return countTokens(this._apiSettings,this.model,t,this.chromeAdapter)}}class ImagenModel extends AIModel{constructor(e,t,n){const{model:s,generationConfig:o,safetySettings:r}=t;super(e,s),this.requestOptions=n,this.generationConfig=o,this.safetySettings=r}async generateImages(e){const t=createPredictRequestBody(e,{...this.generationConfig,...this.safetySettings});return handlePredictResponse(await makeRequest(this.model,v.PREDICT,this._apiSettings,!1,JSON.stringify(t),this.requestOptions))}async generateImagesGCS(e,t){const n=createPredictRequestBody(e,{gcsURI:t,...this.generationConfig,...this.safetySettings});return handlePredictResponse(await makeRequest(this.model,v.PREDICT,this._apiSettings,!1,JSON.stringify(n),this.requestOptions))}}var x;!function(e){e.UNAVAILABLE="unavailable",e.DOWNLOADABLE="downloadable",e.DOWNLOADING="downloading",e.AVAILABLE="available"}(x||(x={}));class ChromeAdapterImpl{constructor(e,t,n={createOptions:{expectedInputs:[{type:"image"}]}}){this.languageModelProvider=e,this.mode=t,this.onDeviceParams=n,this.isDownloading=!1}async isAvailable(e){if(!this.mode)return M.debug("On-device inference unavailable because mode is undefined."),!1;if(this.mode===T.ONLY_IN_CLOUD)return M.debug('On-device inference unavailable because mode is "only_in_cloud".'),!1;const t=await this.downloadIfAvailable();if(this.mode===T.ONLY_ON_DEVICE){if(t===x.UNAVAILABLE)throw new AIError(C.API_NOT_ENABLED,"Local LanguageModel API not available in this environment.");return t!==x.DOWNLOADABLE&&t!==x.DOWNLOADING||(M.debug("Waiting for download of LanguageModel to complete."),await this.downloadPromise,!0)}return t!==x.AVAILABLE?(M.debug(`On-device inference unavailable because availability is "${t}".`),!1):!!ChromeAdapterImpl.isOnDeviceRequest(e)||(M.debug("On-device inference unavailable because request is incompatible."),!1)}async generateContent(e){const t=await this.createSession(),n=await Promise.all(e.contents.map(ChromeAdapterImpl.toLanguageModelMessage)),s=await t.prompt(n,this.onDeviceParams.promptOptions);return ChromeAdapterImpl.toResponse(s)}async generateContentStream(e){const t=await this.createSession(),n=await Promise.all(e.contents.map(ChromeAdapterImpl.toLanguageModelMessage)),s=t.promptStreaming(n,this.onDeviceParams.promptOptions);return ChromeAdapterImpl.toStreamResponse(s)}async countTokens(e){throw new AIError(C.REQUEST_ERROR,"Count Tokens is not yet available for on-device model.")}static isOnDeviceRequest(e){if(0===e.contents.length)return M.debug("Empty prompt rejected for on-device inference."),!1;for(const t of e.contents){if("function"===t.role)return M.debug('"Function" role rejected for on-device inference.'),!1;for(const e of t.parts)if(e.inlineData&&-1===ChromeAdapterImpl.SUPPORTED_MIME_TYPES.indexOf(e.inlineData.mimeType))return M.debug(`Unsupported mime type "${e.inlineData.mimeType}" rejected for on-device inference.`),!1}return!0}async downloadIfAvailable(){const e=await(this.languageModelProvider?.availability(this.onDeviceParams.createOptions));return e===x.DOWNLOADABLE&&this.download(),e}download(){this.isDownloading||(this.isDownloading=!0,this.downloadPromise=this.languageModelProvider?.create(this.onDeviceParams.createOptions).finally((()=>{this.isDownloading=!1})))}static async toLanguageModelMessage(e){const t=await Promise.all(e.parts.map(ChromeAdapterImpl.toLanguageModelMessageContent));return{role:ChromeAdapterImpl.toLanguageModelMessageRole(e.role),content:t}}static async toLanguageModelMessageContent(e){if(e.text)return{type:"text",value:e.text};if(e.inlineData){const t=await fetch(`data:${e.inlineData.mimeType};base64,${e.inlineData.data}`),n=await t.blob();return{type:"image",value:await createImageBitmap(n)}}throw new AIError(C.REQUEST_ERROR,"Processing of this Part type is not currently supported.")}static toLanguageModelMessageRole(e){return"model"===e?"assistant":"user"}async createSession(){if(!this.languageModelProvider)throw new AIError(C.UNSUPPORTED,"Chrome AI requested for unsupported browser version.");const e=await this.languageModelProvider.create(this.onDeviceParams.createOptions);return this.oldSession&&this.oldSession.destroy(),this.oldSession=e,e}static toResponse(e){return{json:async()=>({candidates:[{content:{parts:[{text:e}]}}]})}}static toStreamResponse(e){const t=new TextEncoder;return{body:e.pipeThrough(new TransformStream({transform(e,n){const s=JSON.stringify({candidates:[{content:{role:"model",parts:[{text:e}]}}]});n.enqueue(t.encode(`data: ${s}\n\n`))}}))}}}ChromeAdapterImpl.SUPPORTED_MIME_TYPES=["image/jpeg","image/png"];class Schema{constructor(e){if(!e.type&&!e.anyOf)throw new AIError(C.INVALID_SCHEMA,"A schema must have either a 'type' or an 'anyOf' array of sub-schemas.");for(const t in e)this[t]=e[t];this.type=e.type,this.format=e.hasOwnProperty("format")?e.format:void 0,this.nullable=!!e.hasOwnProperty("nullable")&&!!e.nullable}toJSON(){const e={type:this.type};for(const t in this)this.hasOwnProperty(t)&&void 0!==this[t]&&("required"===t&&this.type!==N.OBJECT||(e[t]=this[t]));return e}static array(e){return new ArraySchema(e,e.items)}static object(e){return new ObjectSchema(e,e.properties,e.optionalProperties)}static string(e){return new StringSchema(e)}static enumString(e){return new StringSchema(e,e.enum)}static integer(e){return new IntegerSchema(e)}static number(e){return new NumberSchema(e)}static boolean(e){return new BooleanSchema(e)}static anyOf(e){return new AnyOfSchema(e)}}class IntegerSchema extends Schema{constructor(e){super({type:N.INTEGER,...e})}}class NumberSchema extends Schema{constructor(e){super({type:N.NUMBER,...e})}}class BooleanSchema extends Schema{constructor(e){super({type:N.BOOLEAN,...e})}}class StringSchema extends Schema{constructor(e,t){super({type:N.STRING,...e}),this.enum=t}toJSON(){const e=super.toJSON();return this.enum&&(e.enum=this.enum),e}}class ArraySchema extends Schema{constructor(e,t){super({type:N.ARRAY,...e}),this.items=t}toJSON(){const e=super.toJSON();return e.items=this.items.toJSON(),e}}class ObjectSchema extends Schema{constructor(e,t,n=[]){super({type:N.OBJECT,...e}),this.properties=t,this.optionalProperties=n}toJSON(){const e=super.toJSON();e.properties={...this.properties};const t=[];if(this.optionalProperties)for(const e of this.optionalProperties)if(!this.properties.hasOwnProperty(e))throw new AIError(C.INVALID_SCHEMA,`Property "${e}" specified in "optionalProperties" does not exist.`);for(const n in this.properties)this.properties.hasOwnProperty(n)&&(e.properties[n]=this.properties[n].toJSON(),this.optionalProperties.includes(n)||t.push(n));return t.length>0&&(e.required=t),delete e.optionalProperties,e}}class AnyOfSchema extends Schema{constructor(e){if(0===e.anyOf.length)throw new AIError(C.INVALID_SCHEMA,"The 'anyOf' array must not be empty.");super({...e,type:void 0}),this.anyOf=e.anyOf}toJSON(){const e=super.toJSON();return this.anyOf&&Array.isArray(this.anyOf)&&(e.anyOf=this.anyOf.map((e=>e.toJSON()))),e}}class ImagenImageFormat{constructor(){this.mimeType="image/png"}static jpeg(e){return e&&(e<0||e>100)&&M.warn(`Invalid JPEG compression quality of ${e} specified; the supported range is [0, 100].`),{mimeType:"image/jpeg",compressionQuality:e}}static png(){return{mimeType:"image/png"}}}function getAI(e=t(),n={backend:new GoogleAIBackend}){e=function getModularInstance(e){return e&&e._delegate?e._delegate:e}(e);const s=_getProvider(e,p),o=function encodeInstanceIdentifier(e){if(e instanceof GoogleAIBackend)return`${p}/googleai`;if(e instanceof VertexAIBackend)return`${p}/vertexai/${e.location}`;throw new AIError(C.ERROR,`Invalid backend: ${JSON.stringify(e.backendType)}`)}(n.backend);return s.getImmediate({identifier:o})}function getGenerativeModel(e,t,n){const s=t;let o,r;if(o=s.mode?s.inCloudParams||{model:"gemini-2.0-flash-lite"}:t,!o.model)throw new AIError(C.NO_MODEL,"Must provide a model name. Example: getGenerativeModel({ model: 'my-model-name' })");return"undefined"!=typeof window&&s.mode&&(r=new ChromeAdapterImpl(window.LanguageModel,s.mode,s.onDeviceParams)),new GenerativeModel(e,o,n,r)}function getImagenModel(e,t,n){if(!t.model)throw new AIError(C.NO_MODEL,"Must provide a model name. Example: getImagenModel({ model: 'my-model-name' })");return new ImagenModel(e,t,n)}!function registerAI(){n(new Component(p,((e,{instanceIdentifier:t})=>{if(!t)throw new AIError(C.ERROR,"AIService instance identifier is undefined.");const n=function decodeInstanceIdentifier(e){const t=e.split("/");if(t[0]!==p)throw new AIError(C.ERROR,`Invalid instance identifier, unknown prefix '${t[0]}'`);switch(t[1]){case"vertexai":const n=t[2];if(!n)throw new AIError(C.ERROR,`Invalid instance identifier, unknown location '${e}'`);return new VertexAIBackend(n);case"googleai":return new GoogleAIBackend;default:throw new AIError(C.ERROR,`Invalid instance identifier string: '${e}'`)}}(t),s=e.getProvider("app").getImmediate(),o=e.getProvider("auth-internal"),r=e.getProvider("app-check-internal");return new AIService(s,n,o,r)}),"PUBLIC").setMultipleInstances(!0)),s(d,l),s(d,l,"esm2020")}();export{AIError,C as AIErrorCode,AIModel,AnyOfSchema,ArraySchema,Backend,P as BackendType,O as BlockReason,BooleanSchema,ChatSession,A as FinishReason,y as FunctionCallingMode,GenerativeModel,GoogleAIBackend,E as HarmBlockMethod,f as HarmBlockThreshold,m as HarmCategory,I as HarmProbability,R as HarmSeverity,L as ImagenAspectRatio,ImagenImageFormat,ImagenModel,b as ImagenPersonFilterLevel,w as ImagenSafetyFilterLevel,T as InferenceMode,IntegerSchema,S as Modality,NumberSchema,ObjectSchema,g as POSSIBLE_ROLES,_ as ResponseModality,Schema,N as SchemaType,StringSchema,VertexAIBackend,getAI,getGenerativeModel,getImagenModel};
//# sourceMappingURL=firebase-ai.js.map