UNPKG

@roo-code/cloud

Version:

SDK for integrating with Roo Code Cloud

1 lines 50.4 kB
import{z as t}from"zod";import{globalSettingsSchema as s,discriminatedProviderSettingsWithIdSchema as e,mcpMarketplaceItemSchema as i,toolUsageSchema as n,tokenUsageSchema as a,TelemetryEventName as r,rooCodeTelemetryEventSchema as o,RooCodeEventName as h}from"@roo-code/types";import c from"events";import d from"crypto";import{io as l}from"socket.io-client";var u=(t=>"undefined"!=typeof require?require:"undefined"!=typeof Proxy?new Proxy(t,{get:(t,s)=>("undefined"!=typeof require?require:t)[s]}):t)(function(t){if("undefined"!=typeof require)return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')}),p=t.object({allowAll:t.boolean(),providers:t.record(t.object({allowAll:t.boolean(),models:t.array(t.string()).optional()}))}),g=s.pick({enableCheckpoints:!0,fuzzyMatchThreshold:!0,maxOpenTabsContext:!0,maxReadFileLine:!0,maxWorkspaceFiles:!0,showRooIgnoredFiles:!0,terminalCommandDelay:!0,terminalCompressProgressBar:!0,terminalOutputLineLimit:!0,terminalShellIntegrationDisabled:!0,terminalShellIntegrationTimeout:!0,terminalZshClearEolMark:!0}).merge(t.object({maxOpenTabsContext:t.number().int().nonnegative().optional(),maxReadFileLine:t.number().int().gte(-1).optional(),maxWorkspaceFiles:t.number().int().nonnegative().optional(),terminalCommandDelay:t.number().int().nonnegative().optional(),terminalOutputLineLimit:t.number().int().nonnegative().optional(),terminalShellIntegrationTimeout:t.number().int().nonnegative().optional()})),y=t.object({recordTaskMessages:t.boolean().optional(),enableTaskSharing:t.boolean().optional(),taskShareExpirationDays:t.number().int().positive().optional(),allowMembersViewAllTasks:t.boolean().optional()}),m=t.object({version:t.number(),cloudSettings:y.optional(),defaultSettings:g,allowList:p,hiddenMcps:t.array(t.string()).optional(),hideMarketplaceMcps:t.boolean().optional(),mcps:t.array(i).optional(),providerProfiles:t.record(t.string(),e).optional()}),k={allowAll:!0,providers:{}},w={version:0,cloudSettings:{recordTaskMessages:!0,enableTaskSharing:!0,taskShareExpirationDays:30,allowMembersViewAllTasks:!0},defaultSettings:{},allowList:k},f=t.object({success:t.boolean(),shareUrl:t.string().optional(),error:t.string().optional(),isNewShare:t.boolean().optional(),manageUrl:t.string().optional()}),S=(t=>(t.DISCONNECTED="disconnected",t.CONNECTING="connecting",t.CONNECTED="connected",t.RETRYING="retrying",t.FAILED="failed",t))(S||{}),I=2e4,v=60,b=(t=>(t.Extension="bridge:extension",t.Task="bridge:task",t))(b||{}),T=(t=>(t.InstanceId="instanceId",t.UserId="userId",t.WorkspacePath="workspacePath",t.ExtensionVersion="extensionVersion",t.LastHeartbeat="lastHeartbeat",t.TaskId="taskId",t.TaskStatus="taskStatus",t))(T||{}),C=(t=>(t.Running="running",t.Idle="idle",t.None="none",t))(C||{}),_=t.object({instanceId:t.string(),userId:t.string(),workspacePath:t.string(),extensionVersion:t.string(),lastHeartbeat:t.coerce.number(),taskId:t.string(),taskStatus:t.nativeEnum(C)}),$=(t=>(t.Control="control",t.Events="events",t.Instances="instances",t.Instance="instance",t))($||{}),E=(t=>(t.TaskCreated="task_created",t.TaskStarted="task_started",t.TaskCompleted="task_completed",t.TaskAborted="task_aborted",t.TaskFocused="task_focused",t.TaskUnfocused="task_unfocused",t.TaskActive="task_active",t.TaskIdle="task_idle",t.InstanceRegistered="instance_registered",t.InstanceUnregistered="instance_unregistered",t.HeartbeatUpdated="heartbeat_updated",t))(E||{}),A=t.discriminatedUnion("type",[t.object({type:t.literal("task_created"),instanceId:t.string(),payload:t.object({taskId:t.string(),taskStatus:t.nativeEnum(C)}),timestamp:t.number()}),t.object({type:t.literal("task_started"),instanceId:t.string(),payload:t.object({taskId:t.string(),taskStatus:t.nativeEnum(C)}),timestamp:t.number()}),t.object({type:t.literal("task_completed"),instanceId:t.string(),payload:t.object({taskId:t.string(),taskStatus:t.nativeEnum(C),tokenUsage:a,toolUsage:n}),timestamp:t.number()}),t.object({type:t.literal("task_aborted"),instanceId:t.string(),payload:t.object({taskId:t.string(),taskStatus:t.nativeEnum(C)}),timestamp:t.number()}),t.object({type:t.literal("task_focused"),instanceId:t.string(),payload:t.object({taskId:t.string(),taskStatus:t.nativeEnum(C)}),timestamp:t.number()}),t.object({type:t.literal("task_unfocused"),instanceId:t.string(),payload:t.object({taskId:t.string(),taskStatus:t.nativeEnum(C)}),timestamp:t.number()}),t.object({type:t.literal("task_active"),instanceId:t.string(),payload:t.object({taskId:t.string(),taskStatus:t.nativeEnum(C)}),timestamp:t.number()}),t.object({type:t.literal("task_idle"),instanceId:t.string(),payload:t.object({taskId:t.string(),taskStatus:t.nativeEnum(C)}),timestamp:t.number()}),t.object({type:t.literal("instance_registered"),instanceId:t.string(),payload:t.object({instance:_}),timestamp:t.number()}),t.object({type:t.literal("instance_unregistered"),instanceId:t.string(),payload:t.object({instanceId:t.string()}),timestamp:t.number()}),t.object({type:t.literal("heartbeat_updated"),instanceId:t.string(),payload:t.object({instance:_}),timestamp:t.number()})]),x=(t=>(t.StartTask="start_task",t.StopTask="stop_task",t))(x||{}),z=t.discriminatedUnion("type",[t.object({type:t.literal("start_task"),instanceId:t.string(),payload:t.object({text:t.string(),images:t.array(t.string()).optional()}),timestamp:t.number()}),t.object({type:t.literal("stop_task"),instanceId:t.string(),payload:t.object({taskId:t.string()}),timestamp:t.number()})]),O=(t=>(t.Control="control",t.Events="events",t))(O||{}),R=(t=>(t.TaskStarted="task_started",t.TaskCompleted="task_completed",t.TaskAborted="task_aborted",t.TaskFocused="task_focused",t.TaskUnfocused="task_unfocused",t.TaskActive="task_active",t.TaskIdle="task_idle",t))(R||{}),M=t.discriminatedUnion("type",[t.object({type:t.literal("task_started"),payload:t.object({taskId:t.string(),taskStatus:t.nativeEnum(C)}),timestamp:t.number()}),t.object({type:t.literal("task_completed"),payload:t.object({taskId:t.string(),taskStatus:t.nativeEnum(C),tokenUsage:a,toolUsage:n}),timestamp:t.number()}),t.object({type:t.literal("task_aborted"),payload:t.object({taskId:t.string(),taskStatus:t.nativeEnum(C)}),timestamp:t.number()}),t.object({type:t.literal("task_focused"),payload:t.object({taskId:t.string(),taskStatus:t.nativeEnum(C)}),timestamp:t.number()}),t.object({type:t.literal("task_unfocused"),payload:t.object({taskId:t.string(),taskStatus:t.nativeEnum(C)}),timestamp:t.number()}),t.object({type:t.literal("task_active"),payload:t.object({taskId:t.string(),taskStatus:t.nativeEnum(C)}),timestamp:t.number()}),t.object({type:t.literal("task_idle"),payload:t.object({taskId:t.string(),taskStatus:t.nativeEnum(C)}),timestamp:t.number()})]),U=(t=>(t.Message="message",t))(U||{}),D=t.discriminatedUnion("type",[t.object({type:t.literal("message"),taskId:t.string(),payload:t.object({text:t.string(),images:t.array(t.string()).optional()}),timestamp:t.number()})]),P="https://clerk.roocode.com",L="https://app.roocode.com",B=()=>process.env.CLERK_BASE_URL||P,N=()=>process.env.ROO_CODE_API_URL||L;function F(t){return`Roo-Code ${t?.extension?.packageJSON?.version||"unknown"}`}var q,j=class t extends Error{constructor(s,e,i){super(s),this.statusCode=e,this.responseBody=i,this.name="CloudAPIError",Object.setPrototypeOf(this,t.prototype)}},H=class t extends j{constructor(s){super(s?`Task '${s}' not found`:"Task not found",404),this.name="TaskNotFoundError",Object.setPrototypeOf(this,t.prototype)}},V=class t extends j{constructor(s="Authentication required"){super(s,401),this.name="AuthenticationError",Object.setPrototypeOf(this,t.prototype)}},J=class t extends j{constructor(s="Network error occurred"){super(s),this.name="NetworkError",Object.setPrototypeOf(this,t.prototype)}},W=class t extends Error{constructor(){super("Invalid/Expired client token"),Object.setPrototypeOf(this,t.prototype)}},G=class{authService;log;baseUrl;constructor(t,s){this.authService=t,this.log=s||console.log,this.baseUrl=N()}async request(t,s={}){const{timeout:e=3e4,parseResponse:i,headers:n={},...a}=s,r=this.authService.getSessionToken();if(!r)throw new V;const o=`${this.baseUrl}${t}`,h={"Content-Type":"application/json",Authorization:`Bearer ${r}`,"User-Agent":F(),...n};try{const s=await fetch(o,{...a,headers:h,signal:AbortSignal.timeout(e)});s.ok||await this.handleErrorResponse(s,t);const n=await s.json();return i?i(n):n}catch(s){if(s instanceof TypeError&&s.message.includes("fetch"))throw new J(`Network error while calling ${t}`);if(s instanceof j)throw s;if(s instanceof Error&&"AbortError"===s.name)throw new j(`Request to ${t} timed out`,void 0,void 0);throw new j(`Unexpected error while calling ${t}: ${s instanceof Error?s.message:String(s)}`)}}async handleErrorResponse(t,s){let e;try{e=await t.json()}catch{e=await t.text()}switch(t.status){case 401:throw new V;case 404:if(s.includes("/share"))throw new H;throw new j(`Resource not found: ${s}`,404,e);default:throw new j(`HTTP ${t.status}: ${t.statusText}`,t.status,e)}}async shareTask(t,s="organization"){this.log(`[CloudAPI] Sharing task ${t} with visibility: ${s}`);const e=await this.request("/api/extension/share",{method:"POST",body:JSON.stringify({taskId:t,visibility:s}),parseResponse:t=>f.parse(t)});return this.log("[CloudAPI] Share response:",e),e}async bridgeConfig(){return this.request("/api/extension/bridge/config",{method:"GET",parseResponse:s=>t.object({userId:t.string(),socketBridgeUrl:t.string(),token:t.string()}).parse(s)})}};async function X(){if(q)return q;try{if("undefined"!=typeof globalThis&&"acquireVsCodeApi"in globalThis)return;if(void 0!==u)try{if(q=u("vscode"))return q}catch(t){}return q=await import("vscode")}catch(t){}}var Y=class{callback;successInterval;initialBackoffMs;maxBackoffMs;currentBackoffMs;attemptCount;timerId;isRunning;constructor(t){this.callback=t.callback,this.successInterval=t.successInterval??5e4,this.initialBackoffMs=t.initialBackoffMs??1e3,this.maxBackoffMs=t.maxBackoffMs??3e5,this.currentBackoffMs=this.initialBackoffMs,this.attemptCount=0,this.timerId=null,this.isRunning=!1}start(){this.isRunning||(this.isRunning=!0,this.executeCallback())}stop(){this.isRunning&&(this.timerId&&(clearTimeout(this.timerId),this.timerId=null),this.isRunning=!1)}reset(){this.currentBackoffMs=this.initialBackoffMs,this.attemptCount=0}scheduleNextAttempt(t){this.isRunning&&(t?(this.currentBackoffMs=this.initialBackoffMs,this.attemptCount=0,this.timerId=setTimeout(()=>this.executeCallback(),this.successInterval)):(this.attemptCount++,this.currentBackoffMs=Math.min(this.initialBackoffMs*Math.pow(2,this.attemptCount-1),this.maxBackoffMs),this.timerId=setTimeout(()=>this.executeCallback(),this.currentBackoffMs)))}async executeCallback(){if(this.isRunning)try{const t=await this.callback();this.scheduleNextAttempt(t)}catch(t){this.scheduleNextAttempt(!1)}}},K="clerk-auth-state",Z=t.object({clientToken:t.string().min(1,"Client token cannot be empty"),sessionId:t.string().min(1,"Session ID cannot be empty"),organizationId:t.string().nullable().optional()}),Q=t.object({response:t.object({created_session_id:t.string()})}),tt=t.object({jwt:t.string()}),st=t.object({response:t.object({id:t.string().optional(),first_name:t.string().nullish(),last_name:t.string().nullish(),image_url:t.string().optional(),primary_email_address_id:t.string().optional(),email_addresses:t.array(t.object({id:t.string(),email_address:t.string()})).optional(),public_metadata:t.record(t.any()).optional()})}),et=t.object({response:t.array(t.object({id:t.string(),role:t.string(),permissions:t.array(t.string()).optional(),created_at:t.number().optional(),updated_at:t.number().optional(),organization:t.object({id:t.string(),name:t.string(),slug:t.string().optional(),image_url:t.string().optional(),has_image:t.boolean().optional(),created_at:t.number().optional(),updated_at:t.number().optional()})}))}),it=class extends c{context;timer;state="initializing";log;authCredentialsKey;credentials=null;sessionToken=null;userInfo=null;isFirstRefreshAttempt=!1;constructor(t,s){super(),this.context=t,this.log=s||console.log;const e=B();this.authCredentialsKey=e!==P?`clerk-auth-credentials-${e}`:"clerk-auth-credentials",this.timer=new Y({callback:async()=>(await this.refreshSession(),!0),successInterval:5e4,initialBackoffMs:1e3,maxBackoffMs:3e5})}changeState(t){const s=this.state;this.state=t,this.emit("auth-state-changed",{state:t,previousState:s})}async handleCredentialsChange(){try{const t=await this.loadCredentials();t?null!==this.credentials&&this.credentials.clientToken===t.clientToken&&this.credentials.sessionId===t.sessionId||this.transitionToAttemptingSession(t):"logged-out"!==this.state&&this.transitionToLoggedOut()}catch(t){this.log("[auth] Error handling credentials change:",t)}}transitionToLoggedOut(){this.timer.stop(),this.credentials=null,this.sessionToken=null,this.userInfo=null,this.changeState("logged-out"),this.log("[auth] Transitioned to logged-out state")}transitionToAttemptingSession(t){this.credentials=t,this.sessionToken=null,this.userInfo=null,this.isFirstRefreshAttempt=!0,this.changeState("attempting-session"),this.timer.start(),this.log("[auth] Transitioned to attempting-session state")}transitionToInactiveSession(){this.sessionToken=null,this.userInfo=null,this.changeState("inactive-session"),this.log("[auth] Transitioned to inactive-session state")}async initialize(){"initializing"===this.state?(await this.handleCredentialsChange(),this.context.subscriptions.push(this.context.secrets.onDidChange(t=>{t.key===this.authCredentialsKey&&this.handleCredentialsChange()}))):this.log("[auth] initialize() called after already initialized")}async storeCredentials(t){await this.context.secrets.store(this.authCredentialsKey,JSON.stringify(t))}async loadCredentials(){const s=await this.context.secrets.get(this.authCredentialsKey);if(!s)return null;try{const t=JSON.parse(s),e=Z.parse(t);return void 0===e.organizationId&&this.userInfo?.organizationId&&(e.organizationId=this.userInfo.organizationId,await this.storeCredentials(e),this.log("[auth] Migrated credentials with organizationId")),e}catch(s){return s instanceof t.ZodError?this.log("[auth] Invalid credentials format:",s.errors):this.log("[auth] Failed to parse stored credentials:",s),null}}async clearCredentials(){await this.context.secrets.delete(this.authCredentialsKey)}async login(){try{const t=await X();if(!t)throw new Error("VS Code API not available");const s=d.randomBytes(16).toString("hex");await this.context.globalState.update(K,s);const e=this.context.extension?.packageJSON,i=e?.publisher??"RooVeterinaryInc",n=e?.name??"roo-cline",a=new URLSearchParams({state:s,auth_redirect:`${t.env.uriScheme}://${i}.${n}`}),r=`${N()}/extension/sign-in?${a.toString()}`;await t.env.openExternal(t.Uri.parse(r))}catch(t){throw this.log(`[auth] Error initiating Roo Code Cloud auth: ${t}`),new Error(`Failed to initiate Roo Code Cloud authentication: ${t}`)}}async handleCallback(t,s,e){if(!t||!s){const t=await X();return void(t&&t.window.showInformationMessage("Invalid Roo Code Cloud sign in url"))}try{if(s!==this.context.globalState.get(K))throw this.log("[auth] State mismatch in callback"),new Error("Invalid state parameter. Authentication request may have been tampered with.");const i=await this.clerkSignIn(t);i.organizationId=e||null,await this.storeCredentials(i);const n=await X();n&&n.window.showInformationMessage("Successfully authenticated with Roo Code Cloud"),this.log("[auth] Successfully authenticated with Roo Code Cloud")}catch(t){throw this.log(`[auth] Error handling Roo Code Cloud callback: ${t}`),this.changeState("logged-out"),new Error(`Failed to handle Roo Code Cloud callback: ${t}`)}}async logout(){const t=this.credentials;try{if(await this.clearCredentials(),await this.context.globalState.update(K,void 0),t)try{await this.clerkLogout(t)}catch(t){this.log("[auth] Error calling clerkLogout:",t)}const s=await X();s&&s.window.showInformationMessage("Logged out from Roo Code Cloud"),this.log("[auth] Logged out from Roo Code Cloud")}catch(t){throw this.log(`[auth] Error logging out from Roo Code Cloud: ${t}`),new Error(`Failed to log out from Roo Code Cloud: ${t}`)}}getState(){return this.state}getSessionToken(){if("active-session"===this.state&&this.sessionToken)return this.sessionToken}isAuthenticated(){return"active-session"===this.state||"attempting-session"===this.state||"inactive-session"===this.state}hasActiveSession(){return"active-session"===this.state}hasOrIsAcquiringActiveSession(){return"active-session"===this.state||"attempting-session"===this.state}async refreshSession(){if(this.credentials)try{const t=this.state;this.sessionToken=await this.clerkCreateSessionToken(),"active-session"!==t?(this.changeState("active-session"),this.log("[auth] Transitioned to active-session state"),this.fetchUserInfo()):this.state="active-session"}catch(t){throw t instanceof W?(this.log("[auth] Invalid/Expired client token: clearing credentials"),this.clearCredentials()):this.isFirstRefreshAttempt&&"attempting-session"===this.state&&(this.isFirstRefreshAttempt=!1,this.transitionToInactiveSession()),this.log("[auth] Failed to refresh session",t),t}else this.log("[auth] Cannot refresh session: missing credentials")}async fetchUserInfo(){this.credentials&&(this.userInfo=await this.clerkMe(),this.emit("user-info",{userInfo:this.userInfo}))}getUserInfo(){return this.userInfo}getStoredOrganizationId(){return this.credentials?.organizationId||null}async clerkSignIn(t){const s=new URLSearchParams;s.append("strategy","ticket"),s.append("ticket",t);const e=await fetch(`${B()}/v1/client/sign_ins`,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded","User-Agent":this.userAgent()},body:s.toString(),signal:AbortSignal.timeout(1e4)});if(!e.ok)throw new Error(`HTTP ${e.status}: ${e.statusText}`);const{response:{created_session_id:i}}=Q.parse(await e.json()),n=e.headers.get("authorization");if(!n)throw new Error("No authorization header found in the response");return Z.parse({clientToken:n,sessionId:i})}async clerkCreateSessionToken(){const t=new URLSearchParams;t.append("_is_native","1");const s=this.getStoredOrganizationId();void 0!==this.credentials?.organizationId&&t.append("organization_id",s||"");const e=await fetch(`${B()}/v1/client/sessions/${this.credentials.sessionId}/tokens`,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Authorization:`Bearer ${this.credentials.clientToken}`,"User-Agent":this.userAgent()},body:t.toString(),signal:AbortSignal.timeout(1e4)});if(401===e.status||404===e.status)throw new W;if(!e.ok)throw new Error(`HTTP ${e.status}: ${e.statusText}`);return tt.parse(await e.json()).jwt}async clerkMe(){const t=await fetch(`${B()}/v1/me`,{headers:{Authorization:`Bearer ${this.credentials.clientToken}`,"User-Agent":this.userAgent()},signal:AbortSignal.timeout(1e4)});if(!t.ok)throw new Error(`HTTP ${t.status}: ${t.statusText}`);const s=await t.json(),{response:e}=st.parse(s),i={id:e.id,picture:e.image_url},n=[e.first_name,e.last_name].filter(t=>!!t);i.name=n.length>0?n.join(" "):void 0;const a=e.primary_email_address_id,r=e.email_addresses;a&&r&&(i.email=r.find(t=>a===t.id)?.email_address);let o=!1;!0===e.public_metadata?.extension_bridge_enabled&&(o=!0);try{const t=this.getStoredOrganizationId();if(void 0!==this.credentials?.organizationId)if(null!==t){const s=await this.clerkGetOrganizationMemberships(),e=this.findOrganizationMembership(s,t);e?(this.setUserOrganizationInfo(i,e),await this.isExtensionBridgeEnabledForOrganization(t)&&(o=!0),this.log("[auth] User in organization context:",{id:e.organization.id,name:e.organization.name,role:e.role})):this.log("[auth] Warning: User not found in stored organization:",t)}else this.log("[auth] User in personal account context - not setting organization info");else{const t=await this.clerkGetOrganizationMemberships(),s=this.findPrimaryOrganizationMembership(t);s?(this.setUserOrganizationInfo(i,s),await this.isExtensionBridgeEnabledForOrganization(s.organization.id)&&(o=!0),this.log("[auth] Legacy credentials: Found organization membership:",{id:s.organization.id,name:s.organization.name,role:s.role})):this.log("[auth] Legacy credentials: No organization memberships found")}}catch(t){this.log("[auth] Failed to fetch organization info:",t)}return i.extensionBridgeEnabled=o,i}findOrganizationMembership(t,s){return t?.find(t=>t.organization.id===s)}findPrimaryOrganizationMembership(t){return t&&t.length>0?t[0]:void 0}setUserOrganizationInfo(t,s){t.organizationId=s.organization.id,t.organizationName=s.organization.name,t.organizationRole=s.role,t.organizationImageUrl=s.organization.image_url}async clerkGetOrganizationMemberships(){const t=await fetch(`${B()}/v1/me/organization_memberships`,{headers:{Authorization:`Bearer ${this.credentials.clientToken}`,"User-Agent":this.userAgent()},signal:AbortSignal.timeout(1e4)});return et.parse(await t.json()).response}async getOrganizationMetadata(t){try{const s=await fetch(`${B()}/v1/organizations/${t}`,{headers:{Authorization:`Bearer ${this.credentials.clientToken}`,"User-Agent":this.userAgent()},signal:AbortSignal.timeout(1e4)});if(!s.ok)return this.log(`[auth] Failed to fetch organization metadata: ${s.status} ${s.statusText}`),null;const e=await s.json();return e.response||e}catch(t){return this.log("[auth] Error fetching organization metadata:",t),null}}async isExtensionBridgeEnabledForOrganization(t){const s=await this.getOrganizationMetadata(t);return!0===s?.public_metadata?.extension_bridge_enabled}async clerkLogout(t){const s=new URLSearchParams;s.append("_is_native","1");const e=await fetch(`${B()}/v1/client/sessions/${t.sessionId}/remove`,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Authorization:`Bearer ${t.clientToken}`,"User-Agent":this.userAgent()},body:s.toString(),signal:AbortSignal.timeout(1e4)});if(!e.ok)throw new Error(`HTTP ${e.status}: ${e.statusText}`)}userAgent(){return F(this.context)}},nt=class extends c{state="active-session";token;log;constructor(t,s,e){super(),this.token=s,this.log=e||console.log,this.log("[auth] Using static token authentication mode")}async initialize(){this.state="active-session",this.emit("auth-state-changed",{state:this.state,previousState:"initializing"}),this.log("[auth] Static token auth service initialized in active-session state")}async login(){throw new Error("Authentication methods are disabled in StaticTokenAuthService")}async logout(){throw new Error("Authentication methods are disabled in StaticTokenAuthService")}async handleCallback(t,s,e){throw new Error("Authentication methods are disabled in StaticTokenAuthService")}getState(){return this.state}getSessionToken(){return this.token}isAuthenticated(){return!0}hasActiveSession(){return!0}hasOrIsAcquiringActiveSession(){return!0}getUserInfo(){return{}}getStoredOrganizationId(){return null}},at="organization-settings",rt=class extends c{context;authService;settings=void 0;timer;log;constructor(t,s,e){super(),this.context=t,this.authService=s,this.log=e||console.log,this.timer=new Y({callback:async()=>await this.fetchSettings(),successInterval:3e4,initialBackoffMs:1e3,maxBackoffMs:3e4})}initialize(){this.loadCachedSettings(),"logged-out"==this.authService.getState()&&this.settings&&this.removeSettings(),this.authService.on("auth-state-changed",t=>{"active-session"===t.state?this.timer.start():"active-session"===t.previousState&&(this.timer.stop(),"logged-out"===t.state&&this.removeSettings())}),this.authService.hasActiveSession()&&this.timer.start()}async fetchSettings(){const t=this.authService.getSessionToken();if(!t)return!1;try{const s=await fetch(`${N()}/api/organization-settings`,{headers:{Authorization:`Bearer ${t}`}});if(!s.ok)return this.log("[cloud-settings] Failed to fetch organization settings:",s.status,s.statusText),!1;const e=await s.json(),i=m.safeParse(e);if(!i.success)return this.log("[cloud-settings] Invalid organization settings format:",i.error),!1;const n=i.data;if(!this.settings||this.settings.version!==n.version){const t=this.settings;this.settings=n,await this.cacheSettings(),this.emit("settings-updated",{settings:this.settings,previousSettings:t})}return!0}catch(t){return this.log("[cloud-settings] Error fetching organization settings:",t),!1}}async cacheSettings(){await this.context.globalState.update(at,this.settings)}loadCachedSettings(){this.settings=this.context.globalState.get(at)}getAllowList(){return this.settings?.allowList||k}getSettings(){return this.settings}async removeSettings(){this.settings=void 0,await this.cacheSettings()}dispose(){this.removeAllListeners(),this.timer.stop()}},ot=class{settings;log;constructor(t,s){this.log=s||console.log,this.settings=this.parseEnvironmentSettings(t)}parseEnvironmentSettings(t){try{const s=Buffer.from(t,"base64").toString("utf-8"),e=JSON.parse(s);return m.parse(e)}catch(t){throw this.log(`[StaticSettingsService] failed to parse static settings: ${t instanceof Error?t.message:String(t)}`,t),new Error("Failed to parse static settings",{cause:t})}}getAllowList(){return this.settings?.allowList||k}getSettings(){return this.settings}dispose(){}},ht=class{constructor(t,s=!1){this.subscription=t,this.debug=s}providerRef=null;telemetryEnabled=!1;isEventCapturable(t){return!this.subscription||("include"===this.subscription.type?this.subscription.events.includes(t):!this.subscription.events.includes(t))}isPropertyCapturable(t){return!0}async getEventProperties(t){let s={};const e=this.providerRef?.deref();if(e)try{s=await e.getTelemetryProperties()}catch(t){}const i={...s,...t.properties||{}};return Object.fromEntries(Object.entries(i).filter(([t])=>this.isPropertyCapturable(t)))}setProvider(t){this.providerRef=new WeakRef(t)}isTelemetryEnabled(){return this.telemetryEnabled}},ct=class extends ht{constructor(t,s,e=!1){super({type:"exclude",events:[r.TASK_CONVERSATION_MESSAGE]},e),this.authService=t,this.settingsService=s}async fetch(t,s){if(!this.authService.isAuthenticated())return;const e=this.authService.getSessionToken();e&&(await fetch(`${N()}/api/${t}`,{...s,headers:{Authorization:`Bearer ${e}`,"Content-Type":"application/json"}})).ok}async capture(t){if(!this.isTelemetryEnabled()||!this.isEventCapturable(t.event))return void this.debug;const s={type:t.event,properties:await this.getEventProperties(t)};this.debug;const e=o.safeParse(s);if(e.success)try{await this.fetch("events",{method:"POST",body:JSON.stringify(e.data)})}catch(t){}}async backfillMessages(t,s){if(!this.authService.isAuthenticated())return void this.debug;const e=this.authService.getSessionToken();if(e)try{const i=await this.getEventProperties({event:r.TASK_MESSAGE,properties:{taskId:s}}),n=new FormData;n.append("taskId",s),n.append("properties",JSON.stringify(i)),n.append("file",new File([JSON.stringify(t)],"task.json",{type:"application/json"})),this.debug,(await fetch(`${N()}/api/events/backfill`,{method:"POST",headers:{Authorization:`Bearer ${e}`},body:n})).ok&&this.debug}catch(t){}}updateTelemetryState(t){}isTelemetryEnabled(){return!0}isEventCapturable(t){return!!super.isEventCapturable(t)&&(t!==r.TASK_MESSAGE||this.settingsService.getSettings()?.cloudSettings?.recordTaskMessages||!1)}async shutdown(){}},dt=class{cloudAPI;settingsService;log;constructor(t,s,e){this.cloudAPI=t,this.settingsService=s,this.log=e||console.log}async shareTask(t,s="organization"){try{const e=await this.cloudAPI.shareTask(t,s);if(e.success&&e.shareUrl){const t=await X();if(t?.env?.clipboard?.writeText)try{await t.env.clipboard.writeText(e.shareUrl)}catch(t){this.log("[ShareService] Clipboard write failed (non-fatal):",t)}else this.log("[ShareService] VS Code clipboard unavailable; running outside extension host.")}return e}catch(t){throw this.log("[ShareService] Error sharing task:",t),t}}async canShareTask(){try{return!!this.settingsService.getSettings()?.cloudSettings?.enableTaskSharing}catch(t){return this.log("[ShareService] Error checking if task can be shared:",t),!1}}},lt=class t extends c{static t=null;context;authStateListener;authUserInfoListener;settingsListener;isInitialized=!1;log;i=null;get authService(){return this.i}o=null;get settingsService(){return this.o}h=null;get telemetryClient(){return this.h}l=null;get shareService(){return this.l}u=null;get cloudAPI(){return this.u}constructor(t,s){super(),this.context=t,this.log=s||console.log,this.authStateListener=t=>{this.emit("auth-state-changed",t)},this.authUserInfoListener=t=>{this.emit("user-info",t)},this.settingsListener=t=>{this.emit("settings-updated",t)}}async initialize(){if(!this.isInitialized)try{const t=process.env.ROO_CODE_CLOUD_TOKEN;t&&t.length>0?this.i=new nt(this.context,t,this.log):this.i=new it(this.context,this.log),await this.i.initialize(),this.i.on("auth-state-changed",this.authStateListener),this.i.on("user-info",this.authUserInfoListener);const s=process.env.ROO_CODE_CLOUD_ORG_SETTINGS;if(s&&s.length>0)this.o=new ot(s,this.log);else{const t=new rt(this.context,this.i,this.log);t.initialize(),t.on("settings-updated",this.settingsListener),this.o=t}this.u=new G(this.i,this.log),this.h=new ct(this.i,this.o),this.l=new dt(this.u,this.o,this.log),this.isInitialized=!0}catch(t){throw this.log("[CloudService] Failed to initialize:",t),new Error(`Failed to initialize CloudService: ${t}`)}}async login(){return this.ensureInitialized(),this.authService.login()}async logout(){return this.ensureInitialized(),this.authService.logout()}isAuthenticated(){return this.ensureInitialized(),this.authService.isAuthenticated()}hasActiveSession(){return this.ensureInitialized(),this.authService.hasActiveSession()}hasOrIsAcquiringActiveSession(){return this.ensureInitialized(),this.authService.hasOrIsAcquiringActiveSession()}getUserInfo(){return this.ensureInitialized(),this.authService.getUserInfo()}getOrganizationId(){this.ensureInitialized();const t=this.authService.getUserInfo();return t?.organizationId||null}getOrganizationName(){this.ensureInitialized();const t=this.authService.getUserInfo();return t?.organizationName||null}getOrganizationRole(){this.ensureInitialized();const t=this.authService.getUserInfo();return t?.organizationRole||null}hasStoredOrganizationId(){return this.ensureInitialized(),null!==this.authService.getStoredOrganizationId()}getStoredOrganizationId(){return this.ensureInitialized(),this.authService.getStoredOrganizationId()}getAuthState(){return this.ensureInitialized(),this.authService.getState()}async handleAuthCallback(t,s,e){return this.ensureInitialized(),this.authService.handleCallback(t,s,e)}getAllowList(){return this.ensureInitialized(),this.settingsService.getAllowList()}getOrganizationSettings(){return this.ensureInitialized(),this.settingsService.getSettings()}captureEvent(t){this.ensureInitialized(),this.telemetryClient.capture(t)}async shareTask(t,s="organization",e){this.ensureInitialized();try{return await this.shareService.shareTask(t,s)}catch(i){if(i instanceof H&&e)return await this.telemetryClient.backfillMessages(e,t),await this.shareService.shareTask(t,s);throw i}}async canShareTask(){return this.ensureInitialized(),this.shareService.canShareTask()}dispose(){this.authService&&(this.authService.off("auth-state-changed",this.authStateListener),this.authService.off("user-info",this.authUserInfoListener)),this.settingsService&&(this.settingsService instanceof rt&&this.settingsService.off("settings-updated",this.settingsListener),this.settingsService.dispose()),this.isInitialized=!1}ensureInitialized(){if(!this.isInitialized)throw new Error("CloudService not initialized.")}static get instance(){if(!this.t)throw new Error("CloudService not initialized");return this.t}static async createInstance(s,e){if(this.t)throw new Error("CloudService instance already created");return this.t=new t(s,e),await this.t.initialize(),this.t}static hasInstance(){return null!==this.t&&this.t.isInitialized}static resetInstance(){this.t&&(this.t.dispose(),this.t=null)}static isEnabled(){return!!this.t?.isAuthenticated()}},ut=class{socket=null;connectionState="disconnected";retryAttempt=0;retryTimeout=null;hasConnectedOnce=!1;retryConfig={maxInitialAttempts:10,initialDelay:1e3,maxDelay:15e3,backoffMultiplier:2};CONNECTION_TIMEOUT=2e3;serviceName;options;logger;constructor(t,s,e){this.serviceName=t,this.options=s,this.logger=s.logger||console,e&&(this.retryConfig={...this.retryConfig,...e})}async connect(){"connected"!==this.connectionState?"connecting"!==this.connectionState&&"retrying"!==this.connectionState?(this.logger.log(`[${this.serviceName}] Starting connection process to Socket.IO bridge at:`,this.options.url),this.startConnectionAttempt()):this.logger.log(`[${this.serviceName}] Connection attempt already in progress`):this.logger.log(`[${this.serviceName}] Already connected`)}async startConnectionAttempt(){this.retryAttempt=0;try{await this.connectWithRetry()}catch(t){this.logger.error(`[${this.serviceName}] Initial connection attempts failed:`,t),this.connectionState="failed"}}async connectWithRetry(){let t=this.retryConfig.initialDelay;for(;this.retryAttempt<this.retryConfig.maxInitialAttempts;)try{return this.connectionState=0===this.retryAttempt?"connecting":"retrying",this.logger.log(`[${this.serviceName}] Connection attempt ${this.retryAttempt+1}/${this.retryConfig.maxInitialAttempts}`),await this.connectSocket(),this.connectionState="connected",this.retryAttempt=0,this.logger.log(`[${this.serviceName}] Successfully connected to Socket.IO bridge`),this.clearRetryTimeouts(),void(this.options.onConnect&&await this.options.onConnect())}catch(s){if(this.retryAttempt++,this.logger.error(`[${this.serviceName}] Connection attempt ${this.retryAttempt} failed:`,s),this.socket&&(this.socket.disconnect(),this.socket=null),this.retryAttempt>=this.retryConfig.maxInitialAttempts)throw this.connectionState="failed",new Error(`Failed to connect after ${this.retryConfig.maxInitialAttempts} attempts`);this.logger.log(`[${this.serviceName}] Waiting ${t}ms before retry...`),await this.delay(t),t=Math.min(t*this.retryConfig.backoffMultiplier,this.retryConfig.maxDelay)}}async connectSocket(){return new Promise((t,s)=>{this.logger.log(`[${this.serviceName}] Creating Socket.IO connection (${this.options.url})...`),this.socket=l(this.options.url,this.options.socketOptions),this.logger.log(`[${this.serviceName}] Socket.IO options:`,{reconnection:this.socket.io.opts.reconnection,reconnectionAttempts:this.socket.io.opts.reconnectionAttempts,reconnectionDelay:this.socket.io.opts.reconnectionDelay,reconnectionDelayMax:this.socket.io.opts.reconnectionDelayMax});const e=setTimeout(()=>{this.logger.error(`[${this.serviceName}] Connection timeout`),"connected"!==this.connectionState&&(this.socket?.disconnect(),s(new Error("Connection timeout")))},this.CONNECTION_TIMEOUT);this.socket.on("connect",async()=>{clearTimeout(e);const s=this.hasConnectedOnce;setTimeout(()=>{this.logger.log(`[${this.serviceName}] Socket connected:`,{socketId:this.socket?.id,firstConnection:!s,isReconnection:s})},0),s&&(this.logger.log(`[${this.serviceName}] Treating connect as reconnection (server may have restarted)`),this.connectionState="connected",this.options.onReconnect&&await this.options.onReconnect(0)),this.hasConnectedOnce=!0,t()}),this.socket.on("disconnect",t=>{this.logger.log(`[${this.serviceName}] Socket disconnected:`,{reason:t,socketId:this.socket?.id}),this.connectionState="disconnected",this.options.onDisconnect&&this.options.onDisconnect(t),"io client disconnect"!==t&&this.hasConnectedOnce&&this.logger.log(`[${this.serviceName}] Socket.IO will handle reconnection (reason: ${t})`)}),this.socket.on("reconnect_attempt",t=>{this.logger.log(`[${this.serviceName}] Socket.IO reconnect attempt:`,{attemptNumber:t})}),this.socket.on("reconnect",t=>{this.logger.log(`[${this.serviceName}] Socket reconnected:`,{attemptNumber:t,socketId:this.socket?.id}),this.connectionState="connected",this.options.onReconnect&&this.options.onReconnect(t)}),this.socket.on("reconnect_error",t=>{this.logger.error(`[${this.serviceName}] Socket.IO reconnect error:`,t)}),this.socket.on("reconnect_failed",()=>{this.logger.error(`[${this.serviceName}] Socket.IO reconnection failed after all attempts`),this.connectionState="failed"}),this.socket.on("error",t=>{this.logger.error(`[${this.serviceName}] Socket error:`,t),"connected"!==this.connectionState&&(clearTimeout(e),s(t)),this.options.onError&&this.options.onError(t)}),this.socket.on("auth_error",t=>{this.logger.error(`[${this.serviceName}] Authentication error:`,t),clearTimeout(e),s(new Error(t.message||"Authentication failed"))})})}delay(t){return new Promise(s=>{this.retryTimeout=setTimeout(s,t)})}clearRetryTimeouts(){this.retryTimeout&&(clearTimeout(this.retryTimeout),this.retryTimeout=null)}async disconnect(){this.logger.log(`[${this.serviceName}] Disconnecting...`),this.clearRetryTimeouts(),this.socket&&(this.socket.removeAllListeners(),this.socket.disconnect(),this.socket=null),this.connectionState="disconnected",this.logger.log(`[${this.serviceName}] Disconnected`)}getSocket(){return this.socket}getConnectionState(){return this.connectionState}isConnected(){return"connected"===this.connectionState&&!0===this.socket?.connected}async reconnect(){"connected"!==this.connectionState?(this.logger.log(`[${this.serviceName}] Manual reconnection requested`),this.hasConnectedOnce=!1,await this.disconnect(),await this.connect()):this.logger.log(`[${this.serviceName}] Already connected`)}},pt=class{instanceId;userId;provider;publishEvent;extensionInstance;heartbeatInterval=null;constructor(t,s,e,i){this.instanceId=t,this.userId=s,this.provider=e,this.publishEvent=i,this.extensionInstance={instanceId:this.instanceId,userId:this.userId,workspacePath:this.provider.cwd,extensionVersion:this.provider.context?.extension?.packageJSON?.version||"unknown",lastHeartbeat:Date.now(),...this.getCurrentTask()},this.setupProviderListeners()}async onConnect(t){await this.registerInstance(t),this.startHeartbeat(t)}onDisconnect(){this.stopHeartbeat()}async onReconnect(t){await this.registerInstance(t),this.startHeartbeat(t)}async cleanup(t){this.stopHeartbeat(),t&&await this.unregisterInstance(t)}getExtensionInstance(){return this.extensionInstance}updateTask(t,s){this.extensionInstance.taskId=t,this.extensionInstance.taskStatus=s}handleControlMessage(t){if(t.instanceId===this.instanceId)switch(t.type){case"start_task":this.provider.initClineWithTask(t.payload.text,t.payload.images);break;case"stop_task":{const{taskId:t,taskStatus:s}=this.getCurrentTask();"running"===s?(this.provider.cancelTask(),this.provider.postStateToWebview()):t&&(this.provider.clearTask(),this.provider.postStateToWebview());break}}}async registerInstance(t){this.extensionInstance={...this.extensionInstance,lastHeartbeat:Date.now(),...this.getCurrentTask()};try{t.emit("extension:register",this.extensionInstance)}catch(t){return}await this.publishEvent({type:"instance_registered",instanceId:this.instanceId,payload:{instance:this.extensionInstance},timestamp:Date.now()})}async unregisterInstance(t){await this.publishEvent({type:"instance_unregistered",instanceId:this.instanceId,payload:{instanceId:this.instanceId},timestamp:Date.now()});try{t.emit("extension:unregister",{instanceId:this.instanceId})}catch(t){}}startHeartbeat(t){this.stopHeartbeat(),this.heartbeatInterval=setInterval(async()=>{this.extensionInstance.lastHeartbeat=Date.now();const{taskId:s,taskStatus:e}=this.getCurrentTask();this.extensionInstance.taskId=s,this.extensionInstance.taskStatus=e;try{t.emit("extension:heartbeat",this.extensionInstance)}catch(t){}await this.publishEvent({type:"heartbeat_updated",instanceId:this.instanceId,payload:{instance:this.extensionInstance},timestamp:Date.now()})},2e4)}stopHeartbeat(){this.heartbeatInterval&&(clearInterval(this.heartbeatInterval),this.heartbeatInterval=null)}setupProviderListeners(){this.provider.on(h.TaskCreated,async t=>{const s=this.getCurrentTask();this.publishEvent({type:"task_created",instanceId:this.instanceId,payload:s,timestamp:Date.now()})}),this.provider.on(h.TaskStarted,async t=>{const s=this.getCurrentTask();this.publishEvent({type:"task_started",instanceId:this.instanceId,payload:s,timestamp:Date.now()})}),this.provider.on(h.TaskCompleted,async(t,s,e)=>{const i=this.getCurrentTask();this.publishEvent({type:"task_completed",instanceId:this.instanceId,payload:{...i,tokenUsage:s,toolUsage:e},timestamp:Date.now()})}),this.provider.on(h.TaskAborted,async()=>{const t=this.getCurrentTask();this.publishEvent({type:"task_aborted",instanceId:this.instanceId,payload:t,timestamp:Date.now()})}),this.provider.on(h.TaskFocused,async t=>{const s=this.getCurrentTask();this.publishEvent({type:"task_focused",instanceId:this.instanceId,payload:s,timestamp:Date.now()})}),this.provider.on(h.TaskUnfocused,async t=>{const s=this.getCurrentTask();this.publishEvent({type:"task_unfocused",instanceId:this.instanceId,payload:s,timestamp:Date.now()})}),this.provider.on(h.TaskActive,async t=>{const s=this.getCurrentTask();this.publishEvent({type:"task_active",instanceId:this.instanceId,payload:s,timestamp:Date.now()})}),this.provider.on(h.TaskIdle,async t=>{const s=this.getCurrentTask();this.publishEvent({type:"task_idle",instanceId:this.instanceId,payload:s,timestamp:Date.now()})})}getCurrentTask(){const t=this.provider?.getCurrentCline();return t?{taskId:t.taskId,taskStatus:t.blockingAsk?"idle":"running"}:{taskId:"",taskStatus:"none"}}},gt=class{subscribedTasks=new Map;taskListeners=new Map;publishEvent;pendingTasks=new Map;constructor(t){this.publishEvent=t}async onConnect(t){for(const s of this.subscribedTasks.keys())t.emit("task:join",{taskId:s});for(const s of this.pendingTasks.values())await this.subscribeToTask(s,t);this.pendingTasks.clear()}onDisconnect(){}async onReconnect(t){for(const s of this.subscribedTasks.keys())t.emit("task:join",{taskId:s})}async cleanup(t){if(!t)return;const s=[];for(const e of this.subscribedTasks.keys())s.push(this.unsubscribeFromTask(e,t));await Promise.allSettled(s),this.subscribedTasks.clear(),this.taskListeners.clear(),this.pendingTasks.clear()}addPendingTask(t){this.pendingTasks.set(t.taskId,t)}async subscribeToTask(t,s){const e=t.taskId;this.subscribedTasks.set(e,t),this.setupTaskListeners(t);try{s.emit("task:join",{taskId:e})}catch(t){}}async unsubscribeFromTask(t,s){const e=this.subscribedTasks.get(t);e&&(this.removeTaskListeners(e),this.subscribedTasks.delete(t));try{s.emit("task:leave",{taskId:t})}catch(t){}}getSubscribedTasks(){return this.subscribedTasks}handleControlMessage(t){const{taskId:s}=t,e=this.subscribedTasks.get(s);e&&e.submitUserMessage(t.payload.text,t.payload.images)}setupTaskListeners(t){this.taskListeners.has(t.taskId)&&this.removeTaskListeners(t);const s=new Map,e=()=>{this.publishEvent({type:"task_started",payload:{taskId:t.taskId,taskStatus:t.blockingAsk?"idle":"running"},timestamp:Date.now()})};s.set(h.TaskStarted,e),t.on(h.TaskStarted,e);const i=(s,e,i)=>{this.publishEvent({type:"task_completed",payload:{taskId:t.taskId,taskStatus:t.blockingAsk?"idle":"running",tokenUsage:e,toolUsage:i},timestamp:Date.now()})};s.set(h.TaskCompleted,i),t.on(h.TaskCompleted,i);const n=async()=>{this.publishEvent({type:"task_aborted",payload:{taskId:t.taskId,taskStatus:t.blockingAsk?"idle":"running"},timestamp:Date.now()})};s.set(h.TaskAborted,n),t.on(h.TaskAborted,n);const a=()=>{this.publishEvent({type:"task_focused",payload:{taskId:t.taskId,taskStatus:t.blockingAsk?"idle":"running"},timestamp:Date.now()})};s.set(h.TaskFocused,a),t.on(h.TaskFocused,a);const r=()=>{this.publishEvent({type:"task_unfocused",payload:{taskId:t.taskId,taskStatus:t.blockingAsk?"idle":"running"},timestamp:Date.now()})};s.set(h.TaskUnfocused,r),t.on(h.TaskUnfocused,r);const o=async()=>{this.publishEvent({type:"task_active",payload:{taskId:t.taskId,taskStatus:t.blockingAsk?"idle":"running"},timestamp:Date.now()})};s.set(h.TaskActive,o),t.on(h.TaskActive,o);const c=()=>{this.publishEvent({type:"task_idle",payload:{taskId:t.taskId,taskStatus:t.blockingAsk?"idle":"running"},timestamp:Date.now()})};s.set(h.TaskIdle,c),t.on(h.TaskIdle,c),this.taskListeners.set(t.taskId,s)}removeTaskListeners(t){const s=this.taskListeners.get(t.taskId);s&&(s.forEach((s,e)=>{try{t.off(e,s)}catch(t){}}),this.taskListeners.delete(t.taskId))}},yt=class t{static instance=null;userId;socketBridgeUrl;token;provider;instanceId;connectionManager;extensionManager=null;taskManager=null;MAX_RECONNECT_ATTEMPTS=1/0;RECONNECT_DELAY=1e3;RECONNECT_DELAY_MAX=3e4;static getInstance(){return t.instance}static async createInstance(s){return t.instance=new t(s),await t.instance.initialize(),t.instance}static resetInstance(){t.instance&&(t.instance.disconnect().catch(()=>{}),t.instance=null)}constructor(t){this.userId=t.userId,this.socketBridgeUrl=t.socketBridgeUrl,this.token=t.token,this.provider=t.provider,this.instanceId=d.randomUUID(),this.connectionManager=new ut("UnifiedBridgeService",{url:this.socketBridgeUrl,socketOptions:{query:{token:this.token,clientType:"extension",instanceId:this.instanceId},transports:["websocket","polling"],reconnection:!0,reconnectionAttempts:this.MAX_RECONNECT_ATTEMPTS,reconnectionDelay:this.RECONNECT_DELAY,reconnectionDelayMax:this.RECONNECT_DELAY_MAX},onConnect:async()=>{await this.handleConnect()},onDisconnect:()=>{this.handleDisconnect()},onReconnect:async t=>{await this.handleReconnect(t)}}),this.extensionManager=new pt(this.instanceId,this.userId,this.provider,t=>this.publishExtensionEvent(t)),this.taskManager=new gt(t=>this.publishTaskEvent(t))}async initialize(){await this.connectionManager.connect(),this.setupSocketListeners()}setupSocketListeners(){const t=this.connectionManager.getSocket();t&&(t.off("extension:control:message"),t.off("task:control:message"),t.off("connected"),t.on("extension:control:message",t=>{this.extensionManager?.handleControlMessage(t)}),t.on("task:control:message",t=>{this.taskManager?.handleControlMessage(t)}),t.on("connected",t=>{}))}async handleConnect(){const t=this.connectionManager.getSocket();t&&(this.extensionManager&&await this.extensionManager.onConnect(t),this.taskManager&&await this.taskManager.onConnect(t))}handleDisconnect(){this.extensionManager&&this.extensionManager.onDisconnect(),this.taskManager&&this.taskManager.onDisconnect()}async handleReconnect(t){const s=this.connectionManager.getSocket();s&&(this.setupSocketListeners(),this.extensionManager&&await this.extensionManager.onReconnect(s),this.taskManager&&await this.taskManager.onReconnect(s))}getExtensionInstance(){return this.extensionManager?.getExtensionInstance()??null}updateExtensionTask(t,s){this.extensionManager?.updateTask(t,s)}async subscribeToTask(t){if(!this.taskManager)throw new Error("Task management is not enabled");const s=this.connectionManager.getSocket();if(!s||!this.connectionManager.isConnected()){this.taskManager.addPendingTask(t);const s=this.connectionManager.getConnectionState();return void("disconnected"!==s&&"failed"!==s||this.initialize())}await this.taskManager.subscribeToTask(t,s)}async unsubscribeFromTask(t){if(!this.taskManager)throw new Error("Task management is not enabled");const s=this.connectionManager.getSocket();s&&await this.taskManager.unsubscribeFromTask(t,s)}getSubscribedTasks(){return this.taskManager?.getSubscribedTasks()??new Map}async publishExtensionEvent(t){const s=this.connectionManager.getSocket();if(!s||!this.connectionManager.isConnected())return!1;try{return s.emit("extension:event",t),!0}catch(t){return!1}}async publishTaskEvent(t){const s=this.connectionManager.getSocket();if(!s||!this.connectionManager.isConnected())return!1;try{return s.emit("task:event",t),!0}catch(t){return!1}}getConnectionState(){return this.connectionManager.getConnectionState()}async disconnect(){this.extensionManager&&await this.extensionManager.cleanup(this.connectionManager.getSocket()),this.taskManager&&await this.taskManager.cleanup(this.connectionManager.getSocket()),await this.connectionManager.disconnect(),t.instance=null}async reconnect(){await this.connectionManager.reconnect(),this.setupSocketListeners()}get connected(){return this.connectionManager.isConnected()}get subscribedTaskCount(){return this.taskManager?.getSubscribedTasks().size??0}static async handleRemoteControlState(s,e,i,n){if(s?.extensionBridgeEnabled&&e){const s=t.getInstance();if(s){const t=s.getConnectionState();"failed"!==t&&"disconnected"!==t||(n?.(`[UnifiedBridgeService#handleRemoteControlState] Existing service is ${t}, attempting reconnection`),s.reconnect().catch(t=>{const s=`[UnifiedBridgeService#handleRemoteControlState] Reconnection failed: ${t instanceof Error?t.message:String(t)}`;n?.(s)}))}else try{const s=(await t.createInstance(i)).getConnectionState();n?.(`[UnifiedBridgeService#handleRemoteControlState] Instance created (state: ${s})`),"connected"!==s&&n?.("[UnifiedBridgeService#handleRemoteControlState] Service is not connected yet, will retry in background")}catch(t){const s=`[UnifiedBridgeService#handleRemoteControlState] Failed to create instance: ${t instanceof Error?t.message:String(t)}`;n?.(s)}}else{const s=t.getInstance();if(s)try{await s.disconnect(),t.resetInstance(),n?.("[UnifiedBridgeService#handleRemoteControlState] Service disconnected and reset")}catch(t){const s=`[UnifiedBridgeService#handleRemoteControlState] Failed to disconnect and reset instance: ${t instanceof Error?t.message:String(t)}`;n?.(s)}}}};export{b as BridgeNamespace,G as CloudAPI,lt as CloudService,S as ConnectionState,$ as ExtensionBridgeChannel,x as ExtensionBridgeControlChannelMessageType,E as ExtensionBridgeEventChannelMessageType,T as ExtensionInstanceField,I as HEARTBEAT_INTERVAL_MS,v as INSTANCE_TTL_SECONDS,k as ORGANIZATION_ALLOW_ALL,w as ORGANIZATION_DEFAULT,P as PRODUCTION_CLERK_BASE_URL,L as PRODUCTION_ROO_CODE_API_URL,O as TaskBridgeChannel,U as TaskBridgeControlChannelMessageType,R as TaskBridgeEventChannelMessageType,C as TaskStatus,yt as UnifiedBridgeService,z as extensionBridgeControl