@bodhiapp/bodhi-js 0.0.39 → 0.0.41

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
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("@bodhiapp/bodhi-js-core");class S{async get(e){return localStorage.getItem(e)}async set(e){Object.entries(e).forEach(([t,i])=>{localStorage.setItem(t,String(i))})}async remove(e){e.forEach(t=>localStorage.removeItem(t))}}class w extends r.DirectClientBase{constructor(e,t){const i=r.createStoragePrefixWithNamespace(e.basePath,r.STORAGE_PREFIXES.WEB_DIRECT),s={authClientId:e.authClientId,authServerUrl:e.authServerUrl,storagePrefix:i,logLevel:e.logLevel,loggerPrefix:"DirectWebClient",apiTimeoutMs:e.apiTimeoutMs,storage:e.storage??new S,initialTokens:e.initialTokens};super(s,t),this.redirectUri=e.redirectUri}async login(e){const t=await this.getAuthState();if(t.status==="authenticated")return t;const i=e?.userRole??"scope_user_user",s=e?.flowType??"popup";e?.onProgress?.("requesting");const o=new r.AccessRequestBuilder(this.authClientId).requestedRole(i).flowType(s);if(e?.requested&&o.requested(e.requested),s==="redirect"){const u=e?.redirectUrl??this.redirectUri;o.redirectUrl(u)}const n=o.build(),c=await this.requestAccess(n),{id:l,review_url:a}=r.unwrapResponse(c);e?.onProgress?.("reviewing");let h;if(s==="popup"){const u=async()=>{const p=await this.getAccessRequestStatus(l);if(p.status>=400)return null;const{status:g,access_request_scope:E}=p.body;return g==="approved"?{approved:!0,accessRequestScope:E??void 0}:["denied","failed","expired"].includes(g)?{approved:!1,status:g}:null},d=await r.openPopupReview(a,u,{intervalMs:e?.pollIntervalMs??r.DEFAULT_POLL_INTERVAL_MS,timeoutMs:e?.pollTimeoutMs??r.DEFAULT_POLL_TIMEOUT_MS});d.approved||r.throwAccessRequestDenialError(d.status??"unknown"),h=d.accessRequestScope}else return await this._storageSet({[this.storageKeys.ACCESS_REQUEST_ID]:l}),window.location.href=a,new Promise(()=>{});return e?.onProgress?.("authenticating"),this.performOAuthPkce(`openid profile email roles ${h??""}`.trim())}async performOAuthPkce(e){const t=r.generateCodeVerifier(),i=await r.generateCodeChallenge(t),s=r.generateCodeVerifier();await this._storageSet({[this.storageKeys.CODE_VERIFIER]:t,[this.storageKeys.STATE]:s});const o=new URL(this.authEndpoints.authorize);throw o.searchParams.set("client_id",this.authClientId),o.searchParams.set("response_type","code"),o.searchParams.set("redirect_uri",this.redirectUri),o.searchParams.set("scope",e),o.searchParams.set("code_challenge",i),o.searchParams.set("code_challenge_method","S256"),o.searchParams.set("state",s),window.location.href=o.toString(),new Error("Redirect initiated")}async handleOAuthCallback(e,t){const i=await this._storageGet(this.storageKeys.STATE);if(!i||i!==t)throw new Error("Invalid state parameter - possible CSRF attack");await this.exchangeCodeForTokens(e);const s=await this.getAuthState();if(s.status!=="authenticated")throw new Error("Login failed");return this.setAuthState(s),s}async handleAccessRequestCallback(e){const t=await this.getAccessRequestStatus(e),{status:i,access_request_scope:s}=r.unwrapResponse(t);await this._storageRemove([this.storageKeys.ACCESS_REQUEST_ID]),i!=="approved"&&r.throwAccessRequestDenialError(i);const o=`openid profile email roles ${s??""}`.trim();return this.performOAuthPkce(o)}_getRedirectUri(){return this.redirectUri}}const m=500,_=5e3,T=3e4;class R{constructor(e,t,i){this.state=r.EXTENSION_STATE_NOT_INITIALIZED,this.bodhiext=null,this.refreshPromise=null,this.logger=new r.Logger("WindowBodhiextClient",t.logLevel),this.authClientId=e,this.config=t,this.authEndpoints=r.createOAuthEndpoints(this.config.authServerUrl),this.onStateChange=i??r.NOOP_STATE_CALLBACK;const s=r.createStoragePrefixWithNamespace(t.basePath,r.STORAGE_PREFIXES.WEB_EXT);this.storageKeys=r.createStorageKeys(s),this.apiTimeoutMs=t.apiTimeoutMs??T}setState(e){this.state=e,this.logger.info(`{state: ${JSON.stringify(e)}} - Setting client state`),this.onStateChange({type:"client-state",state:e})}setAuthState(e){this.onStateChange({type:"auth-state",state:e})}setStateCallback(e){this.onStateChange=e}ensureBodhiext(){if(!this.bodhiext&&window.bodhiext&&(this.logger.info("Acquiring window.bodhiext reference"),this.bodhiext=window.bodhiext),!this.bodhiext)throw r.createOperationError("not_initialized","Client not initialized")}async sendExtRequest(e,t){return this.ensureBodhiext(),this.bodhiext.sendExtRequest(e,t)}async sendApiRequest(e,t,i,s,o){this.ensureBodhiext();try{const n=new Promise((l,a)=>setTimeout(()=>a(new r.BodhiError("timeout_error",`[bodhi-js-sdk/web] network timeout: api request not completed within configured/default timeout of ${this.apiTimeoutMs}ms`)),this.apiTimeoutMs)),c=(async()=>{let l=s||{};if(o){const a=await this._getAccessTokenRaw();if(!a)throw new r.BodhiError("auth_error","Not authenticated. Please log in first.");l={...l,Authorization:`Bearer ${a}`}}return this.bodhiext.sendApiRequest(e,t,i,l)})();return await Promise.race([c,n])}catch(n){if(n instanceof r.BodhiApiError||n instanceof r.BodhiError)throw n;if(n instanceof Error){const c=n;throw n.name==="BodhiApiError"&&typeof c.status=="number"&&c.body!=null?new r.BodhiApiError(c.status,c.body,n.message,c.headers):n.name==="BodhiError"&&typeof c.code=="string"?new r.BodhiError(c.code,n.message):new r.BodhiError("network_error",n.message)}throw new r.BodhiError("network_error",String(n))}}getState(){return this.state}isClientInitialized(){return this.state.extension==="ready"}isServerReady(){return this.isClientInitialized()&&this.state.server.status==="ready"}async init(e={}){if(!e.testConnection&&!e.selectedConnection)return this.logger.info("No testConnection or selectedConnection, returning not-initialized state"),r.EXTENSION_STATE_NOT_INITIALIZED;if(this.bodhiext&&!e.testConnection)return this.logger.debug("Already have bodhiext handle, skipping polling"),this.state;if(!this.bodhiext){const s=e.timeoutMs??this.config.initParams?.extension?.timeoutMs??_,o=e.intervalMs??this.config.initParams?.extension?.intervalMs??m,n=Date.now();if(!await new Promise(l=>{const a=()=>{if(window.bodhiext){this.bodhiext=window.bodhiext,l(!0);return}if(Date.now()-n>=s){l(!1);return}setTimeout(a,o)};a()}))return this.logger.warn("Extension discovery timed out"),this.setState(r.EXTENSION_STATE_NOT_FOUND),this.state}const t=await this.bodhiext.getExtensionId();this.logger.info(`Extension discovered: ${t}`);const i={type:"extension",extension:"ready",extensionId:t,server:r.PENDING_EXTENSION_READY};if(e.testConnection)try{const s=await this.getServerState();this.setState({...i,server:s}),this.logger.info(`Server connectivity tested: ${s.status}`)}catch(s){this.logger.error("Failed to get server state:",s),this.setState({...i,server:r.BACKEND_SERVER_NOT_REACHABLE})}else this.setState(i);return this.state}async login(e){const t=await this.getAuthState();if(t.status==="authenticated")return t;this.ensureBodhiext();const i=e?.userRole??"scope_user_user",s=e?.flowType??"popup";e?.onProgress?.("requesting");const o=new r.AccessRequestBuilder(this.authClientId).requestedRole(i).flowType(s);if(e?.requested&&o.requested(e.requested),s==="redirect"){const u=e?.redirectUrl??this.config.redirectUri;o.redirectUrl(u)}const n=o.build(),c=await this.requestAccess(n),{id:l,review_url:a}=r.unwrapResponse(c);e?.onProgress?.("reviewing");let h;if(s==="popup"){const u=async()=>{const p=await this.getAccessRequestStatus(l);if(p.status>=400)return null;const{status:g,access_request_scope:E}=p.body;return g==="approved"?{approved:!0,accessRequestScope:E??void 0}:["denied","failed","expired"].includes(g)?{approved:!1,status:g}:null},d=await r.openPopupReview(a,u,{intervalMs:e?.pollIntervalMs??r.DEFAULT_POLL_INTERVAL_MS,timeoutMs:e?.pollTimeoutMs??r.DEFAULT_POLL_TIMEOUT_MS});d.approved||r.throwAccessRequestDenialError(d.status??"unknown"),h=d.accessRequestScope}else return localStorage.setItem(this.storageKeys.ACCESS_REQUEST_ID,l),window.location.href=a,new Promise(()=>{});return e?.onProgress?.("authenticating"),this.performOAuthPkce(`openid profile email roles ${h??""}`.trim())}async handleOAuthCallback(e,t){const i=localStorage.getItem(this.storageKeys.STATE);if(!i||i!==t)throw new Error("Invalid state parameter - possible CSRF attack");await this.exchangeCodeForTokens(e),localStorage.removeItem(this.storageKeys.CODE_VERIFIER),localStorage.removeItem(this.storageKeys.STATE);const s=await this.getAuthState();if(s.status!=="authenticated")throw new Error("Login failed");return this.setAuthState(s),s}async exchangeCodeForTokens(e){const t=localStorage.getItem(this.storageKeys.CODE_VERIFIER);if(!t)throw new Error("Code verifier not found");const i=new URLSearchParams({grant_type:"authorization_code",client_id:this.authClientId,code:e,redirect_uri:this.config.redirectUri,code_verifier:t}),s=await fetch(this.authEndpoints.token,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:i});if(!s.ok){const n=await s.text();throw new Error(`Token exchange failed: ${s.status} ${n}`)}const o=await s.json();if(!o.access_token)throw new Error("No access token received");if(localStorage.setItem(this.storageKeys.ACCESS_TOKEN,o.access_token),o.refresh_token&&localStorage.setItem(this.storageKeys.REFRESH_TOKEN,o.refresh_token),o.expires_in){const n=Date.now()+o.expires_in*1e3;localStorage.setItem(this.storageKeys.EXPIRES_AT,n.toString())}}async logout(){const e=localStorage.getItem(this.storageKeys.REFRESH_TOKEN);if(e)try{const i=new URLSearchParams({token:e,client_id:this.authClientId,token_type_hint:"refresh_token"});await fetch(this.authEndpoints.revoke,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:i})}catch(i){this.logger.warn("Token revocation failed:",i)}localStorage.removeItem(this.storageKeys.ACCESS_TOKEN),localStorage.removeItem(this.storageKeys.REFRESH_TOKEN),localStorage.removeItem(this.storageKeys.EXPIRES_AT),localStorage.removeItem(this.storageKeys.CODE_VERIFIER),localStorage.removeItem(this.storageKeys.STATE);const t={status:"unauthenticated",user:null,accessToken:null,error:null,refreshToken:null,expiresAt:null,isTokenRefresh:!1};return this.setAuthState(t),t}async getAuthState(){const e=await this._getAccessTokenRaw();if(!e)return{status:"unauthenticated",user:null,accessToken:null,error:null,refreshToken:null,expiresAt:null,isTokenRefresh:!1};try{return{status:"authenticated",user:r.extractUserInfo(e),accessToken:e,error:null,refreshToken:null,expiresAt:null,isTokenRefresh:!1}}catch(t){return this.logger.error("Failed to parse token:",t),{status:"unauthenticated",user:null,accessToken:null,error:null,refreshToken:null,expiresAt:null,isTokenRefresh:!1}}}async _getAccessTokenRaw(){const e=localStorage.getItem(this.storageKeys.ACCESS_TOKEN),t=localStorage.getItem(this.storageKeys.EXPIRES_AT);if(!e)return null;if(t){const i=parseInt(t,10);if(Date.now()>=i-5*1e3){const s=localStorage.getItem(this.storageKeys.REFRESH_TOKEN);return s?this._tryRefreshToken(s):null}}return e}async _tryRefreshToken(e){if(this.refreshPromise)return this.logger.debug("Refresh already in progress, returning existing promise"),this.refreshPromise;this.refreshPromise=this._doRefreshToken(e);try{return await this.refreshPromise}finally{this.refreshPromise=null}}async _doRefreshToken(e){this.logger.debug("Refreshing access token");try{const t=await r.refreshAccessToken(this.authEndpoints.token,e,this.authClientId);if(t.success){this._storeRefreshedTokens(t.tokens);const i=r.extractUserInfo(t.tokens.access_token);return this.setAuthState({status:"authenticated",user:i,accessToken:t.tokens.access_token,error:null,refreshToken:null,expiresAt:null,isTokenRefresh:!0}),this.logger.info("Token refreshed successfully"),t.tokens.access_token}if(t.error==="invalid_grant")return this.logger.warn("Refresh token expired or revoked, clearing tokens and logging out"),this.clearAuthStorage(),this.setAuthState({status:"unauthenticated",user:null,accessToken:null,error:null,refreshToken:null,expiresAt:null,isTokenRefresh:!1}),null}catch(t){this.logger.warn("Token refresh failed:",t)}throw this.logger.warn("Token refresh failed, keeping tokens for manual retry"),r.createOperationError("auth_error","Access token expired and unable to refresh. Try logging out and logging in again.")}clearAuthStorage(){localStorage.removeItem(this.storageKeys.ACCESS_TOKEN),localStorage.removeItem(this.storageKeys.REFRESH_TOKEN),localStorage.removeItem(this.storageKeys.EXPIRES_AT)}_storeRefreshedTokens(e){const t=Date.now()+e.expires_in*1e3;localStorage.setItem(this.storageKeys.ACCESS_TOKEN,e.access_token),localStorage.setItem(this.storageKeys.EXPIRES_AT,String(t)),e.refresh_token&&localStorage.setItem(this.storageKeys.REFRESH_TOKEN,e.refresh_token)}async pingApi(){return this.sendApiRequest("GET","/ping")}async getServerState(){try{const e=await this.sendApiRequest("GET","/bodhi/v1/info");if(e.status>=400)return r.BACKEND_SERVER_NOT_REACHABLE;const t=e.body,i=t.version||"unknown";switch(t.status){case"ready":return{status:"ready",version:i,error:null,deployment:t.deployment??null,client_id:t.client_id??null};case"setup":return r.backendServerNotReady("setup",i,void 0,t.deployment,t.client_id);case"resource_admin":return r.backendServerNotReady("resource_admin",i,void 0,t.deployment,t.client_id);case"error":return r.backendServerNotReady("error",i,t.error?{message:t.error.message,type:t.error.type}:r.SERVER_ERROR_CODES.SERVER_NOT_READY,t.deployment,t.client_id);default:return r.BACKEND_SERVER_NOT_REACHABLE}}catch{return r.BACKEND_SERVER_NOT_REACHABLE}}async*stream(e,t,i,s,o=!0){this.ensureBodhiext();let n=s||{};if(o){const a=await this._getAccessTokenRaw();if(!a)throw r.createOperationError("auth_error","Not authenticated. Please log in first.");n={...n,Authorization:`Bearer ${a}`}}const l=this.bodhiext.sendStreamRequest(e,t,i,n).getReader();try{for(;;){const{value:a,done:h}=await l.read();if(h||a?.done)break;yield a.body}}catch(a){if(a instanceof r.BodhiApiError||a instanceof r.BodhiError)throw a;if(a instanceof Error){const h=a;throw a.name==="BodhiApiError"&&typeof h.status=="number"&&h.body!=null?new r.BodhiApiError(h.status,h.body,a.message,h.headers):a.name==="BodhiError"&&typeof h.code=="string"?new r.BodhiError(h.code,a.message):new r.BodhiError("extension_error",a.message)}throw a}finally{l.releaseLock()}}async streamText(e,t,i,s,o=!0){this.ensureBodhiext();let n={...s};if(o){const a=await this._getAccessTokenRaw();a&&(n={...n,Authorization:`Bearer ${a}`})}const c=await this.bodhiext.sendStreamText(e,t,i,n);async function*l(a){const h=a.getReader();try{for(;;){const{done:u,value:d}=await h.read();if(u)break;yield d}}finally{h.releaseLock()}}return{status:c.status,headers:c.headers,body:l(c.body)}}get chat(){return this._chat??=new r.Chat(this)}get models(){return this._models??=new r.Models(this)}get embeddings(){return this._embeddings??=new r.Embeddings(this)}get mcps(){return this._mcps??=new r.Mcps(this)}async requestAccess(e){return this.sendApiRequest("POST","/bodhi/v1/apps/request-access",e,{},!1)}async getAccessRequestStatus(e){return this.sendApiRequest("GET",`/bodhi/v1/apps/access-requests/${e}?app_client_id=${encodeURIComponent(this.authClientId)}`,void 0,{},!1)}async pollAccessRequestStatus(e,t){return r.pollAccessRequestUntilResolved(i=>this.getAccessRequestStatus(i),e,t)}async performOAuthPkce(e){const t=r.generateCodeVerifier(),i=await r.generateCodeChallenge(t),s=r.generateCodeVerifier();localStorage.setItem(this.storageKeys.CODE_VERIFIER,t),localStorage.setItem(this.storageKeys.STATE,s);const o=e.split(" ").filter(Boolean),n=new URLSearchParams({response_type:"code",client_id:this.authClientId,redirect_uri:this.config.redirectUri,scope:o.join(" "),state:s,code_challenge:i,code_challenge_method:"S256"});return window.location.href=`${this.authEndpoints.authorize}?${n}`,new Promise(()=>{})}async handleAccessRequestCallback(e){const t=await this.getAccessRequestStatus(e),{status:i,access_request_scope:s}=r.unwrapResponse(t);localStorage.removeItem(this.storageKeys.ACCESS_REQUEST_ID),i!=="approved"&&r.throwAccessRequestDenialError(i);const o=`openid profile email roles ${s??""}`.trim();return this.performOAuthPkce(o)}serialize(){return{extensionId:this.state.type==="extension"&&this.state.extension==="ready"?this.state.extensionId:void 0}}async debug(){return{type:"WindowBodhiextClient",state:this.state,authState:await this.getAuthState(),bodhiextAvailable:this.bodhiext!==null,authClientId:this.authClientId,authServerUrl:this.config.authServerUrl,redirectUri:this.config.redirectUri}}}function y(f){if(typeof window>"u")throw new Error("redirectUri required in non-browser environment");const e=f==="/"?"":f.replace(/\/$/,"");return`${window.location.origin}${e}/callback`}class A extends r.BaseFacadeClient{constructor(e,t,i){const s=t||{},o={basePath:s.basePath||"/",redirectUri:s.redirectUri||y(s.basePath||"/"),authServerUrl:s.authServerUrl||"https://id.getbodhi.app/realms/bodhi",logLevel:s.logLevel||"warn",apiTimeoutMs:s.apiTimeoutMs,storage:s.storage,initialTokens:s.initialTokens,initParams:s.initParams};super(e,o,i)}createLogger(e){return new r.Logger("WebUIClient",e.logLevel)}createStoragePrefix(e){return r.createStoragePrefixWithNamespace(e.basePath,r.STORAGE_PREFIXES.WEB)}createExtClient(e,t){return new R(this.authClientId,{authServerUrl:e.authServerUrl,redirectUri:e.redirectUri,basePath:e.basePath,logLevel:e.logLevel,apiTimeoutMs:e.apiTimeoutMs,initParams:e.initParams},t)}createDirectClient(e,t,i){return new w({authClientId:e,authServerUrl:t.authServerUrl,redirectUri:t.redirectUri,logLevel:t.logLevel,basePath:t.basePath,apiTimeoutMs:t.apiTimeoutMs,storage:t.storage,initialTokens:t.initialTokens},i)}async handleOAuthCallback(e,t){return this.connectionMode==="direct"?this.directClient.handleOAuthCallback(e,t):this.extClient.handleOAuthCallback(e,t)}async handleAccessRequestCallback(e){return this.connectionMode==="direct"?this.directClient.handleAccessRequestCallback(e):this.extClient.handleAccessRequestCallback(e)}}const k="production";Object.defineProperty(exports,"InMemoryStorage",{enumerable:!0,get:()=>r.InMemoryStorage});exports.DirectWebClient=w;exports.LocalStorageAdapter=S;exports.WEB_BUILD_MODE=k;exports.WebUIClient=A;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("@bodhiapp/bodhi-js-core");class E{async get(e){return localStorage.getItem(e)}async set(e){Object.entries(e).forEach(([t,i])=>{localStorage.setItem(t,String(i))})}async remove(e){e.forEach(t=>localStorage.removeItem(t))}}class f extends r.DirectClientBase{constructor(e,t){const i=r.createStoragePrefixWithNamespace(e.basePath,r.STORAGE_PREFIXES.WEB_DIRECT),s={authClientId:e.authClientId,authServerUrl:e.authServerUrl,storagePrefix:i,logLevel:e.logLevel,loggerPrefix:"DirectWebClient",apiTimeoutMs:e.apiTimeoutMs,storage:e.storage??new E,initialTokens:e.initialTokens};super(s,t),this.redirectUri=e.redirectUri}async login(e){const t=await this.getAuthState();if(t.status==="authenticated")return t;const i=e?.userRole??"scope_user_user",s=this.redirectUri;e?.onProgress?.("requesting");const a=r.generateCodeVerifier(),n=await r.generateCodeChallenge(a),h=r.generateCodeVerifier();await this._storageSet({[this.storageKeys.CODE_VERIFIER]:a,[this.storageKeys.STATE]:h});const c=r.buildAuthorizeUrl(this.authEndpoints,{clientId:this.authClientId,redirectUri:s,scope:r.BASE_OAUTH_SCOPE,state:h,codeChallenge:n}),o=r.buildErrorUrl(s),l=new r.AccessRequestBuilder(this.authClientId).requestedRole(i);e?.requested&&l.requested(e.requested);const d=await this.requestAccess(l.build()),{review_url:g}=r.unwrapResponse(d);return e?.onProgress?.("reviewing"),window.location.href=r.buildReviewUrl(g,c,o),new Promise(()=>{})}async handleOAuthCallback(e,t){const i=await this._storageGet(this.storageKeys.STATE);if(!i||i!==t)throw new Error("Invalid state parameter - possible CSRF attack");await this.exchangeCodeForTokens(e);const s=await this.getAuthState();if(s.status!=="authenticated")throw new Error("Login failed");return this.setAuthState(s),s}_getRedirectUri(){return this.redirectUri}}const S=500,w=5e3,T=3e4;class m{constructor(e,t,i){this.state=r.EXTENSION_STATE_NOT_INITIALIZED,this.bodhiext=null,this.refreshPromise=null,this.logger=new r.Logger("WindowBodhiextClient",t.logLevel),this.authClientId=e,this.config=t,this.authEndpoints=r.createOAuthEndpoints(this.config.authServerUrl),this.onStateChange=i??r.NOOP_STATE_CALLBACK;const s=r.createStoragePrefixWithNamespace(t.basePath,r.STORAGE_PREFIXES.WEB_EXT);this.storageKeys=r.createStorageKeys(s),this.apiTimeoutMs=t.apiTimeoutMs??T}setState(e){this.state=e,this.logger.info(`{state: ${JSON.stringify(e)}} - Setting client state`),this.onStateChange({type:"client-state",state:e})}setAuthState(e){this.onStateChange({type:"auth-state",state:e})}setStateCallback(e){this.onStateChange=e}ensureBodhiext(){if(!this.bodhiext&&window.bodhiext&&(this.logger.info("Acquiring window.bodhiext reference"),this.bodhiext=window.bodhiext),!this.bodhiext)throw r.createOperationError("not_initialized","Client not initialized")}async sendExtRequest(e,t){return this.ensureBodhiext(),this.bodhiext.sendExtRequest(e,t)}async sendApiRequest(e,t,i,s,a){this.ensureBodhiext();try{const n=new Promise((c,o)=>setTimeout(()=>o(new r.BodhiError("timeout_error",`[bodhi-js-sdk/web] network timeout: api request not completed within configured/default timeout of ${this.apiTimeoutMs}ms`)),this.apiTimeoutMs)),h=(async()=>{let c=s||{};if(a){const o=await this._getAccessTokenRaw();if(!o)throw new r.BodhiError("auth_error","Not authenticated. Please log in first.");c={...c,Authorization:`Bearer ${o}`}}return this.bodhiext.sendApiRequest(e,t,i,c)})();return await Promise.race([h,n])}catch(n){if(n instanceof r.BodhiApiError||n instanceof r.BodhiError)throw n;if(n instanceof Error){const h=n;throw n.name==="BodhiApiError"&&typeof h.status=="number"&&h.body!=null?new r.BodhiApiError(h.status,h.body,n.message,h.headers):n.name==="BodhiError"&&typeof h.code=="string"?new r.BodhiError(h.code,n.message):new r.BodhiError("network_error",n.message)}throw new r.BodhiError("network_error",String(n))}}getState(){return this.state}isClientInitialized(){return this.state.extension==="ready"}isServerReady(){return this.isClientInitialized()&&this.state.server.status==="ready"}async init(e={}){if(!e.testConnection&&!e.selectedConnection)return this.logger.info("No testConnection or selectedConnection, returning not-initialized state"),r.EXTENSION_STATE_NOT_INITIALIZED;if(this.bodhiext&&!e.testConnection)return this.logger.debug("Already have bodhiext handle, skipping polling"),this.state;if(!this.bodhiext){const s=e.timeoutMs??this.config.initParams?.extension?.timeoutMs??w,a=e.intervalMs??this.config.initParams?.extension?.intervalMs??S,n=Date.now();if(!await new Promise(c=>{const o=()=>{if(window.bodhiext){this.bodhiext=window.bodhiext,c(!0);return}if(Date.now()-n>=s){c(!1);return}setTimeout(o,a)};o()}))return this.logger.warn("Extension discovery timed out"),this.setState(r.EXTENSION_STATE_NOT_FOUND),this.state}const t=await this.bodhiext.getExtensionId();this.logger.info(`Extension discovered: ${t}`);const i={type:"extension",extension:"ready",extensionId:t,server:r.PENDING_EXTENSION_READY};if(e.testConnection)try{const s=await this.getServerState();this.setState({...i,server:s}),this.logger.info(`Server connectivity tested: ${s.status}`)}catch(s){this.logger.error("Failed to get server state:",s),this.setState({...i,server:r.BACKEND_SERVER_NOT_REACHABLE})}else this.setState(i);return this.state}async login(e){const t=await this.getAuthState();if(t.status==="authenticated")return t;this.ensureBodhiext();const i=e?.userRole??"scope_user_user",s=this.config.redirectUri;e?.onProgress?.("requesting");const a=r.generateCodeVerifier(),n=await r.generateCodeChallenge(a),h=r.generateCodeVerifier();localStorage.setItem(this.storageKeys.CODE_VERIFIER,a),localStorage.setItem(this.storageKeys.STATE,h);const c=r.buildAuthorizeUrl(this.authEndpoints,{clientId:this.authClientId,redirectUri:s,scope:r.BASE_OAUTH_SCOPE,state:h,codeChallenge:n}),o=r.buildErrorUrl(s),l=new r.AccessRequestBuilder(this.authClientId).requestedRole(i);e?.requested&&l.requested(e.requested);const d=await this.requestAccess(l.build()),{review_url:g}=r.unwrapResponse(d);return e?.onProgress?.("reviewing"),window.location.href=r.buildReviewUrl(g,c,o),new Promise(()=>{})}async handleOAuthCallback(e,t){const i=localStorage.getItem(this.storageKeys.STATE);if(!i||i!==t)throw new Error("Invalid state parameter - possible CSRF attack");await this.exchangeCodeForTokens(e),localStorage.removeItem(this.storageKeys.CODE_VERIFIER),localStorage.removeItem(this.storageKeys.STATE);const s=await this.getAuthState();if(s.status!=="authenticated")throw new Error("Login failed");return this.setAuthState(s),s}async exchangeCodeForTokens(e){const t=localStorage.getItem(this.storageKeys.CODE_VERIFIER);if(!t)throw new Error("Code verifier not found");const i=new URLSearchParams({grant_type:"authorization_code",client_id:this.authClientId,code:e,redirect_uri:this.config.redirectUri,code_verifier:t}),s=await fetch(this.authEndpoints.token,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:i});if(!s.ok){const n=await s.text();throw new Error(`Token exchange failed: ${s.status} ${n}`)}const a=await s.json();if(!a.access_token)throw new Error("No access token received");if(localStorage.setItem(this.storageKeys.ACCESS_TOKEN,a.access_token),a.refresh_token&&localStorage.setItem(this.storageKeys.REFRESH_TOKEN,a.refresh_token),a.expires_in){const n=Date.now()+a.expires_in*1e3;localStorage.setItem(this.storageKeys.EXPIRES_AT,n.toString())}}async logout(){const e=localStorage.getItem(this.storageKeys.REFRESH_TOKEN);if(e)try{const i=new URLSearchParams({token:e,client_id:this.authClientId,token_type_hint:"refresh_token"});await fetch(this.authEndpoints.revoke,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:i})}catch(i){this.logger.warn("Token revocation failed:",i)}localStorage.removeItem(this.storageKeys.ACCESS_TOKEN),localStorage.removeItem(this.storageKeys.REFRESH_TOKEN),localStorage.removeItem(this.storageKeys.EXPIRES_AT),localStorage.removeItem(this.storageKeys.CODE_VERIFIER),localStorage.removeItem(this.storageKeys.STATE);const t={status:"unauthenticated",user:null,accessToken:null,error:null,refreshToken:null,expiresAt:null,isTokenRefresh:!1};return this.setAuthState(t),t}async getAuthState(){const e=await this._getAccessTokenRaw();if(!e)return{status:"unauthenticated",user:null,accessToken:null,error:null,refreshToken:null,expiresAt:null,isTokenRefresh:!1};try{return{status:"authenticated",user:r.extractUserInfo(e),accessToken:e,error:null,refreshToken:null,expiresAt:null,isTokenRefresh:!1}}catch(t){return this.logger.error("Failed to parse token:",t),{status:"unauthenticated",user:null,accessToken:null,error:null,refreshToken:null,expiresAt:null,isTokenRefresh:!1}}}async _getAccessTokenRaw(){const e=localStorage.getItem(this.storageKeys.ACCESS_TOKEN),t=localStorage.getItem(this.storageKeys.EXPIRES_AT);if(!e)return null;if(t){const i=parseInt(t,10);if(Date.now()>=i-5*1e3){const s=localStorage.getItem(this.storageKeys.REFRESH_TOKEN);return s?this._tryRefreshToken(s):null}}return e}async _tryRefreshToken(e){if(this.refreshPromise)return this.logger.debug("Refresh already in progress, returning existing promise"),this.refreshPromise;this.refreshPromise=this._doRefreshToken(e);try{return await this.refreshPromise}finally{this.refreshPromise=null}}async _doRefreshToken(e){this.logger.debug("Refreshing access token");try{const t=await r.refreshAccessToken(this.authEndpoints.token,e,this.authClientId);if(t.success){this._storeRefreshedTokens(t.tokens);const i=r.extractUserInfo(t.tokens.access_token);return this.setAuthState({status:"authenticated",user:i,accessToken:t.tokens.access_token,error:null,refreshToken:null,expiresAt:null,isTokenRefresh:!0}),this.logger.info("Token refreshed successfully"),t.tokens.access_token}if(t.error==="invalid_grant")return this.logger.warn("Refresh token expired or revoked, clearing tokens and logging out"),this.clearAuthStorage(),this.setAuthState({status:"unauthenticated",user:null,accessToken:null,error:null,refreshToken:null,expiresAt:null,isTokenRefresh:!1}),null}catch(t){this.logger.warn("Token refresh failed:",t)}throw this.logger.warn("Token refresh failed, keeping tokens for manual retry"),r.createOperationError("auth_error","Access token expired and unable to refresh. Try logging out and logging in again.")}clearAuthStorage(){localStorage.removeItem(this.storageKeys.ACCESS_TOKEN),localStorage.removeItem(this.storageKeys.REFRESH_TOKEN),localStorage.removeItem(this.storageKeys.EXPIRES_AT)}_storeRefreshedTokens(e){const t=Date.now()+e.expires_in*1e3;localStorage.setItem(this.storageKeys.ACCESS_TOKEN,e.access_token),localStorage.setItem(this.storageKeys.EXPIRES_AT,String(t)),e.refresh_token&&localStorage.setItem(this.storageKeys.REFRESH_TOKEN,e.refresh_token)}async pingApi(){return this.sendApiRequest("GET","/ping")}async getServerState(){try{const e=await this.sendApiRequest("GET","/bodhi/v1/info");if(e.status>=400)return r.BACKEND_SERVER_NOT_REACHABLE;const t=e.body,i=t.version||"unknown";switch(t.status){case"ready":return{status:"ready",version:i,error:null,deployment:t.deployment??null,client_id:t.client_id??null};case"setup":return r.backendServerNotReady("setup",i,void 0,t.deployment,t.client_id);case"resource_admin":return r.backendServerNotReady("resource_admin",i,void 0,t.deployment,t.client_id);case"error":return r.backendServerNotReady("error",i,t.error?{message:t.error.message,type:t.error.type}:r.SERVER_ERROR_CODES.SERVER_NOT_READY,t.deployment,t.client_id);default:return r.BACKEND_SERVER_NOT_REACHABLE}}catch{return r.BACKEND_SERVER_NOT_REACHABLE}}async*stream(e,t,i,s,a=!0){this.ensureBodhiext();let n=s||{};if(a){const o=await this._getAccessTokenRaw();if(!o)throw r.createOperationError("auth_error","Not authenticated. Please log in first.");n={...n,Authorization:`Bearer ${o}`}}const c=this.bodhiext.sendStreamRequest(e,t,i,n).getReader();try{for(;;){const{value:o,done:l}=await c.read();if(l||o?.done)break;yield o.body}}catch(o){if(o instanceof r.BodhiApiError||o instanceof r.BodhiError)throw o;if(o instanceof Error){const l=o;throw o.name==="BodhiApiError"&&typeof l.status=="number"&&l.body!=null?new r.BodhiApiError(l.status,l.body,o.message,l.headers):o.name==="BodhiError"&&typeof l.code=="string"?new r.BodhiError(l.code,o.message):new r.BodhiError("extension_error",o.message)}throw o}finally{c.releaseLock()}}async streamText(e,t,i,s,a=!0){this.ensureBodhiext();let n={...s};if(a){const o=await this._getAccessTokenRaw();o&&(n={...n,Authorization:`Bearer ${o}`})}const h=await this.bodhiext.sendStreamText(e,t,i,n);async function*c(o){const l=o.getReader();try{for(;;){const{done:d,value:g}=await l.read();if(d)break;yield g}}finally{l.releaseLock()}}return{status:h.status,headers:h.headers,body:c(h.body)}}get chat(){return this._chat??=new r.Chat(this)}get models(){return this._models??=new r.Models(this)}get embeddings(){return this._embeddings??=new r.Embeddings(this)}get mcps(){return this._mcps??=new r.Mcps(this)}async requestAccess(e){return this.sendApiRequest("POST","/bodhi/v1/apps/request-access",e,{},!1)}serialize(){return{extensionId:this.state.type==="extension"&&this.state.extension==="ready"?this.state.extensionId:void 0}}async debug(){return{type:"WindowBodhiextClient",state:this.state,authState:await this.getAuthState(),bodhiextAvailable:this.bodhiext!==null,authClientId:this.authClientId,authServerUrl:this.config.authServerUrl,redirectUri:this.config.redirectUri}}}function _(u){if(typeof window>"u")throw new Error("redirectUri required in non-browser environment");const e=u==="/"?"":u.replace(/\/$/,"");return`${window.location.origin}${e}/callback`}class y extends r.BaseFacadeClient{constructor(e,t,i){const s=t||{},a={basePath:s.basePath||"/",redirectUri:s.redirectUri||_(s.basePath||"/"),authServerUrl:s.authServerUrl||"https://id.getbodhi.app/realms/bodhi",logLevel:s.logLevel||"warn",apiTimeoutMs:s.apiTimeoutMs,storage:s.storage,initialTokens:s.initialTokens,initParams:s.initParams};super(e,a,i)}createLogger(e){return new r.Logger("WebUIClient",e.logLevel)}createStoragePrefix(e){return r.createStoragePrefixWithNamespace(e.basePath,r.STORAGE_PREFIXES.WEB)}createExtClient(e,t){return new m(this.authClientId,{authServerUrl:e.authServerUrl,redirectUri:e.redirectUri,basePath:e.basePath,logLevel:e.logLevel,apiTimeoutMs:e.apiTimeoutMs,initParams:e.initParams},t)}createDirectClient(e,t,i){return new f({authClientId:e,authServerUrl:t.authServerUrl,redirectUri:t.redirectUri,logLevel:t.logLevel,basePath:t.basePath,apiTimeoutMs:t.apiTimeoutMs,storage:t.storage,initialTokens:t.initialTokens},i)}async handleOAuthCallback(e,t){return this.connectionMode==="direct"?this.directClient.handleOAuthCallback(e,t):this.extClient.handleOAuthCallback(e,t)}}const A="production";Object.defineProperty(exports,"InMemoryStorage",{enumerable:!0,get:()=>r.InMemoryStorage});exports.DirectWebClient=f;exports.LocalStorageAdapter=E;exports.WEB_BUILD_MODE=A;exports.WebUIClient=y;
@@ -1,34 +1,34 @@
1
- import { DirectClientBase as O, createStoragePrefixWithNamespace as A, STORAGE_PREFIXES as k, AccessRequestBuilder as C, unwrapResponse as S, openPopupReview as b, DEFAULT_POLL_TIMEOUT_MS as x, DEFAULT_POLL_INTERVAL_MS as P, throwAccessRequestDenialError as E, generateCodeVerifier as _, generateCodeChallenge as U, EXTENSION_STATE_NOT_INITIALIZED as v, Logger as q, createOAuthEndpoints as K, NOOP_STATE_CALLBACK as L, createStorageKeys as M, createOperationError as y, BodhiError as u, BodhiApiError as w, EXTENSION_STATE_NOT_FOUND as D, PENDING_EXTENSION_READY as N, BACKEND_SERVER_NOT_REACHABLE as m, extractUserInfo as I, refreshAccessToken as B, backendServerNotReady as R, SERVER_ERROR_CODES as F, Chat as $, Models as z, Embeddings as V, Mcps as W, pollAccessRequestUntilResolved as H, BaseFacadeClient as X } from "@bodhiapp/bodhi-js-core";
2
- import { InMemoryStorage as ae } from "@bodhiapp/bodhi-js-core";
3
- class G {
1
+ import { DirectClientBase as P, createStoragePrefixWithNamespace as T, STORAGE_PREFIXES as y, generateCodeVerifier as S, generateCodeChallenge as k, buildAuthorizeUrl as R, BASE_OAUTH_SCOPE as A, buildErrorUrl as I, AccessRequestBuilder as x, unwrapResponse as b, buildReviewUrl as C, EXTENSION_STATE_NOT_INITIALIZED as _, Logger as v, createOAuthEndpoints as U, NOOP_STATE_CALLBACK as O, createStorageKeys as K, createOperationError as E, BodhiError as c, BodhiApiError as f, EXTENSION_STATE_NOT_FOUND as N, PENDING_EXTENSION_READY as B, BACKEND_SERVER_NOT_REACHABLE as w, extractUserInfo as p, refreshAccessToken as q, backendServerNotReady as m, SERVER_ERROR_CODES as L, Chat as D, Models as M, Embeddings as F, Mcps as z, BaseFacadeClient as V } from "@bodhiapp/bodhi-js-core";
2
+ import { InMemoryStorage as re } from "@bodhiapp/bodhi-js-core";
3
+ class W {
4
4
  async get(e) {
5
5
  return localStorage.getItem(e);
6
6
  }
7
7
  async set(e) {
8
- Object.entries(e).forEach(([t, r]) => {
9
- localStorage.setItem(t, String(r));
8
+ Object.entries(e).forEach(([t, s]) => {
9
+ localStorage.setItem(t, String(s));
10
10
  });
11
11
  }
12
12
  async remove(e) {
13
13
  e.forEach((t) => localStorage.removeItem(t));
14
14
  }
15
15
  }
16
- class j extends O {
16
+ class $ extends P {
17
17
  constructor(e, t) {
18
- const r = A(
18
+ const s = T(
19
19
  e.basePath,
20
- k.WEB_DIRECT
21
- ), s = {
20
+ y.WEB_DIRECT
21
+ ), r = {
22
22
  authClientId: e.authClientId,
23
23
  authServerUrl: e.authServerUrl,
24
- storagePrefix: r,
24
+ storagePrefix: s,
25
25
  logLevel: e.logLevel,
26
26
  loggerPrefix: "DirectWebClient",
27
27
  apiTimeoutMs: e.apiTimeoutMs,
28
- storage: e.storage ?? new G(),
28
+ storage: e.storage ?? new W(),
29
29
  initialTokens: e.initialTokens
30
30
  };
31
- super(s, t), this.redirectUri = e.redirectUri;
31
+ super(r, t), this.redirectUri = e.redirectUri;
32
32
  }
33
33
  // ============================================================================
34
34
  // Authentication (Browser Redirect OAuth)
@@ -37,67 +37,45 @@ class j extends O {
37
37
  const t = await this.getAuthState();
38
38
  if (t.status === "authenticated")
39
39
  return t;
40
- const r = e?.userRole ?? "scope_user_user", s = e?.flowType ?? "popup";
40
+ const s = e?.userRole ?? "scope_user_user", r = this.redirectUri;
41
41
  e?.onProgress?.("requesting");
42
- const i = new C(this.authClientId).requestedRole(r).flowType(s);
43
- if (e?.requested && i.requested(e.requested), s === "redirect") {
44
- const d = e?.redirectUrl ?? this.redirectUri;
45
- i.redirectUrl(d);
46
- }
47
- const a = i.build(), n = await this.requestAccess(a), { id: c, review_url: o } = S(n);
48
- e?.onProgress?.("reviewing");
49
- let l;
50
- if (s === "popup") {
51
- const h = await b(o, async () => {
52
- const p = await this.getAccessRequestStatus(c);
53
- if (p.status >= 400) return null;
54
- const { status: g, access_request_scope: T } = p.body;
55
- return g === "approved" ? { approved: !0, accessRequestScope: T ?? void 0 } : ["denied", "failed", "expired"].includes(g) ? { approved: !1, status: g } : null;
56
- }, {
57
- intervalMs: e?.pollIntervalMs ?? P,
58
- timeoutMs: e?.pollTimeoutMs ?? x
59
- });
60
- h.approved || E(h.status ?? "unknown"), l = h.accessRequestScope;
61
- } else
62
- return await this._storageSet({ [this.storageKeys.ACCESS_REQUEST_ID]: c }), window.location.href = o, new Promise(() => {
63
- });
64
- return e?.onProgress?.("authenticating"), this.performOAuthPkce(`openid profile email roles ${l ?? ""}`.trim());
65
- }
66
- async performOAuthPkce(e) {
67
- const t = _(), r = await U(t), s = _();
42
+ const n = S(), o = await k(n), a = S();
68
43
  await this._storageSet({
69
- [this.storageKeys.CODE_VERIFIER]: t,
70
- [this.storageKeys.STATE]: s
44
+ [this.storageKeys.CODE_VERIFIER]: n,
45
+ [this.storageKeys.STATE]: a
46
+ });
47
+ const l = R(this.authEndpoints, {
48
+ clientId: this.authClientId,
49
+ redirectUri: r,
50
+ scope: A,
51
+ state: a,
52
+ codeChallenge: o
53
+ }), i = I(r), h = new x(this.authClientId).requestedRole(s);
54
+ e?.requested && h.requested(e.requested);
55
+ const d = await this.requestAccess(h.build()), { review_url: g } = b(d);
56
+ return e?.onProgress?.("reviewing"), window.location.href = C(g, l, i), new Promise(() => {
71
57
  });
72
- const i = new URL(this.authEndpoints.authorize);
73
- throw i.searchParams.set("client_id", this.authClientId), i.searchParams.set("response_type", "code"), i.searchParams.set("redirect_uri", this.redirectUri), i.searchParams.set("scope", e), i.searchParams.set("code_challenge", r), i.searchParams.set("code_challenge_method", "S256"), i.searchParams.set("state", s), window.location.href = i.toString(), new Error("Redirect initiated");
74
58
  }
75
59
  async handleOAuthCallback(e, t) {
76
- const r = await this._storageGet(this.storageKeys.STATE);
77
- if (!r || r !== t)
60
+ const s = await this._storageGet(this.storageKeys.STATE);
61
+ if (!s || s !== t)
78
62
  throw new Error("Invalid state parameter - possible CSRF attack");
79
63
  await this.exchangeCodeForTokens(e);
80
- const s = await this.getAuthState();
81
- if (s.status !== "authenticated")
64
+ const r = await this.getAuthState();
65
+ if (r.status !== "authenticated")
82
66
  throw new Error("Login failed");
83
- return this.setAuthState(s), s;
84
- }
85
- async handleAccessRequestCallback(e) {
86
- const t = await this.getAccessRequestStatus(e), { status: r, access_request_scope: s } = S(t);
87
- await this._storageRemove([this.storageKeys.ACCESS_REQUEST_ID]), r !== "approved" && E(r);
88
- const i = `openid profile email roles ${s ?? ""}`.trim();
89
- return this.performOAuthPkce(i);
67
+ return this.setAuthState(r), r;
90
68
  }
91
69
  _getRedirectUri() {
92
70
  return this.redirectUri;
93
71
  }
94
72
  }
95
- const Q = 500, Y = 5e3, J = 3e4;
96
- class Z {
97
- constructor(e, t, r) {
98
- this.state = v, this.bodhiext = null, this.refreshPromise = null, this.logger = new q("WindowBodhiextClient", t.logLevel), this.authClientId = e, this.config = t, this.authEndpoints = K(this.config.authServerUrl), this.onStateChange = r ?? L;
99
- const s = A(t.basePath, k.WEB_EXT);
100
- this.storageKeys = M(s), this.apiTimeoutMs = t.apiTimeoutMs ?? J;
73
+ const H = 500, X = 5e3, G = 3e4;
74
+ class j {
75
+ constructor(e, t, s) {
76
+ this.state = _, this.bodhiext = null, this.refreshPromise = null, this.logger = new v("WindowBodhiextClient", t.logLevel), this.authClientId = e, this.config = t, this.authEndpoints = U(this.config.authServerUrl), this.onStateChange = s ?? O;
77
+ const r = T(t.basePath, y.WEB_EXT);
78
+ this.storageKeys = K(r), this.apiTimeoutMs = t.apiTimeoutMs ?? G;
101
79
  }
102
80
  /**
103
81
  * Set client state and notify callback
@@ -126,7 +104,7 @@ class Z {
126
104
  */
127
105
  ensureBodhiext() {
128
106
  if (!this.bodhiext && window.bodhiext && (this.logger.info("Acquiring window.bodhiext reference"), this.bodhiext = window.bodhiext), !this.bodhiext)
129
- throw y("not_initialized", "Client not initialized");
107
+ throw E("not_initialized", "Client not initialized");
130
108
  }
131
109
  /**
132
110
  * Send extension request via window.bodhiext.sendExtRequest
@@ -138,45 +116,45 @@ class Z {
138
116
  * Send API message via window.bodhiext.sendApiRequest
139
117
  * @throws BodhiError on operational errors (extension not ready, auth, network, timeout)
140
118
  */
141
- async sendApiRequest(e, t, r, s, i) {
119
+ async sendApiRequest(e, t, s, r, n) {
142
120
  this.ensureBodhiext();
143
121
  try {
144
- const a = new Promise(
145
- (c, o) => setTimeout(
146
- () => o(
147
- new u(
122
+ const o = new Promise(
123
+ (l, i) => setTimeout(
124
+ () => i(
125
+ new c(
148
126
  "timeout_error",
149
127
  `[bodhi-js-sdk/web] network timeout: api request not completed within configured/default timeout of ${this.apiTimeoutMs}ms`
150
128
  )
151
129
  ),
152
130
  this.apiTimeoutMs
153
131
  )
154
- ), n = (async () => {
155
- let c = s || {};
156
- if (i) {
157
- const o = await this._getAccessTokenRaw();
158
- if (!o)
159
- throw new u("auth_error", "Not authenticated. Please log in first.");
160
- c = {
161
- ...c,
162
- Authorization: `Bearer ${o}`
132
+ ), a = (async () => {
133
+ let l = r || {};
134
+ if (n) {
135
+ const i = await this._getAccessTokenRaw();
136
+ if (!i)
137
+ throw new c("auth_error", "Not authenticated. Please log in first.");
138
+ l = {
139
+ ...l,
140
+ Authorization: `Bearer ${i}`
163
141
  };
164
142
  }
165
- return this.bodhiext.sendApiRequest(e, t, r, c);
143
+ return this.bodhiext.sendApiRequest(e, t, s, l);
166
144
  })();
167
- return await Promise.race([n, a]);
168
- } catch (a) {
169
- if (a instanceof w || a instanceof u) throw a;
170
- if (a instanceof Error) {
171
- const n = a;
172
- throw a.name === "BodhiApiError" && typeof n.status == "number" && n.body != null ? new w(
173
- n.status,
174
- n.body,
175
- a.message,
176
- n.headers
177
- ) : a.name === "BodhiError" && typeof n.code == "string" ? new u(n.code, a.message) : new u("network_error", a.message);
145
+ return await Promise.race([a, o]);
146
+ } catch (o) {
147
+ if (o instanceof f || o instanceof c) throw o;
148
+ if (o instanceof Error) {
149
+ const a = o;
150
+ throw o.name === "BodhiApiError" && typeof a.status == "number" && a.body != null ? new f(
151
+ a.status,
152
+ a.body,
153
+ o.message,
154
+ a.headers
155
+ ) : o.name === "BodhiError" && typeof a.code == "string" ? new c(a.code, o.message) : new c("network_error", o.message);
178
156
  }
179
- throw new u("network_error", String(a));
157
+ throw new c("network_error", String(o));
180
158
  }
181
159
  }
182
160
  /**
@@ -200,44 +178,44 @@ class Z {
200
178
  */
201
179
  async init(e = {}) {
202
180
  if (!e.testConnection && !e.selectedConnection)
203
- return this.logger.info("No testConnection or selectedConnection, returning not-initialized state"), v;
181
+ return this.logger.info("No testConnection or selectedConnection, returning not-initialized state"), _;
204
182
  if (this.bodhiext && !e.testConnection)
205
183
  return this.logger.debug("Already have bodhiext handle, skipping polling"), this.state;
206
184
  if (!this.bodhiext) {
207
- const s = e.timeoutMs ?? this.config.initParams?.extension?.timeoutMs ?? Y, i = e.intervalMs ?? this.config.initParams?.extension?.intervalMs ?? Q, a = Date.now();
208
- if (!await new Promise((c) => {
209
- const o = () => {
185
+ const r = e.timeoutMs ?? this.config.initParams?.extension?.timeoutMs ?? X, n = e.intervalMs ?? this.config.initParams?.extension?.intervalMs ?? H, o = Date.now();
186
+ if (!await new Promise((l) => {
187
+ const i = () => {
210
188
  if (window.bodhiext) {
211
- this.bodhiext = window.bodhiext, c(!0);
189
+ this.bodhiext = window.bodhiext, l(!0);
212
190
  return;
213
191
  }
214
- if (Date.now() - a >= s) {
215
- c(!1);
192
+ if (Date.now() - o >= r) {
193
+ l(!1);
216
194
  return;
217
195
  }
218
- setTimeout(o, i);
196
+ setTimeout(i, n);
219
197
  };
220
- o();
198
+ i();
221
199
  }))
222
- return this.logger.warn("Extension discovery timed out"), this.setState(D), this.state;
200
+ return this.logger.warn("Extension discovery timed out"), this.setState(N), this.state;
223
201
  }
224
202
  const t = await this.bodhiext.getExtensionId();
225
203
  this.logger.info(`Extension discovered: ${t}`);
226
- const r = {
204
+ const s = {
227
205
  type: "extension",
228
206
  extension: "ready",
229
207
  extensionId: t,
230
- server: N
208
+ server: B
231
209
  };
232
210
  if (e.testConnection)
233
211
  try {
234
- const s = await this.getServerState();
235
- this.setState({ ...r, server: s }), this.logger.info(`Server connectivity tested: ${s.status}`);
236
- } catch (s) {
237
- this.logger.error("Failed to get server state:", s), this.setState({ ...r, server: m });
212
+ const r = await this.getServerState();
213
+ this.setState({ ...s, server: r }), this.logger.info(`Server connectivity tested: ${r.status}`);
214
+ } catch (r) {
215
+ this.logger.error("Failed to get server state:", r), this.setState({ ...s, server: w });
238
216
  }
239
217
  else
240
- this.setState(r);
218
+ this.setState(s);
241
219
  return this.state;
242
220
  }
243
221
  // ============================================================================
@@ -253,31 +231,21 @@ class Z {
253
231
  if (t.status === "authenticated")
254
232
  return t;
255
233
  this.ensureBodhiext();
256
- const r = e?.userRole ?? "scope_user_user", s = e?.flowType ?? "popup";
234
+ const s = e?.userRole ?? "scope_user_user", r = this.config.redirectUri;
257
235
  e?.onProgress?.("requesting");
258
- const i = new C(this.authClientId).requestedRole(r).flowType(s);
259
- if (e?.requested && i.requested(e.requested), s === "redirect") {
260
- const d = e?.redirectUrl ?? this.config.redirectUri;
261
- i.redirectUrl(d);
262
- }
263
- const a = i.build(), n = await this.requestAccess(a), { id: c, review_url: o } = S(n);
264
- e?.onProgress?.("reviewing");
265
- let l;
266
- if (s === "popup") {
267
- const h = await b(o, async () => {
268
- const p = await this.getAccessRequestStatus(c);
269
- if (p.status >= 400) return null;
270
- const { status: g, access_request_scope: T } = p.body;
271
- return g === "approved" ? { approved: !0, accessRequestScope: T ?? void 0 } : ["denied", "failed", "expired"].includes(g) ? { approved: !1, status: g } : null;
272
- }, {
273
- intervalMs: e?.pollIntervalMs ?? P,
274
- timeoutMs: e?.pollTimeoutMs ?? x
275
- });
276
- h.approved || E(h.status ?? "unknown"), l = h.accessRequestScope;
277
- } else
278
- return localStorage.setItem(this.storageKeys.ACCESS_REQUEST_ID, c), window.location.href = o, new Promise(() => {
279
- });
280
- return e?.onProgress?.("authenticating"), this.performOAuthPkce(`openid profile email roles ${l ?? ""}`.trim());
236
+ const n = S(), o = await k(n), a = S();
237
+ localStorage.setItem(this.storageKeys.CODE_VERIFIER, n), localStorage.setItem(this.storageKeys.STATE, a);
238
+ const l = R(this.authEndpoints, {
239
+ clientId: this.authClientId,
240
+ redirectUri: r,
241
+ scope: A,
242
+ state: a,
243
+ codeChallenge: o
244
+ }), i = I(r), h = new x(this.authClientId).requestedRole(s);
245
+ e?.requested && h.requested(e.requested);
246
+ const d = await this.requestAccess(h.build()), { review_url: g } = b(d);
247
+ return e?.onProgress?.("reviewing"), window.location.href = C(g, l, i), new Promise(() => {
248
+ });
281
249
  }
282
250
  /**
283
251
  * Handle OAuth callback with authorization code
@@ -285,14 +253,14 @@ class Z {
285
253
  * @returns AuthState with login state and user info
286
254
  */
287
255
  async handleOAuthCallback(e, t) {
288
- const r = localStorage.getItem(this.storageKeys.STATE);
289
- if (!r || r !== t)
256
+ const s = localStorage.getItem(this.storageKeys.STATE);
257
+ if (!s || s !== t)
290
258
  throw new Error("Invalid state parameter - possible CSRF attack");
291
259
  await this.exchangeCodeForTokens(e), localStorage.removeItem(this.storageKeys.CODE_VERIFIER), localStorage.removeItem(this.storageKeys.STATE);
292
- const s = await this.getAuthState();
293
- if (s.status !== "authenticated")
260
+ const r = await this.getAuthState();
261
+ if (r.status !== "authenticated")
294
262
  throw new Error("Login failed");
295
- return this.setAuthState(s), s;
263
+ return this.setAuthState(r), r;
296
264
  }
297
265
  /**
298
266
  * Exchange authorization code for tokens
@@ -301,29 +269,29 @@ class Z {
301
269
  const t = localStorage.getItem(this.storageKeys.CODE_VERIFIER);
302
270
  if (!t)
303
271
  throw new Error("Code verifier not found");
304
- const r = new URLSearchParams({
272
+ const s = new URLSearchParams({
305
273
  grant_type: "authorization_code",
306
274
  client_id: this.authClientId,
307
275
  code: e,
308
276
  redirect_uri: this.config.redirectUri,
309
277
  code_verifier: t
310
- }), s = await fetch(this.authEndpoints.token, {
278
+ }), r = await fetch(this.authEndpoints.token, {
311
279
  method: "POST",
312
280
  headers: {
313
281
  "Content-Type": "application/x-www-form-urlencoded"
314
282
  },
315
- body: r
283
+ body: s
316
284
  });
317
- if (!s.ok) {
318
- const a = await s.text();
319
- throw new Error(`Token exchange failed: ${s.status} ${a}`);
285
+ if (!r.ok) {
286
+ const o = await r.text();
287
+ throw new Error(`Token exchange failed: ${r.status} ${o}`);
320
288
  }
321
- const i = await s.json();
322
- if (!i.access_token)
289
+ const n = await r.json();
290
+ if (!n.access_token)
323
291
  throw new Error("No access token received");
324
- if (localStorage.setItem(this.storageKeys.ACCESS_TOKEN, i.access_token), i.refresh_token && localStorage.setItem(this.storageKeys.REFRESH_TOKEN, i.refresh_token), i.expires_in) {
325
- const a = Date.now() + i.expires_in * 1e3;
326
- localStorage.setItem(this.storageKeys.EXPIRES_AT, a.toString());
292
+ if (localStorage.setItem(this.storageKeys.ACCESS_TOKEN, n.access_token), n.refresh_token && localStorage.setItem(this.storageKeys.REFRESH_TOKEN, n.refresh_token), n.expires_in) {
293
+ const o = Date.now() + n.expires_in * 1e3;
294
+ localStorage.setItem(this.storageKeys.EXPIRES_AT, o.toString());
327
295
  }
328
296
  }
329
297
  /**
@@ -334,7 +302,7 @@ class Z {
334
302
  const e = localStorage.getItem(this.storageKeys.REFRESH_TOKEN);
335
303
  if (e)
336
304
  try {
337
- const r = new URLSearchParams({
305
+ const s = new URLSearchParams({
338
306
  token: e,
339
307
  client_id: this.authClientId,
340
308
  token_type_hint: "refresh_token"
@@ -344,10 +312,10 @@ class Z {
344
312
  headers: {
345
313
  "Content-Type": "application/x-www-form-urlencoded"
346
314
  },
347
- body: r
315
+ body: s
348
316
  });
349
- } catch (r) {
350
- this.logger.warn("Token revocation failed:", r);
317
+ } catch (s) {
318
+ this.logger.warn("Token revocation failed:", s);
351
319
  }
352
320
  localStorage.removeItem(this.storageKeys.ACCESS_TOKEN), localStorage.removeItem(this.storageKeys.REFRESH_TOKEN), localStorage.removeItem(this.storageKeys.EXPIRES_AT), localStorage.removeItem(this.storageKeys.CODE_VERIFIER), localStorage.removeItem(this.storageKeys.STATE);
353
321
  const t = {
@@ -379,7 +347,7 @@ class Z {
379
347
  try {
380
348
  return {
381
349
  status: "authenticated",
382
- user: I(e),
350
+ user: p(e),
383
351
  accessToken: e,
384
352
  error: null,
385
353
  refreshToken: null,
@@ -407,10 +375,10 @@ class Z {
407
375
  if (!e)
408
376
  return null;
409
377
  if (t) {
410
- const r = parseInt(t, 10);
411
- if (Date.now() >= r - 5 * 1e3) {
412
- const s = localStorage.getItem(this.storageKeys.REFRESH_TOKEN);
413
- return s ? this._tryRefreshToken(s) : null;
378
+ const s = parseInt(t, 10);
379
+ if (Date.now() >= s - 5 * 1e3) {
380
+ const r = localStorage.getItem(this.storageKeys.REFRESH_TOKEN);
381
+ return r ? this._tryRefreshToken(r) : null;
414
382
  }
415
383
  }
416
384
  return e;
@@ -435,17 +403,17 @@ class Z {
435
403
  async _doRefreshToken(e) {
436
404
  this.logger.debug("Refreshing access token");
437
405
  try {
438
- const t = await B(
406
+ const t = await q(
439
407
  this.authEndpoints.token,
440
408
  e,
441
409
  this.authClientId
442
410
  );
443
411
  if (t.success) {
444
412
  this._storeRefreshedTokens(t.tokens);
445
- const r = I(t.tokens.access_token);
413
+ const s = p(t.tokens.access_token);
446
414
  return this.setAuthState({
447
415
  status: "authenticated",
448
- user: r,
416
+ user: s,
449
417
  accessToken: t.tokens.access_token,
450
418
  error: null,
451
419
  refreshToken: null,
@@ -466,7 +434,7 @@ class Z {
466
434
  } catch (t) {
467
435
  this.logger.warn("Token refresh failed:", t);
468
436
  }
469
- throw this.logger.warn("Token refresh failed, keeping tokens for manual retry"), y(
437
+ throw this.logger.warn("Token refresh failed, keeping tokens for manual retry"), E(
470
438
  "auth_error",
471
439
  "Access token expired and unable to refresh. Try logging out and logging in again."
472
440
  );
@@ -495,86 +463,86 @@ class Z {
495
463
  try {
496
464
  const e = await this.sendApiRequest("GET", "/bodhi/v1/info");
497
465
  if (e.status >= 400)
498
- return m;
499
- const t = e.body, r = t.version || "unknown";
466
+ return w;
467
+ const t = e.body, s = t.version || "unknown";
500
468
  switch (t.status) {
501
469
  case "ready":
502
470
  return {
503
471
  status: "ready",
504
- version: r,
472
+ version: s,
505
473
  error: null,
506
474
  deployment: t.deployment ?? null,
507
475
  client_id: t.client_id ?? null
508
476
  };
509
477
  case "setup":
510
- return R(
478
+ return m(
511
479
  "setup",
512
- r,
480
+ s,
513
481
  void 0,
514
482
  t.deployment,
515
483
  t.client_id
516
484
  );
517
485
  case "resource_admin":
518
- return R(
486
+ return m(
519
487
  "resource_admin",
520
- r,
488
+ s,
521
489
  void 0,
522
490
  t.deployment,
523
491
  t.client_id
524
492
  );
525
493
  case "error":
526
- return R(
494
+ return m(
527
495
  "error",
528
- r,
529
- t.error ? { message: t.error.message, type: t.error.type } : F.SERVER_NOT_READY,
496
+ s,
497
+ t.error ? { message: t.error.message, type: t.error.type } : L.SERVER_NOT_READY,
530
498
  t.deployment,
531
499
  t.client_id
532
500
  );
533
501
  default:
534
- return m;
502
+ return w;
535
503
  }
536
504
  } catch {
537
- return m;
505
+ return w;
538
506
  }
539
507
  }
540
508
  /**
541
509
  * Generic streaming via window.bodhiext.sendStreamRequest
542
510
  * Wraps ReadableStream as AsyncGenerator
543
511
  */
544
- async *stream(e, t, r, s, i = !0) {
512
+ async *stream(e, t, s, r, n = !0) {
545
513
  this.ensureBodhiext();
546
- let a = s || {};
547
- if (i) {
548
- const o = await this._getAccessTokenRaw();
549
- if (!o)
550
- throw y("auth_error", "Not authenticated. Please log in first.");
551
- a = {
552
- ...a,
553
- Authorization: `Bearer ${o}`
514
+ let o = r || {};
515
+ if (n) {
516
+ const i = await this._getAccessTokenRaw();
517
+ if (!i)
518
+ throw E("auth_error", "Not authenticated. Please log in first.");
519
+ o = {
520
+ ...o,
521
+ Authorization: `Bearer ${i}`
554
522
  };
555
523
  }
556
- const c = this.bodhiext.sendStreamRequest(e, t, r, a).getReader();
524
+ const l = this.bodhiext.sendStreamRequest(e, t, s, o).getReader();
557
525
  try {
558
526
  for (; ; ) {
559
- const { value: o, done: l } = await c.read();
560
- if (l || o?.done)
527
+ const { value: i, done: h } = await l.read();
528
+ if (h || i?.done)
561
529
  break;
562
- yield o.body;
530
+ yield i.body;
563
531
  }
564
- } catch (o) {
565
- if (o instanceof w || o instanceof u) throw o;
566
- if (o instanceof Error) {
567
- const l = o;
568
- throw o.name === "BodhiApiError" && typeof l.status == "number" && l.body != null ? new w(
569
- l.status,
570
- l.body,
571
- o.message,
572
- l.headers
573
- ) : o.name === "BodhiError" && typeof l.code == "string" ? new u(l.code, o.message) : new u("extension_error", o.message);
532
+ } catch (i) {
533
+ if (i instanceof f || i instanceof c) throw i;
534
+ if (i instanceof Error) {
535
+ const h = i;
536
+ throw i.name === "BodhiApiError" && typeof h.status == "number" && h.body != null ? new f(
537
+ h.status,
538
+ h.body,
539
+ i.message,
540
+ h.headers
541
+ ) : i.name === "BodhiError" && typeof h.code == "string" ? new c(h.code, i.message) : new c("extension_error", i.message);
574
542
  }
575
- throw o;
543
+ throw i;
576
544
  } finally {
577
- c.releaseLock();
545
+ l.releaseLock();
578
546
  }
579
547
  }
580
548
  /**
@@ -582,49 +550,49 @@ class Z {
582
550
  * Returns status, headers, and async generator of raw text chunks.
583
551
  * No SSE/JSON parsing. Non-2xx responses are returned as data (not thrown).
584
552
  */
585
- async streamText(e, t, r, s, i = !0) {
553
+ async streamText(e, t, s, r, n = !0) {
586
554
  this.ensureBodhiext();
587
- let a = { ...s };
588
- if (i) {
589
- const o = await this._getAccessTokenRaw();
590
- o && (a = {
591
- ...a,
592
- Authorization: `Bearer ${o}`
555
+ let o = { ...r };
556
+ if (n) {
557
+ const i = await this._getAccessTokenRaw();
558
+ i && (o = {
559
+ ...o,
560
+ Authorization: `Bearer ${i}`
593
561
  });
594
562
  }
595
- const n = await this.bodhiext.sendStreamText(e, t, r, a);
596
- async function* c(o) {
597
- const l = o.getReader();
563
+ const a = await this.bodhiext.sendStreamText(e, t, s, o);
564
+ async function* l(i) {
565
+ const h = i.getReader();
598
566
  try {
599
567
  for (; ; ) {
600
- const { done: d, value: h } = await l.read();
568
+ const { done: d, value: g } = await h.read();
601
569
  if (d) break;
602
- yield h;
570
+ yield g;
603
571
  }
604
572
  } finally {
605
- l.releaseLock();
573
+ h.releaseLock();
606
574
  }
607
575
  }
608
576
  return {
609
- status: n.status,
610
- headers: n.headers,
611
- body: c(n.body)
577
+ status: a.status,
578
+ headers: a.headers,
579
+ body: l(a.body)
612
580
  };
613
581
  }
614
582
  // ============================================================================
615
583
  // OpenAI-Compatible Namespaced API
616
584
  // ============================================================================
617
585
  get chat() {
618
- return this._chat ??= new $(this);
586
+ return this._chat ??= new D(this);
619
587
  }
620
588
  get models() {
621
- return this._models ??= new z(this);
589
+ return this._models ??= new M(this);
622
590
  }
623
591
  get embeddings() {
624
- return this._embeddings ??= new V(this);
592
+ return this._embeddings ??= new F(this);
625
593
  }
626
594
  get mcps() {
627
- return this._mcps ??= new W(this);
595
+ return this._mcps ??= new z(this);
628
596
  }
629
597
  // ============================================================================
630
598
  // Access Request Methods
@@ -638,43 +606,6 @@ class Z {
638
606
  !1
639
607
  );
640
608
  }
641
- async getAccessRequestStatus(e) {
642
- return this.sendApiRequest(
643
- "GET",
644
- `/bodhi/v1/apps/access-requests/${e}?app_client_id=${encodeURIComponent(this.authClientId)}`,
645
- void 0,
646
- {},
647
- !1
648
- );
649
- }
650
- async pollAccessRequestStatus(e, t) {
651
- return H(
652
- (r) => this.getAccessRequestStatus(r),
653
- e,
654
- t
655
- );
656
- }
657
- async performOAuthPkce(e) {
658
- const t = _(), r = await U(t), s = _();
659
- localStorage.setItem(this.storageKeys.CODE_VERIFIER, t), localStorage.setItem(this.storageKeys.STATE, s);
660
- const i = e.split(" ").filter(Boolean), a = new URLSearchParams({
661
- response_type: "code",
662
- client_id: this.authClientId,
663
- redirect_uri: this.config.redirectUri,
664
- scope: i.join(" "),
665
- state: s,
666
- code_challenge: r,
667
- code_challenge_method: "S256"
668
- });
669
- return window.location.href = `${this.authEndpoints.authorize}?${a}`, new Promise(() => {
670
- });
671
- }
672
- async handleAccessRequestCallback(e) {
673
- const t = await this.getAccessRequestStatus(e), { status: r, access_request_scope: s } = S(t);
674
- localStorage.removeItem(this.storageKeys.ACCESS_REQUEST_ID), r !== "approved" && E(r);
675
- const i = `openid profile email roles ${s ?? ""}`.trim();
676
- return this.performOAuthPkce(i);
677
- }
678
609
  /**
679
610
  * Serialize web extension client state (all transient, nothing to persist)
680
611
  */
@@ -698,34 +629,34 @@ class Z {
698
629
  };
699
630
  }
700
631
  }
701
- function ee(f) {
632
+ function Y(u) {
702
633
  if (typeof window > "u")
703
634
  throw new Error("redirectUri required in non-browser environment");
704
- const e = f === "/" ? "" : f.replace(/\/$/, "");
635
+ const e = u === "/" ? "" : u.replace(/\/$/, "");
705
636
  return `${window.location.origin}${e}/callback`;
706
637
  }
707
- class se extends X {
708
- constructor(e, t, r) {
709
- const s = t || {}, i = {
710
- basePath: s.basePath || "/",
711
- redirectUri: s.redirectUri || ee(s.basePath || "/"),
712
- authServerUrl: s.authServerUrl || "https://id.getbodhi.app/realms/bodhi",
713
- logLevel: s.logLevel || "warn",
714
- apiTimeoutMs: s.apiTimeoutMs,
715
- storage: s.storage,
716
- initialTokens: s.initialTokens,
717
- initParams: s.initParams
638
+ class Z extends V {
639
+ constructor(e, t, s) {
640
+ const r = t || {}, n = {
641
+ basePath: r.basePath || "/",
642
+ redirectUri: r.redirectUri || Y(r.basePath || "/"),
643
+ authServerUrl: r.authServerUrl || "https://id.getbodhi.app/realms/bodhi",
644
+ logLevel: r.logLevel || "warn",
645
+ apiTimeoutMs: r.apiTimeoutMs,
646
+ storage: r.storage,
647
+ initialTokens: r.initialTokens,
648
+ initParams: r.initParams
718
649
  };
719
- super(e, i, r);
650
+ super(e, n, s);
720
651
  }
721
652
  createLogger(e) {
722
- return new q("WebUIClient", e.logLevel);
653
+ return new v("WebUIClient", e.logLevel);
723
654
  }
724
655
  createStoragePrefix(e) {
725
- return A(e.basePath, k.WEB);
656
+ return T(e.basePath, y.WEB);
726
657
  }
727
658
  createExtClient(e, t) {
728
- return new Z(
659
+ return new j(
729
660
  this.authClientId,
730
661
  {
731
662
  authServerUrl: e.authServerUrl,
@@ -738,8 +669,8 @@ class se extends X {
738
669
  t
739
670
  );
740
671
  }
741
- createDirectClient(e, t, r) {
742
- return new j(
672
+ createDirectClient(e, t, s) {
673
+ return new $(
743
674
  {
744
675
  authClientId: e,
745
676
  authServerUrl: t.authServerUrl,
@@ -750,7 +681,7 @@ class se extends X {
750
681
  storage: t.storage,
751
682
  initialTokens: t.initialTokens
752
683
  },
753
- r
684
+ s
754
685
  );
755
686
  }
756
687
  // ============================================================================
@@ -759,15 +690,12 @@ class se extends X {
759
690
  async handleOAuthCallback(e, t) {
760
691
  return this.connectionMode === "direct" ? this.directClient.handleOAuthCallback(e, t) : this.extClient.handleOAuthCallback(e, t);
761
692
  }
762
- async handleAccessRequestCallback(e) {
763
- return this.connectionMode === "direct" ? this.directClient.handleAccessRequestCallback(e) : this.extClient.handleAccessRequestCallback(e);
764
- }
765
693
  }
766
- const re = "production";
694
+ const Q = "production";
767
695
  export {
768
- j as DirectWebClient,
769
- ae as InMemoryStorage,
770
- G as LocalStorageAdapter,
771
- re as WEB_BUILD_MODE,
772
- se as WebUIClient
696
+ $ as DirectWebClient,
697
+ re as InMemoryStorage,
698
+ W as LocalStorageAdapter,
699
+ Q as WEB_BUILD_MODE,
700
+ Z as WebUIClient
773
701
  };
@@ -19,8 +19,6 @@ export declare class DirectWebClient extends DirectClientBase {
19
19
  private redirectUri;
20
20
  constructor(config: DirectWebClientConfig, onStateChange?: StateChangeCallback);
21
21
  login(options?: LoginOptions): Promise<AuthState>;
22
- protected performOAuthPkce(scope: string): Promise<AuthState>;
23
22
  handleOAuthCallback(code: string, state: string): Promise<AuthState>;
24
- handleAccessRequestCallback(requestId: string): Promise<AuthState>;
25
23
  protected _getRedirectUri(): string;
26
24
  }
@@ -1,4 +1,4 @@
1
- import { AccessRequestStatusResponse, CreateAccessRequest, CreateAccessRequestResponse, PingResponse } from '@bodhiapp/ts-client';
1
+ import { CreateAccessRequest, CreateAccessRequestResponse, PingResponse } from '@bodhiapp/ts-client';
2
2
  import { Chat, Models, Embeddings, Mcps, AuthState, BackendServerState, ClientState, ExtensionState, IExtensionClient, InitParams, LoginOptions, LogLevel, StateChangeCallback, StreamTextResult } from '@bodhiapp/bodhi-js-core';
3
3
  import { ApiResponse } from '@bodhiapp/bodhi-browser-types';
4
4
  export type SerializedWebExtensionState = {
@@ -155,13 +155,6 @@ export declare class WindowBodhiextClient implements IExtensionClient {
155
155
  get embeddings(): Embeddings;
156
156
  get mcps(): Mcps;
157
157
  requestAccess(body: CreateAccessRequest): Promise<ApiResponse<CreateAccessRequestResponse>>;
158
- getAccessRequestStatus(requestId: string): Promise<ApiResponse<AccessRequestStatusResponse>>;
159
- pollAccessRequestStatus(requestId: string, options?: {
160
- intervalMs?: number;
161
- timeoutMs?: number;
162
- }): Promise<AccessRequestStatusResponse>;
163
- private performOAuthPkce;
164
- handleAccessRequestCallback(requestId: string): Promise<AuthState>;
165
158
  /**
166
159
  * Serialize web extension client state (all transient, nothing to persist)
167
160
  */
@@ -52,5 +52,4 @@ export declare class WebUIClient extends BaseFacadeClient<WebClientConfig, Windo
52
52
  protected createExtClient(config: WebClientConfig, onStateChange: (change: StateChange) => void): WindowBodhiextClient;
53
53
  protected createDirectClient(authClientId: string, config: WebClientConfig, onStateChange: (change: StateChange) => void): DirectWebClient;
54
54
  handleOAuthCallback(code: string, state: string): Promise<AuthState>;
55
- handleAccessRequestCallback(requestId: string): Promise<AuthState>;
56
55
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bodhiapp/bodhi-js",
3
- "version": "0.0.39",
3
+ "version": "0.0.41",
4
4
  "description": "Web SDK for Bodhi Browser - window.bodhiext communication",
5
5
  "type": "module",
6
6
  "main": "dist/bodhi-web.cjs.js",
@@ -37,9 +37,9 @@
37
37
  "typecheck": "tsc --noEmit"
38
38
  },
39
39
  "dependencies": {
40
- "@bodhiapp/bodhi-browser-types": "0.0.39",
41
- "@bodhiapp/bodhi-js-core": "0.0.39",
42
- "@bodhiapp/ts-client": "0.1.32"
40
+ "@bodhiapp/bodhi-browser-types": "0.0.41",
41
+ "@bodhiapp/bodhi-js-core": "0.0.41",
42
+ "@bodhiapp/ts-client": "0.1.36"
43
43
  },
44
44
  "devDependencies": {
45
45
  "@eslint/js": "^9.23.0",