@nxcode/sdk 1.0.0 → 1.0.5

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
- !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).Nxcode={})}(this,function(t){"use strict";const e="nxcode_sdk_auth";class i{constructor(t,e){this.user=null,this.token=null,this.refreshToken=null,this.expiresAt=null,this.authCallbacks=[],this.popupWindow=null,this.messageHandler=null,this.apiEndpoint=t,this.appId=e,this.loadFromStorage(),this.setupMessageListener()}async login(t="google"){return new Promise((e,i)=>{const s=window.screenX+(window.outerWidth-500)/2,n=window.screenY+(window.outerHeight-600)/2,o=`${this.apiEndpoint}/api/sdk/auth/login?app_id=${this.appId}&provider=${t}`;if(this.popupWindow=window.open(o,"nxcode_login",`width=500,height=600,left=${s},top=${n}`),!this.popupWindow)return void i(new Error("Failed to open login popup. Please allow popups for this site."));const a=setTimeout(()=>{this.popupWindow?.close(),i(new Error("Login timeout"))},12e4),r=t=>{if("NXCODE_SDK_AUTH"!==t.data?.type)return;clearTimeout(a),window.removeEventListener("message",r);const s=t.data.payload;s.success&&s.user&&s.token?(this.setAuth(s),e(s.user)):i(new Error(s.error||"Login failed"))};window.addEventListener("message",r)})}async logout(){try{this.token&&await fetch(`${this.apiEndpoint}/api/sdk/auth/logout`,{method:"POST",headers:this.getHeaders()})}catch(t){console.warn("Logout request failed:",t)}this.clearAuth()}getUser(){return this.user}getToken(){return this.expiresAt&&new Date>this.expiresAt?(this.refreshSession().catch(console.error),null):this.token}async getValidToken(){return this.expiresAt&&new Date>this.expiresAt&&await this.refreshSession(),this.token}onAuthStateChange(t){return this.authCallbacks.push(t),t(this.user),()=>{const e=this.authCallbacks.indexOf(t);e>-1&&this.authCallbacks.splice(e,1)}}isLoggedIn(){return null!==this.user&&null!==this.token}async refreshSession(){if(this.refreshToken)try{const t=await fetch(`${this.apiEndpoint}/api/sdk/auth/refresh`,{method:"POST",headers:{"Content-Type":"application/json","X-App-Id":this.appId},body:JSON.stringify({refreshToken:this.refreshToken})});if(!t.ok)throw new Error("Refresh failed");const e=await t.json();this.setAuth({success:!0,token:e.token,refreshToken:e.refreshToken,expiresAt:e.expiresAt,user:e.user})}catch(t){console.error("Session refresh failed:",t),this.clearAuth()}else this.clearAuth()}async fetchUser(){if(!this.token)return null;try{const t=await fetch(`${this.apiEndpoint}/api/sdk/auth/me`,{headers:this.getHeaders()});if(!t.ok){if(401===t.status)return await this.refreshSession(),this.user;throw new Error("Failed to fetch user")}const e=await t.json();return this.user=e,this.notifyAuthChange(),this.saveToStorage(),e}catch(t){return console.error("Failed to fetch user:",t),null}}setAuth(t){t.success&&t.user&&t.token&&(this.user=t.user,this.token=t.token,this.refreshToken=t.refreshToken||null,this.expiresAt=t.expiresAt?new Date(t.expiresAt):null,this.saveToStorage(),this.notifyAuthChange())}clearAuth(){this.user=null,this.token=null,this.refreshToken=null,this.expiresAt=null,localStorage.removeItem(`${e}_${this.appId}`),this.notifyAuthChange()}saveToStorage(){if(this.user&&this.token){const t={token:this.token,refreshToken:this.refreshToken||"",expiresAt:this.expiresAt?.toISOString()||"",user:this.user};localStorage.setItem(`${e}_${this.appId}`,JSON.stringify(t))}}loadFromStorage(){try{const t=localStorage.getItem(`${e}_${this.appId}`);if(t){const e=JSON.parse(t);this.token=e.token,this.refreshToken=e.refreshToken,this.expiresAt=e.expiresAt?new Date(e.expiresAt):null,this.user=e.user,this.expiresAt&&new Date>this.expiresAt&&this.refreshSession().catch(()=>this.clearAuth())}}catch(t){console.warn("Failed to load auth from storage:",t)}}notifyAuthChange(){for(const t of this.authCallbacks)try{t(this.user)}catch(t){console.error("Auth callback error:",t)}}setupMessageListener(){}getHeaders(){const t={"Content-Type":"application/json","X-App-Id":this.appId};return this.token&&(t.Authorization=`Bearer ${this.token}`),t}}class s{constructor(t,e,i){this.apiEndpoint=t,this.appId=e,this.getToken=i}async getBalance(){const t=this.getToken();if(!t)throw new Error("Not authenticated. Please login first.");const e=await fetch(`${this.apiEndpoint}/api/sdk/billing/balance`,{headers:this.getHeaders(t)});if(!e.ok){if(401===e.status)throw new Error("Session expired. Please login again.");throw new Error("Failed to fetch balance")}return(await e.json()).balance}topUp(){const t=`${this.apiEndpoint}/api/sdk/billing/topup?app_id=${this.appId}`;window.open(t,"_blank")}getHeaders(t){return{"Content-Type":"application/json","X-App-Id":this.appId,Authorization:`Bearer ${t}`}}}class n{constructor(t,e,i){this.apiEndpoint=t,this.appId=e,this.getToken=i}async charge(t){const e=this.getToken();if(!e)return{success:!1,error:"Not authenticated. Please login first."};try{const i=await fetch(`${this.apiEndpoint}/api/sdk/payment/charge`,{method:"POST",headers:this.getHeaders(e),body:JSON.stringify({amount:t.amount,description:t.description,metadata:t.metadata})});if(!i.ok){if(401===i.status)return{success:!1,error:"Session expired. Please login again."};if(402===i.status)return{success:!1,error:"Insufficient balance. Please top up."};return{success:!1,error:(await i.json().catch(()=>({}))).detail||"Payment failed"}}return await i.json()}catch(t){return{success:!1,error:t instanceof Error?t.message:"Payment failed"}}}async getTransactions(t=50,e=0){const i=this.getToken();if(!i)throw new Error("Not authenticated. Please login first.");const s=await fetch(`${this.apiEndpoint}/api/sdk/payment/transactions?limit=${t}&offset=${e}`,{headers:this.getHeaders(i)});if(!s.ok){if(401===s.status)throw new Error("Session expired. Please login again.");throw new Error("Failed to fetch transactions")}return(await s.json()).transactions}getHeaders(t){return{"Content-Type":"application/json","X-App-Id":this.appId,Authorization:`Bearer ${t}`}}}const o=new class{constructor(){this.config=null,this._auth=null,this._billing=null,this._payment=null,this.initPromise=null,this.apiEndpoint=this.detectApiEndpoint(),this.autoInit()}async autoInit(){return this.initPromise||(this.initPromise=this.init()),this.initPromise}async init(){try{const t=await fetch(`${this.apiEndpoint}/api/sdk/config`,{credentials:"include"});t.ok&&(this.config=await t.json(),this.config.apiEndpoint=this.apiEndpoint,this.setupModules())}catch(t){console.warn("Nxcode SDK: Could not auto-detect app config. Call Nxcode.configure() manually.")}}configure(t){this.config={appId:t,name:"",billingMode:"creator_pays",apiEndpoint:this.apiEndpoint},this.setupModules()}setupModules(){this.config&&(this._auth=new i(this.config.apiEndpoint,this.config.appId),this._billing=new s(this.config.apiEndpoint,this.config.appId,()=>this._auth?.getToken()||null),this._payment=new n(this.config.apiEndpoint,this.config.appId,()=>this._auth?.getToken()||null))}detectApiEndpoint(){if("undefined"!=typeof window){const t=window.location.hostname;if("localhost"===t||"127.0.0.1"===t)return"http://localhost:8001";if(t.includes(".nxcode.dev")||t.includes(".nxcode.app"))return"https://studio-api.nxcode.io"}return"https://studio-api.nxcode.io"}async ensureInitialized(){if(this.initPromise&&await this.initPromise,!this.config)throw new Error("Nxcode SDK not configured. Add X-App-Id header or call Nxcode.configure(appId).")}get auth(){const t=this;return{login:async(e="google")=>(await t.ensureInitialized(),t._auth.login(e)),logout:async()=>(await t.ensureInitialized(),t._auth.logout()),getUser:()=>t._auth?.getUser()||null,getToken:()=>t._auth?.getToken()||null,onAuthStateChange(e){if(!t._auth){let i=null,s=!1;return t.ensureInitialized().then(()=>{!s&&t._auth&&(i=t._auth.onAuthStateChange(e))}),()=>{s=!0,i&&i()}}return t._auth.onAuthStateChange(e)},isLoggedIn:()=>t._auth?.isLoggedIn()||!1}}get billing(){const t=this;return{getBalance:async()=>(await t.ensureInitialized(),t._billing.getBalance()),topUp(){t._billing?.topUp()}}}get payment(){const t=this;return{charge:async e=>(await t.ensureInitialized(),t._payment.charge(e)),getTransactions:async(e,i)=>(await t.ensureInitialized(),t._payment.getTransactions(e,i))}}getConfig(){return this.config}isReady(){return null!==this.config&&null!==this._auth}async ready(){await this.ensureInitialized()}};"undefined"!=typeof window&&(window.Nxcode=o),t.Nxcode=o,t.default=o,Object.defineProperty(t,"__esModule",{value:!0})});
1
+ !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).Nxcode={})}(this,function(t){"use strict";const e="nxcode_sdk_auth";class n{constructor(t,e){this.user=null,this.token=null,this.refreshToken=null,this.expiresAt=null,this.authCallbacks=[],this.popupWindow=null,this.messageHandler=null,this.apiEndpoint=t,this.appId=e,this.loadFromStorage(),this.setupMessageListener()}async login(t="google"){return new Promise((e,n)=>{const s=window.screenX+(window.outerWidth-500)/2,i=window.screenY+(window.outerHeight-600)/2,a=`${this.apiEndpoint}/api/sdk/auth/login?app_id=${this.appId}&provider=${t}`;if(this.popupWindow=window.open(a,"nxcode_login",`width=500,height=600,left=${s},top=${i}`),!this.popupWindow)return void n(new Error("Failed to open login popup. Please allow popups for this site."));const o=setTimeout(()=>{this.popupWindow?.close(),n(new Error("Login timeout"))},12e4),r=t=>{if("NXCODE_SDK_AUTH"!==t.data?.type)return;clearTimeout(o),window.removeEventListener("message",r);const s=t.data.payload;s.success&&s.user&&s.token?(this.setAuth(s),e(s.user)):n(new Error(s.error||"Login failed"))};window.addEventListener("message",r)})}async logout(){try{this.token&&await fetch(`${this.apiEndpoint}/api/sdk/auth/logout`,{method:"POST",headers:this.getHeaders()})}catch(t){console.warn("Logout request failed:",t)}this.clearAuth()}getUser(){return this.user}getToken(){return this.expiresAt&&new Date>this.expiresAt?(this.refreshSession().catch(console.error),null):this.token}async getValidToken(){return this.expiresAt&&new Date>this.expiresAt&&await this.refreshSession(),this.token}onAuthStateChange(t){return this.authCallbacks.push(t),t(this.user),()=>{const e=this.authCallbacks.indexOf(t);e>-1&&this.authCallbacks.splice(e,1)}}isLoggedIn(){return null!==this.user&&null!==this.token}async refreshSession(){if(this.refreshToken)try{const t=await fetch(`${this.apiEndpoint}/api/sdk/auth/refresh`,{method:"POST",headers:{"Content-Type":"application/json","X-App-Id":this.appId},body:JSON.stringify({refreshToken:this.refreshToken})});if(!t.ok)throw new Error("Refresh failed");const e=await t.json();this.setAuth({success:!0,token:e.token,refreshToken:e.refreshToken,expiresAt:e.expiresAt,user:e.user})}catch(t){console.error("Session refresh failed:",t),this.clearAuth()}else this.clearAuth()}async fetchUser(){if(!this.token)return null;try{const t=await fetch(`${this.apiEndpoint}/api/sdk/auth/me`,{headers:this.getHeaders()});if(!t.ok){if(401===t.status)return await this.refreshSession(),this.user;throw new Error("Failed to fetch user")}const e=await t.json();return this.user=e,this.notifyAuthChange(),this.saveToStorage(),e}catch(t){return console.error("Failed to fetch user:",t),null}}setAuth(t){t.success&&t.user&&t.token&&(this.user=t.user,this.token=t.token,this.refreshToken=t.refreshToken||null,this.expiresAt=t.expiresAt?new Date(t.expiresAt):null,this.saveToStorage(),this.notifyAuthChange())}clearAuth(){this.user=null,this.token=null,this.refreshToken=null,this.expiresAt=null,localStorage.removeItem(`${e}_${this.appId}`),this.notifyAuthChange()}saveToStorage(){if(this.user&&this.token){const t={token:this.token,refreshToken:this.refreshToken||"",expiresAt:this.expiresAt?.toISOString()||"",user:this.user};localStorage.setItem(`${e}_${this.appId}`,JSON.stringify(t))}}loadFromStorage(){try{const t=localStorage.getItem(`${e}_${this.appId}`);if(t){const e=JSON.parse(t);this.token=e.token,this.refreshToken=e.refreshToken,this.expiresAt=e.expiresAt?new Date(e.expiresAt):null,this.user=e.user,this.expiresAt&&new Date>this.expiresAt&&this.refreshSession().catch(()=>this.clearAuth())}}catch(t){console.warn("Failed to load auth from storage:",t)}}notifyAuthChange(){for(const t of this.authCallbacks)try{t(this.user)}catch(t){console.error("Auth callback error:",t)}}setupMessageListener(){}getHeaders(){const t={"Content-Type":"application/json","X-App-Id":this.appId};return this.token&&(t.Authorization=`Bearer ${this.token}`),t}}class s{constructor(t,e,n){this.apiEndpoint=t,this.appId=e,this.getToken=n}async getBalance(){const t=this.getToken();if(!t)throw new Error("Not authenticated. Please login first.");const e=await fetch(`${this.apiEndpoint}/api/sdk/billing/balance`,{headers:this.getHeaders(t)});if(!e.ok){if(401===e.status)throw new Error("Session expired. Please login again.");throw new Error("Failed to fetch balance")}return(await e.json()).balance}topUp(){const t=`${this.apiEndpoint}/api/sdk/billing/topup?app_id=${this.appId}`;window.open(t,"_blank")}getHeaders(t){return{"Content-Type":"application/json","X-App-Id":this.appId,Authorization:`Bearer ${t}`}}}class i{constructor(t,e,n){this.apiEndpoint=t,this.appId=e,this.getToken=n}async charge(t){const e=this.getToken();if(!e)return{success:!1,error:"Not authenticated. Please login first."};try{const n=await fetch(`${this.apiEndpoint}/api/sdk/payment/charge`,{method:"POST",headers:this.getHeaders(e),body:JSON.stringify({amount:t.amount,description:t.description,metadata:t.metadata})});if(!n.ok){if(401===n.status)return{success:!1,error:"Session expired. Please login again."};if(402===n.status)return{success:!1,error:"Insufficient balance. Please top up."};return{success:!1,error:(await n.json().catch(()=>({}))).detail||"Payment failed"}}return await n.json()}catch(t){return{success:!1,error:t instanceof Error?t.message:"Payment failed"}}}async getTransactions(t=50,e=0){const n=this.getToken();if(!n)throw new Error("Not authenticated. Please login first.");const s=await fetch(`${this.apiEndpoint}/api/sdk/payment/transactions?limit=${t}&offset=${e}`,{headers:this.getHeaders(n)});if(!s.ok){if(401===s.status)throw new Error("Session expired. Please login again.");throw new Error("Failed to fetch transactions")}return(await s.json()).transactions}getHeaders(t){return{"Content-Type":"application/json","X-App-Id":this.appId,Authorization:`Bearer ${t}`}}}function a(t){if("string"===t)return{type:"STRING"};if("number"===t)return{type:"NUMBER"};if("boolean"===t)return{type:"BOOLEAN"};if(Array.isArray(t)){if(1!==t.length)throw new Error("Array schema must have exactly one element type");return{type:"ARRAY",items:a(t[0])}}if("object"==typeof t&&null!==t){const e={},n=[];for(const[s,i]of Object.entries(t))e[s]=a(i),n.push(s);return{type:"OBJECT",properties:e,required:n}}throw new Error(`Invalid schema type: ${t}`)}class o{constructor(t,e,n){this.apiEndpoint=t,this.appId=e,this.getToken=n}async chat(t){const e=this.getToken();if(!e)throw new Error("Not authenticated. Please login first.");const n=t.model||"fast",s={contents:this.convertMessagesToGemini(t.messages)};t.responseSchema&&(s.generationConfig={responseMimeType:"application/json",responseSchema:a(t.responseSchema)});const i=await fetch(`${this.apiEndpoint}/api/ai-gateway/v1beta/models/${n}:generateContent`,{method:"POST",headers:this.getHeaders(e),body:JSON.stringify(s)});i.ok||await this.handleError(i);const o=await i.json();return this.parseGeminiResponse(o)}async generate(t){const e=await this.chat({messages:[{role:"user",content:t.prompt}],model:t.model,responseSchema:t.responseSchema});return{text:e.content,usage:e.usage}}async chatStream(t){const e=this.getToken(),n=e?this.getHeaders(e):this.getAnonymousHeaders(),s=t.model||"fast",i={contents:this.convertMessagesToGemini(t.messages)},a=await fetch(`${this.apiEndpoint}/api/ai-gateway/v1beta/models/${s}:streamGenerateContent?alt=sse`,{method:"POST",headers:n,body:JSON.stringify(i)});a.ok||await this.handleError(a);const o=a.body?.getReader();if(!o)throw new Error("Streaming not supported");const r=new TextDecoder;let h="";try{for(;;){const{done:e,value:n}=await o.read();if(e)break;h+=r.decode(n,{stream:!0});const s=h.split("\n");h=s.pop()||"";for(const e of s)if(e.startsWith("data: ")){const n=e.slice(6).trim();if("[DONE]"===n)return void t.onChunk({content:"",done:!0});try{const e=JSON.parse(n),s=this.parseStreamChunk(e);t.onChunk(s)}catch{}}}if(h.startsWith("data: ")){const e=h.slice(6).trim();if(e&&"[DONE]"!==e)try{const n=JSON.parse(e),s=this.parseStreamChunk(n);t.onChunk(s)}catch{}}t.onChunk({content:"",done:!0})}finally{o.releaseLock()}}async generateStream(t){return this.chatStream({messages:[{role:"user",content:t.prompt}],model:t.model,onChunk:t.onChunk})}getHeaders(t){return{"Content-Type":"application/json","X-App-Id":this.appId,Authorization:`Bearer ${t}`}}getAnonymousHeaders(){return{"Content-Type":"application/json","X-App-Id":this.appId}}convertMessagesToGemini(t){return t.map(t=>({role:"assistant"===t.role?"model":"user",parts:this.convertContentToParts(t.content)}))}convertContentToParts(t){return"string"==typeof t?[{text:t}]:t.map(t=>{switch(t.type){case"text":return{text:t.text};case"image":return{inlineData:{mimeType:t.mimeType,data:t.data}};case"image_url":return{fileData:{fileUri:t.url}};default:return{text:""}}})}parseGeminiResponse(t){const e=t.candidates,n=e?.[0]?.content?.parts?.[0]?.text||"",s=t.usageMetadata;return{content:n,usage:s?{inputTokens:s.promptTokenCount||0,outputTokens:s.candidatesTokenCount||0}:void 0}}parseStreamChunk(t){const e=t.candidates,n=e?.[0]?.content?.parts?.[0]?.text||"",s=e?.[0]?.finishReason,i="STOP"===s||"END_TURN"===s,a=t.usageMetadata;return{content:n,done:i,usage:a?{inputTokens:a.promptTokenCount||0,outputTokens:a.candidatesTokenCount||0}:void 0}}async handleError(t){if(401===t.status)throw new Error("Session expired. Please login again.");if(402===t.status)throw new Error("Insufficient balance. Please top up to continue.");let e="AI request failed";try{const n=await t.json();e=n.detail||n.message||e}catch{}throw new Error(e)}}const r=new class{constructor(){this.config=null,this._auth=null,this._billing=null,this._payment=null,this._ai=null,this.initPromise=null,this.apiEndpoint=this.detectApiEndpoint(),this.autoInit()}async autoInit(){return this.initPromise||(this.initPromise=this.init()),this.initPromise}async init(){try{const t=await fetch(`${this.apiEndpoint}/api/sdk/config`,{credentials:"include"});t.ok&&(this.config=await t.json(),this.config.apiEndpoint=this.apiEndpoint,this.setupModules())}catch(t){console.warn("Nxcode SDK: Could not auto-detect app config. Call Nxcode.configure() manually.")}}configure(t,e){e?.apiEndpoint&&(this.apiEndpoint=e.apiEndpoint),this.config={appId:t,name:"",billingMode:"creator_pays",apiEndpoint:this.apiEndpoint},this.setupModules()}setupModules(){this.config&&(this._auth=new n(this.config.apiEndpoint,this.config.appId),this._billing=new s(this.config.apiEndpoint,this.config.appId,()=>this._auth?.getToken()||null),this._payment=new i(this.config.apiEndpoint,this.config.appId,()=>this._auth?.getToken()||null),this._ai=new o(this.config.apiEndpoint,this.config.appId,()=>this._auth?.getToken()||null))}detectApiEndpoint(){if("undefined"!=typeof window){const t=window.location.hostname;if("localhost"===t||"127.0.0.1"===t)return"http://localhost:8001";if(t.includes(".nxcode.dev")||t.includes(".nxcode.app"))return"https://studio-api.nxcode.io"}return"https://studio-api.nxcode.io"}async ensureInitialized(){if(this.initPromise&&await this.initPromise,!this.config)throw new Error("Nxcode SDK not configured. Add X-App-Id header or call Nxcode.configure(appId).")}get auth(){const t=this;return{login:async(e="google")=>(await t.ensureInitialized(),t._auth.login(e)),logout:async()=>(await t.ensureInitialized(),t._auth.logout()),getUser:()=>t._auth?.getUser()||null,getToken:()=>t._auth?.getToken()||null,onAuthStateChange(e){if(!t._auth){let n=null,s=!1;return t.ensureInitialized().then(()=>{!s&&t._auth&&(n=t._auth.onAuthStateChange(e))}),()=>{s=!0,n&&n()}}return t._auth.onAuthStateChange(e)},isLoggedIn:()=>t._auth?.isLoggedIn()||!1}}get billing(){const t=this;return{getBalance:async()=>(await t.ensureInitialized(),t._billing.getBalance()),topUp(){t._billing?.topUp()}}}get payment(){const t=this;return{charge:async e=>(await t.ensureInitialized(),t._payment.charge(e)),getTransactions:async(e,n)=>(await t.ensureInitialized(),t._payment.getTransactions(e,n))}}get ai(){const t=this;return{chat:async e=>(await t.ensureInitialized(),t._ai.chat(e)),generate:async e=>(await t.ensureInitialized(),t._ai.generate(e)),chatStream:async e=>(await t.ensureInitialized(),t._ai.chatStream(e)),generateStream:async e=>(await t.ensureInitialized(),t._ai.generateStream(e))}}getConfig(){return this.config}isReady(){return null!==this.config&&null!==this._auth}async ready(){await this.ensureInitialized()}};"undefined"!=typeof window&&(window.Nxcode=r),t.Nxcode=r,t.default=r,Object.defineProperty(t,"__esModule",{value:!0})});
@@ -0,0 +1,149 @@
1
+ /**
2
+ * Nxcode SDK - AI Module
3
+ *
4
+ * Provides access to AI capabilities through the Nxcode AI Gateway.
5
+ * All AI calls require user authentication and are billed to the user's balance.
6
+ */
7
+ /**
8
+ * Simplified schema type for structured output.
9
+ *
10
+ * Use simple TypeScript-style notation:
11
+ * - Primitives: 'string', 'number', 'boolean'
12
+ * - Arrays: ['string'], ['number'], [{ nested: 'object' }]
13
+ * - Objects: { key: 'type', nested: { ... } }
14
+ *
15
+ * @example
16
+ * // Simple object
17
+ * { name: 'string', age: 'number', active: 'boolean' }
18
+ *
19
+ * // With arrays
20
+ * { tags: ['string'], scores: ['number'] }
21
+ *
22
+ * // Nested objects
23
+ * { user: { name: 'string', profile: { bio: 'string' } } }
24
+ */
25
+ export type SimpleSchema = 'string' | 'number' | 'boolean' | SimpleSchema[] | {
26
+ [key: string]: SimpleSchema;
27
+ };
28
+ /**
29
+ * Content part for multimodal messages
30
+ */
31
+ export interface TextPart {
32
+ type: 'text';
33
+ text: string;
34
+ }
35
+ export interface ImagePart {
36
+ type: 'image';
37
+ /** Base64 encoded image data */
38
+ data: string;
39
+ /** MIME type (e.g., 'image/png', 'image/jpeg') */
40
+ mimeType: string;
41
+ }
42
+ export interface ImageUrlPart {
43
+ type: 'image_url';
44
+ /** URL of the image */
45
+ url: string;
46
+ }
47
+ export type ContentPart = TextPart | ImagePart | ImageUrlPart;
48
+ export interface ChatMessage {
49
+ role: 'user' | 'assistant' | 'system';
50
+ /** Text content or array of content parts for multimodal */
51
+ content: string | ContentPart[];
52
+ }
53
+ export interface ChatOptions {
54
+ messages: ChatMessage[];
55
+ model?: string;
56
+ /** Schema for structured output. AI will return JSON matching this schema. */
57
+ responseSchema?: SimpleSchema;
58
+ }
59
+ export interface ChatResponse {
60
+ content: string;
61
+ usage?: {
62
+ inputTokens: number;
63
+ outputTokens: number;
64
+ };
65
+ }
66
+ export interface GenerateOptions {
67
+ prompt: string;
68
+ model?: string;
69
+ /** Schema for structured output. AI will return JSON matching this schema. */
70
+ responseSchema?: SimpleSchema;
71
+ }
72
+ export interface GenerateResponse {
73
+ text: string;
74
+ usage?: {
75
+ inputTokens: number;
76
+ outputTokens: number;
77
+ };
78
+ }
79
+ export interface StreamChunk {
80
+ content: string;
81
+ done: boolean;
82
+ usage?: {
83
+ inputTokens: number;
84
+ outputTokens: number;
85
+ };
86
+ }
87
+ export type StreamCallback = (chunk: StreamChunk) => void;
88
+ export declare class NxcodeAI {
89
+ private apiEndpoint;
90
+ private appId;
91
+ private getToken;
92
+ constructor(apiEndpoint: string, appId: string, getToken: () => string | null);
93
+ /**
94
+ * Send a chat message and get a response.
95
+ *
96
+ * @example
97
+ * const response = await Nxcode.ai.chat({
98
+ * messages: [
99
+ * { role: 'user', content: 'Hello!' }
100
+ * ]
101
+ * });
102
+ * console.log(response.content);
103
+ */
104
+ chat(options: ChatOptions): Promise<ChatResponse>;
105
+ /**
106
+ * Generate text from a prompt.
107
+ *
108
+ * @example
109
+ * const response = await Nxcode.ai.generate({
110
+ * prompt: 'Write a haiku about coding'
111
+ * });
112
+ * console.log(response.text);
113
+ */
114
+ generate(options: GenerateOptions): Promise<GenerateResponse>;
115
+ /**
116
+ * Stream a chat response in real-time.
117
+ *
118
+ * @example
119
+ * await Nxcode.ai.chatStream({
120
+ * messages: [{ role: 'user', content: 'Tell me a story' }],
121
+ * onChunk: (chunk) => {
122
+ * process.stdout.write(chunk.content);
123
+ * if (chunk.done) console.log('\n--- Done ---');
124
+ * }
125
+ * });
126
+ */
127
+ chatStream(options: ChatOptions & {
128
+ onChunk: StreamCallback;
129
+ }): Promise<void>;
130
+ /**
131
+ * Stream text generation from a prompt.
132
+ *
133
+ * @example
134
+ * await Nxcode.ai.generateStream({
135
+ * prompt: 'Write a poem',
136
+ * onChunk: (chunk) => console.log(chunk.content)
137
+ * });
138
+ */
139
+ generateStream(options: GenerateOptions & {
140
+ onChunk: StreamCallback;
141
+ }): Promise<void>;
142
+ private getHeaders;
143
+ private getAnonymousHeaders;
144
+ private convertMessagesToGemini;
145
+ private convertContentToParts;
146
+ private parseGeminiResponse;
147
+ private parseStreamChunk;
148
+ private handleError;
149
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Auth Module Unit Tests
3
+ *
4
+ * Run with: npx vitest run src/auth.test.ts
5
+ */
6
+ export {};
@@ -11,12 +11,14 @@
11
11
  * console.log('Logged in:', user.email);
12
12
  * </script>
13
13
  */
14
+ import { type ChatOptions, type ChatResponse, type GenerateOptions, type GenerateResponse, type StreamChunk, type StreamCallback, type ChatMessage, type ContentPart, type TextPart, type ImagePart, type ImageUrlPart } from './ai';
14
15
  import type { NxcodeUser, NxcodeConfig, ChargeOptions, ChargeResult, Transaction, AuthStateCallback } from './types';
15
16
  declare class NxcodeSDK {
16
17
  private config;
17
18
  private _auth;
18
19
  private _billing;
19
20
  private _payment;
21
+ private _ai;
20
22
  private initPromise;
21
23
  private apiEndpoint;
22
24
  constructor();
@@ -29,9 +31,11 @@ declare class NxcodeSDK {
29
31
  */
30
32
  private init;
31
33
  /**
32
- * Manually configure SDK with app ID
34
+ * Manually configure SDK with app ID and optional endpoint
33
35
  */
34
- configure(appId: string): void;
36
+ configure(appId: string, options?: {
37
+ apiEndpoint?: string;
38
+ }): void;
35
39
  /**
36
40
  * Set up SDK modules after configuration
37
41
  */
@@ -90,6 +94,51 @@ declare class NxcodeSDK {
90
94
  */
91
95
  getTransactions(limit?: number, offset?: number): Promise<Transaction[]>;
92
96
  };
97
+ get ai(): {
98
+ /**
99
+ * Send a chat message and get a response
100
+ *
101
+ * @example
102
+ * const response = await Nxcode.ai.chat({
103
+ * messages: [{ role: 'user', content: 'Hello!' }]
104
+ * });
105
+ */
106
+ chat(options: ChatOptions): Promise<ChatResponse>;
107
+ /**
108
+ * Generate text from a prompt
109
+ *
110
+ * @example
111
+ * const response = await Nxcode.ai.generate({ prompt: 'Write a haiku' });
112
+ */
113
+ generate(options: GenerateOptions): Promise<GenerateResponse>;
114
+ /**
115
+ * Stream a chat response in real-time
116
+ *
117
+ * @example
118
+ * await Nxcode.ai.chatStream({
119
+ * messages: [{ role: 'user', content: 'Tell me a story' }],
120
+ * onChunk: (chunk) => {
121
+ * document.body.innerText += chunk.content;
122
+ * if (chunk.done) console.log('Done!');
123
+ * }
124
+ * });
125
+ */
126
+ chatStream(options: ChatOptions & {
127
+ onChunk: StreamCallback;
128
+ }): Promise<void>;
129
+ /**
130
+ * Stream text generation from a prompt
131
+ *
132
+ * @example
133
+ * await Nxcode.ai.generateStream({
134
+ * prompt: 'Write a poem',
135
+ * onChunk: (chunk) => console.log(chunk.content)
136
+ * });
137
+ */
138
+ generateStream(options: GenerateOptions & {
139
+ onChunk: StreamCallback;
140
+ }): Promise<void>;
141
+ };
93
142
  /**
94
143
  * Get current configuration
95
144
  */
@@ -106,4 +155,4 @@ declare class NxcodeSDK {
106
155
  declare const Nxcode: NxcodeSDK;
107
156
  export default Nxcode;
108
157
  export { Nxcode };
109
- export type { NxcodeUser, NxcodeConfig, ChargeOptions, ChargeResult, Transaction, AuthStateCallback, };
158
+ export type { NxcodeUser, NxcodeConfig, ChargeOptions, ChargeResult, Transaction, AuthStateCallback, ChatOptions, ChatResponse, ChatMessage, ContentPart, TextPart, ImagePart, ImageUrlPart, GenerateOptions, GenerateResponse, StreamChunk, StreamCallback, };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nxcode/sdk",
3
- "version": "1.0.0",
3
+ "version": "1.0.5",
4
4
  "type": "module",
5
5
  "description": "Nxcode SDK for web applications",
6
6
  "main": "dist/nxcode.js",