@roo-code/cloud
Version:
SDK for integrating with Roo Code Cloud
1 lines • 51.5 kB
JavaScript
var t=require("zod"),e=require("@roo-code/types"),s=require("events"),i=require("crypto"),n=require("socket.io-client");function a(t){return t&&t.t?t:{default:t}}var r=a(s),o=a(i),h=(t=>"undefined"!=typeof require?require:"undefined"!=typeof Proxy?new Proxy(t,{get:(t,e)=>("undefined"!=typeof require?require:t)[e]}):t)(function(t){if("undefined"!=typeof require)return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')}),c=t.z.object({allowAll:t.z.boolean(),providers:t.z.record(t.z.object({allowAll:t.z.boolean(),models:t.z.array(t.z.string()).optional()}))}),d=e.globalSettingsSchema.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.z.object({maxOpenTabsContext:t.z.number().int().nonnegative().optional(),maxReadFileLine:t.z.number().int().gte(-1).optional(),maxWorkspaceFiles:t.z.number().int().nonnegative().optional(),terminalCommandDelay:t.z.number().int().nonnegative().optional(),terminalOutputLineLimit:t.z.number().int().nonnegative().optional(),terminalShellIntegrationTimeout:t.z.number().int().nonnegative().optional()})),l=t.z.object({recordTaskMessages:t.z.boolean().optional(),enableTaskSharing:t.z.boolean().optional(),taskShareExpirationDays:t.z.number().int().positive().optional(),allowMembersViewAllTasks:t.z.boolean().optional()}),u=t.z.object({version:t.z.number(),cloudSettings:l.optional(),defaultSettings:d,allowList:c,hiddenMcps:t.z.array(t.z.string()).optional(),hideMarketplaceMcps:t.z.boolean().optional(),mcps:t.z.array(e.mcpMarketplaceItemSchema).optional(),providerProfiles:t.z.record(t.z.string(),e.discriminatedProviderSettingsWithIdSchema).optional()}),p={allowAll:!0,providers:{}},g={version:0,cloudSettings:{recordTaskMessages:!0,enableTaskSharing:!0,taskShareExpirationDays:30,allowMembersViewAllTasks:!0},defaultSettings:{},allowList:p},y=t.z.object({success:t.z.boolean(),shareUrl:t.z.string().optional(),error:t.z.string().optional(),isNewShare:t.z.boolean().optional(),manageUrl:t.z.string().optional()}),m=(t=>(t.DISCONNECTED="disconnected",t.CONNECTING="connecting",t.CONNECTED="connected",t.RETRYING="retrying",t.FAILED="failed",t))(m||{}),k=(t=>(t.Extension="bridge:extension",t.Task="bridge:task",t))(k||{}),w=(t=>(t.InstanceId="instanceId",t.UserId="userId",t.WorkspacePath="workspacePath",t.ExtensionVersion="extensionVersion",t.LastHeartbeat="lastHeartbeat",t.TaskId="taskId",t.TaskStatus="taskStatus",t))(w||{}),f=(t=>(t.Running="running",t.Idle="idle",t.None="none",t))(f||{}),S=t.z.object({instanceId:t.z.string(),userId:t.z.string(),workspacePath:t.z.string(),extensionVersion:t.z.string(),lastHeartbeat:t.z.coerce.number(),taskId:t.z.string(),taskStatus:t.z.nativeEnum(f)}),I=(t=>(t.Control="control",t.Events="events",t.Instances="instances",t.Instance="instance",t))(I||{}),v=(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))(v||{}),b=t.z.discriminatedUnion("type",[t.z.object({type:t.z.literal("task_created"),instanceId:t.z.string(),payload:t.z.object({taskId:t.z.string(),taskStatus:t.z.nativeEnum(f)}),timestamp:t.z.number()}),t.z.object({type:t.z.literal("task_started"),instanceId:t.z.string(),payload:t.z.object({taskId:t.z.string(),taskStatus:t.z.nativeEnum(f)}),timestamp:t.z.number()}),t.z.object({type:t.z.literal("task_completed"),instanceId:t.z.string(),payload:t.z.object({taskId:t.z.string(),taskStatus:t.z.nativeEnum(f),tokenUsage:e.tokenUsageSchema,toolUsage:e.toolUsageSchema}),timestamp:t.z.number()}),t.z.object({type:t.z.literal("task_aborted"),instanceId:t.z.string(),payload:t.z.object({taskId:t.z.string(),taskStatus:t.z.nativeEnum(f)}),timestamp:t.z.number()}),t.z.object({type:t.z.literal("task_focused"),instanceId:t.z.string(),payload:t.z.object({taskId:t.z.string(),taskStatus:t.z.nativeEnum(f)}),timestamp:t.z.number()}),t.z.object({type:t.z.literal("task_unfocused"),instanceId:t.z.string(),payload:t.z.object({taskId:t.z.string(),taskStatus:t.z.nativeEnum(f)}),timestamp:t.z.number()}),t.z.object({type:t.z.literal("task_active"),instanceId:t.z.string(),payload:t.z.object({taskId:t.z.string(),taskStatus:t.z.nativeEnum(f)}),timestamp:t.z.number()}),t.z.object({type:t.z.literal("task_idle"),instanceId:t.z.string(),payload:t.z.object({taskId:t.z.string(),taskStatus:t.z.nativeEnum(f)}),timestamp:t.z.number()}),t.z.object({type:t.z.literal("instance_registered"),instanceId:t.z.string(),payload:t.z.object({instance:S}),timestamp:t.z.number()}),t.z.object({type:t.z.literal("instance_unregistered"),instanceId:t.z.string(),payload:t.z.object({instanceId:t.z.string()}),timestamp:t.z.number()}),t.z.object({type:t.z.literal("heartbeat_updated"),instanceId:t.z.string(),payload:t.z.object({instance:S}),timestamp:t.z.number()})]),T=(t=>(t.StartTask="start_task",t.StopTask="stop_task",t))(T||{}),C=t.z.discriminatedUnion("type",[t.z.object({type:t.z.literal("start_task"),instanceId:t.z.string(),payload:t.z.object({text:t.z.string(),images:t.z.array(t.z.string()).optional()}),timestamp:t.z.number()}),t.z.object({type:t.z.literal("stop_task"),instanceId:t.z.string(),payload:t.z.object({taskId:t.z.string()}),timestamp:t.z.number()})]),_=(t=>(t.Control="control",t.Events="events",t))(_||{}),x=(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))(x||{}),$=t.z.discriminatedUnion("type",[t.z.object({type:t.z.literal("task_started"),payload:t.z.object({taskId:t.z.string(),taskStatus:t.z.nativeEnum(f)}),timestamp:t.z.number()}),t.z.object({type:t.z.literal("task_completed"),payload:t.z.object({taskId:t.z.string(),taskStatus:t.z.nativeEnum(f),tokenUsage:e.tokenUsageSchema,toolUsage:e.toolUsageSchema}),timestamp:t.z.number()}),t.z.object({type:t.z.literal("task_aborted"),payload:t.z.object({taskId:t.z.string(),taskStatus:t.z.nativeEnum(f)}),timestamp:t.z.number()}),t.z.object({type:t.z.literal("task_focused"),payload:t.z.object({taskId:t.z.string(),taskStatus:t.z.nativeEnum(f)}),timestamp:t.z.number()}),t.z.object({type:t.z.literal("task_unfocused"),payload:t.z.object({taskId:t.z.string(),taskStatus:t.z.nativeEnum(f)}),timestamp:t.z.number()}),t.z.object({type:t.z.literal("task_active"),payload:t.z.object({taskId:t.z.string(),taskStatus:t.z.nativeEnum(f)}),timestamp:t.z.number()}),t.z.object({type:t.z.literal("task_idle"),payload:t.z.object({taskId:t.z.string(),taskStatus:t.z.nativeEnum(f)}),timestamp:t.z.number()})]),E=(t=>(t.Message="message",t))(E||{}),A=t.z.discriminatedUnion("type",[t.z.object({type:t.z.literal("message"),taskId:t.z.string(),payload:t.z.object({text:t.z.string(),images:t.z.array(t.z.string()).optional()}),timestamp:t.z.number()})]),z="https://clerk.roocode.com",O="https://app.roocode.com",R=()=>process.env.CLERK_BASE_URL||z,M=()=>process.env.ROO_CODE_API_URL||O;function U(t){return`Roo-Code ${t?.extension?.packageJSON?.version||"unknown"}`}var D,P=class t extends Error{constructor(e,s,i){super(e),this.statusCode=s,this.responseBody=i,this.name="CloudAPIError",Object.setPrototypeOf(this,t.prototype)}},L=class t extends P{constructor(e){super(e?`Task '${e}' not found`:"Task not found",404),this.name="TaskNotFoundError",Object.setPrototypeOf(this,t.prototype)}},B=class t extends P{constructor(e="Authentication required"){super(e,401),this.name="AuthenticationError",Object.setPrototypeOf(this,t.prototype)}},N=class t extends P{constructor(e="Network error occurred"){super(e),this.name="NetworkError",Object.setPrototypeOf(this,t.prototype)}},F=class t extends Error{constructor(){super("Invalid/Expired client token"),Object.setPrototypeOf(this,t.prototype)}},q=class{authService;log;baseUrl;constructor(t,e){this.authService=t,this.log=e||console.log,this.baseUrl=M()}async request(t,e={}){const{timeout:s=3e4,parseResponse:i,headers:n={},...a}=e,r=this.authService.getSessionToken();if(!r)throw new B;const o=`${this.baseUrl}${t}`,h={"Content-Type":"application/json",Authorization:`Bearer ${r}`,"User-Agent":U(),...n};try{const e=await fetch(o,{...a,headers:h,signal:AbortSignal.timeout(s)});e.ok||await this.handleErrorResponse(e,t);const n=await e.json();return i?i(n):n}catch(e){if(e instanceof TypeError&&e.message.includes("fetch"))throw new N(`Network error while calling ${t}`);if(e instanceof P)throw e;if(e instanceof Error&&"AbortError"===e.name)throw new P(`Request to ${t} timed out`,void 0,void 0);throw new P(`Unexpected error while calling ${t}: ${e instanceof Error?e.message:String(e)}`)}}async handleErrorResponse(t,e){let s;try{s=await t.json()}catch{s=await t.text()}switch(t.status){case 401:throw new B;case 404:if(e.includes("/share"))throw new L;throw new P(`Resource not found: ${e}`,404,s);default:throw new P(`HTTP ${t.status}: ${t.statusText}`,t.status,s)}}async shareTask(t,e="organization"){this.log(`[CloudAPI] Sharing task ${t} with visibility: ${e}`);const s=await this.request("/api/extension/share",{method:"POST",body:JSON.stringify({taskId:t,visibility:e}),parseResponse:t=>y.parse(t)});return this.log("[CloudAPI] Share response:",s),s}async bridgeConfig(){return this.request("/api/extension/bridge/config",{method:"GET",parseResponse:e=>t.z.object({userId:t.z.string(),socketBridgeUrl:t.z.string(),token:t.z.string()}).parse(e)})}};async function j(){if(D)return D;try{if("undefined"!=typeof globalThis&&"acquireVsCodeApi"in globalThis)return;if(void 0!==h)try{if(D=h("vscode"))return D}catch(t){}return D=await import("vscode")}catch(t){}}var H=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)}}},V="clerk-auth-state",J=t.z.object({clientToken:t.z.string().min(1,"Client token cannot be empty"),sessionId:t.z.string().min(1,"Session ID cannot be empty"),organizationId:t.z.string().nullable().optional()}),W=t.z.object({response:t.z.object({created_session_id:t.z.string()})}),G=t.z.object({jwt:t.z.string()}),X=t.z.object({response:t.z.object({id:t.z.string().optional(),first_name:t.z.string().nullish(),last_name:t.z.string().nullish(),image_url:t.z.string().optional(),primary_email_address_id:t.z.string().optional(),email_addresses:t.z.array(t.z.object({id:t.z.string(),email_address:t.z.string()})).optional(),public_metadata:t.z.record(t.z.any()).optional()})}),Y=t.z.object({response:t.z.array(t.z.object({id:t.z.string(),role:t.z.string(),permissions:t.z.array(t.z.string()).optional(),created_at:t.z.number().optional(),updated_at:t.z.number().optional(),organization:t.z.object({id:t.z.string(),name:t.z.string(),slug:t.z.string().optional(),image_url:t.z.string().optional(),has_image:t.z.boolean().optional(),created_at:t.z.number().optional(),updated_at:t.z.number().optional()})}))}),K=class extends r.default{context;timer;state="initializing";log;authCredentialsKey;credentials=null;sessionToken=null;userInfo=null;isFirstRefreshAttempt=!1;constructor(t,e){super(),this.context=t,this.log=e||console.log;const s=R();this.authCredentialsKey=s!==z?`clerk-auth-credentials-${s}`:"clerk-auth-credentials",this.timer=new H({callback:async()=>(await this.refreshSession(),!0),successInterval:5e4,initialBackoffMs:1e3,maxBackoffMs:3e5})}changeState(t){const e=this.state;this.state=t,this.emit("auth-state-changed",{state:t,previousState:e})}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 e=await this.context.secrets.get(this.authCredentialsKey);if(!e)return null;try{const t=JSON.parse(e),s=J.parse(t);return void 0===s.organizationId&&this.userInfo?.organizationId&&(s.organizationId=this.userInfo.organizationId,await this.storeCredentials(s),this.log("[auth] Migrated credentials with organizationId")),s}catch(e){return e instanceof t.z.ZodError?this.log("[auth] Invalid credentials format:",e.errors):this.log("[auth] Failed to parse stored credentials:",e),null}}async clearCredentials(){await this.context.secrets.delete(this.authCredentialsKey)}async login(){try{const t=await j();if(!t)throw new Error("VS Code API not available");const e=o.default.randomBytes(16).toString("hex");await this.context.globalState.update(V,e);const s=this.context.extension?.packageJSON,i=s?.publisher??"RooVeterinaryInc",n=s?.name??"roo-cline",a=new URLSearchParams({state:e,auth_redirect:`${t.env.uriScheme}://${i}.${n}`}),r=`${M()}/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,e,s){if(!t||!e){const t=await j();return void(t&&t.window.showInformationMessage("Invalid Roo Code Cloud sign in url"))}try{if(e!==this.context.globalState.get(V))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=s||null,await this.storeCredentials(i);const n=await j();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(V,void 0),t)try{await this.clerkLogout(t)}catch(t){this.log("[auth] Error calling clerkLogout:",t)}const e=await j();e&&e.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 F?(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 e=new URLSearchParams;e.append("strategy","ticket"),e.append("ticket",t);const s=await fetch(`${R()}/v1/client/sign_ins`,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded","User-Agent":this.userAgent()},body:e.toString(),signal:AbortSignal.timeout(1e4)});if(!s.ok)throw new Error(`HTTP ${s.status}: ${s.statusText}`);const{response:{created_session_id:i}}=W.parse(await s.json()),n=s.headers.get("authorization");if(!n)throw new Error("No authorization header found in the response");return J.parse({clientToken:n,sessionId:i})}async clerkCreateSessionToken(){const t=new URLSearchParams;t.append("_is_native","1");const e=this.getStoredOrganizationId();void 0!==this.credentials?.organizationId&&t.append("organization_id",e||"");const s=await fetch(`${R()}/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===s.status||404===s.status)throw new F;if(!s.ok)throw new Error(`HTTP ${s.status}: ${s.statusText}`);return G.parse(await s.json()).jwt}async clerkMe(){const t=await fetch(`${R()}/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 e=await t.json(),{response:s}=X.parse(e),i={id:s.id,picture:s.image_url},n=[s.first_name,s.last_name].filter(t=>!!t);i.name=n.length>0?n.join(" "):void 0;const a=s.primary_email_address_id,r=s.email_addresses;a&&r&&(i.email=r.find(t=>a===t.id)?.email_address);let o=!1;!0===s.public_metadata?.extension_bridge_enabled&&(o=!0);try{const t=this.getStoredOrganizationId();if(void 0!==this.credentials?.organizationId)if(null!==t){const e=await this.clerkGetOrganizationMemberships(),s=this.findOrganizationMembership(e,t);s?(this.setUserOrganizationInfo(i,s),await this.isExtensionBridgeEnabledForOrganization(t)&&(o=!0),this.log("[auth] User in organization context:",{id:s.organization.id,name:s.organization.name,role:s.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(),e=this.findPrimaryOrganizationMembership(t);e?(this.setUserOrganizationInfo(i,e),await this.isExtensionBridgeEnabledForOrganization(e.organization.id)&&(o=!0),this.log("[auth] Legacy credentials: Found organization membership:",{id:e.organization.id,name:e.organization.name,role:e.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,e){return t?.find(t=>t.organization.id===e)}findPrimaryOrganizationMembership(t){return t&&t.length>0?t[0]:void 0}setUserOrganizationInfo(t,e){t.organizationId=e.organization.id,t.organizationName=e.organization.name,t.organizationRole=e.role,t.organizationImageUrl=e.organization.image_url}async clerkGetOrganizationMemberships(){const t=await fetch(`${R()}/v1/me/organization_memberships`,{headers:{Authorization:`Bearer ${this.credentials.clientToken}`,"User-Agent":this.userAgent()},signal:AbortSignal.timeout(1e4)});return Y.parse(await t.json()).response}async getOrganizationMetadata(t){try{const e=await fetch(`${R()}/v1/organizations/${t}`,{headers:{Authorization:`Bearer ${this.credentials.clientToken}`,"User-Agent":this.userAgent()},signal:AbortSignal.timeout(1e4)});if(!e.ok)return this.log(`[auth] Failed to fetch organization metadata: ${e.status} ${e.statusText}`),null;const s=await e.json();return s.response||s}catch(t){return this.log("[auth] Error fetching organization metadata:",t),null}}async isExtensionBridgeEnabledForOrganization(t){const e=await this.getOrganizationMetadata(t);return!0===e?.public_metadata?.extension_bridge_enabled}async clerkLogout(t){const e=new URLSearchParams;e.append("_is_native","1");const s=await fetch(`${R()}/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:e.toString(),signal:AbortSignal.timeout(1e4)});if(!s.ok)throw new Error(`HTTP ${s.status}: ${s.statusText}`)}userAgent(){return U(this.context)}},Z=class extends r.default{state="active-session";token;log;constructor(t,e,s){super(),this.token=e,this.log=s||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,e,s){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}},Q="organization-settings",tt=class extends r.default{context;authService;settings=void 0;timer;log;constructor(t,e,s){super(),this.context=t,this.authService=e,this.log=s||console.log,this.timer=new H({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 e=await fetch(`${M()}/api/organization-settings`,{headers:{Authorization:`Bearer ${t}`}});if(!e.ok)return this.log("[cloud-settings] Failed to fetch organization settings:",e.status,e.statusText),!1;const s=await e.json(),i=u.safeParse(s);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(Q,this.settings)}loadCachedSettings(){this.settings=this.context.globalState.get(Q)}getAllowList(){return this.settings?.allowList||p}getSettings(){return this.settings}async removeSettings(){this.settings=void 0,await this.cacheSettings()}dispose(){this.removeAllListeners(),this.timer.stop()}},et=class{settings;log;constructor(t,e){this.log=e||console.log,this.settings=this.parseEnvironmentSettings(t)}parseEnvironmentSettings(t){try{const e=Buffer.from(t,"base64").toString("utf-8"),s=JSON.parse(e);return u.parse(s)}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||p}getSettings(){return this.settings}dispose(){}},st=class{constructor(t,e=!1){this.subscription=t,this.debug=e}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 e={};const s=this.providerRef?.deref();if(s)try{e=await s.getTelemetryProperties()}catch(t){}const i={...e,...t.properties||{}};return Object.fromEntries(Object.entries(i).filter(([t])=>this.isPropertyCapturable(t)))}setProvider(t){this.providerRef=new WeakRef(t)}isTelemetryEnabled(){return this.telemetryEnabled}},it=class extends st{constructor(t,s,i=!1){super({type:"exclude",events:[e.TelemetryEventName.TASK_CONVERSATION_MESSAGE]},i),this.authService=t,this.settingsService=s}async fetch(t,e){if(!this.authService.isAuthenticated())return;const s=this.authService.getSessionToken();s&&(await fetch(`${M()}/api/${t}`,{...e,headers:{Authorization:`Bearer ${s}`,"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 i=e.rooCodeTelemetryEventSchema.safeParse(s);if(i.success)try{await this.fetch("events",{method:"POST",body:JSON.stringify(i.data)})}catch(t){}}async backfillMessages(t,s){if(!this.authService.isAuthenticated())return void this.debug;const i=this.authService.getSessionToken();if(i)try{const n=await this.getEventProperties({event:e.TelemetryEventName.TASK_MESSAGE,properties:{taskId:s}}),a=new FormData;a.append("taskId",s),a.append("properties",JSON.stringify(n)),a.append("file",new File([JSON.stringify(t)],"task.json",{type:"application/json"})),this.debug,(await fetch(`${M()}/api/events/backfill`,{method:"POST",headers:{Authorization:`Bearer ${i}`},body:a})).ok&&this.debug}catch(t){}}updateTelemetryState(t){}isTelemetryEnabled(){return!0}isEventCapturable(t){return!!super.isEventCapturable(t)&&(t!==e.TelemetryEventName.TASK_MESSAGE||this.settingsService.getSettings()?.cloudSettings?.recordTaskMessages||!1)}async shutdown(){}},nt=class{cloudAPI;settingsService;log;constructor(t,e,s){this.cloudAPI=t,this.settingsService=e,this.log=s||console.log}async shareTask(t,e="organization"){try{const s=await this.cloudAPI.shareTask(t,e);if(s.success&&s.shareUrl){const t=await j();if(t?.env?.clipboard?.writeText)try{await t.env.clipboard.writeText(s.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 s}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}}},at=class t extends r.default{static i=null;context;authStateListener;authUserInfoListener;settingsListener;isInitialized=!1;log;o=null;get authService(){return this.o}h=null;get settingsService(){return this.h}l=null;get telemetryClient(){return this.l}u=null;get shareService(){return this.u}p=null;get cloudAPI(){return this.p}constructor(t,e){super(),this.context=t,this.log=e||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.o=new Z(this.context,t,this.log):this.o=new K(this.context,this.log),await this.o.initialize(),this.o.on("auth-state-changed",this.authStateListener),this.o.on("user-info",this.authUserInfoListener);const e=process.env.ROO_CODE_CLOUD_ORG_SETTINGS;if(e&&e.length>0)this.h=new et(e,this.log);else{const t=new tt(this.context,this.o,this.log);t.initialize(),t.on("settings-updated",this.settingsListener),this.h=t}this.p=new q(this.o,this.log),this.l=new it(this.o,this.h),this.u=new nt(this.p,this.h,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,e,s){return this.ensureInitialized(),this.authService.handleCallback(t,e,s)}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,e="organization",s){this.ensureInitialized();try{return await this.shareService.shareTask(t,e)}catch(i){if(i instanceof L&&s)return await this.telemetryClient.backfillMessages(s,t),await this.shareService.shareTask(t,e);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 tt&&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.i)throw new Error("CloudService not initialized");return this.i}static async createInstance(e,s){if(this.i)throw new Error("CloudService instance already created");return this.i=new t(e,s),await this.i.initialize(),this.i}static hasInstance(){return null!==this.i&&this.i.isInitialized}static resetInstance(){this.i&&(this.i.dispose(),this.i=null)}static isEnabled(){return!!this.i?.isAuthenticated()}},rt=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,e,s){this.serviceName=t,this.options=e,this.logger=e.logger||console,s&&(this.retryConfig={...this.retryConfig,...s})}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(e){if(this.retryAttempt++,this.logger.error(`[${this.serviceName}] Connection attempt ${this.retryAttempt} failed:`,e),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,e)=>{this.logger.log(`[${this.serviceName}] Creating Socket.IO connection (${this.options.url})...`),this.socket=n.io(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 s=setTimeout(()=>{this.logger.error(`[${this.serviceName}] Connection timeout`),"connected"!==this.connectionState&&(this.socket?.disconnect(),e(new Error("Connection timeout")))},this.CONNECTION_TIMEOUT);this.socket.on("connect",async()=>{clearTimeout(s);const e=this.hasConnectedOnce;setTimeout(()=>{this.logger.log(`[${this.serviceName}] Socket connected:`,{socketId:this.socket?.id,firstConnection:!e,isReconnection:e})},0),e&&(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(s),e(t)),this.options.onError&&this.options.onError(t)}),this.socket.on("auth_error",t=>{this.logger.error(`[${this.serviceName}] Authentication error:`,t),clearTimeout(s),e(new Error(t.message||"Authentication failed"))})})}delay(t){return new Promise(e=>{this.retryTimeout=setTimeout(e,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`)}},ot=class{instanceId;userId;provider;publishEvent;extensionInstance;heartbeatInterval=null;constructor(t,e,s,i){this.instanceId=t,this.userId=e,this.provider=s,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,e){this.extensionInstance.taskId=t,this.extensionInstance.taskStatus=e}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:e}=this.getCurrentTask();"running"===e?(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:e,taskStatus:s}=this.getCurrentTask();this.extensionInstance.taskId=e,this.extensionInstance.taskStatus=s;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(e.RooCodeEventName.TaskCreated,async t=>{const e=this.getCurrentTask();this.publishEvent({type:"task_created",instanceId:this.instanceId,payload:e,timestamp:Date.now()})}),this.provider.on(e.RooCodeEventName.TaskStarted,async t=>{const e=this.getCurrentTask();this.publishEvent({type:"task_started",instanceId:this.instanceId,payload:e,timestamp:Date.now()})}),this.provider.on(e.RooCodeEventName.TaskCompleted,async(t,e,s)=>{const i=this.getCurrentTask();this.publishEvent({type:"task_completed",instanceId:this.instanceId,payload:{...i,tokenUsage:e,toolUsage:s},timestamp:Date.now()})}),this.provider.on(e.RooCodeEventName.TaskAborted,async()=>{const t=this.getCurrentTask();this.publishEvent({type:"task_aborted",instanceId:this.instanceId,payload:t,timestamp:Date.now()})}),this.provider.on(e.RooCodeEventName.TaskFocused,async t=>{const e=this.getCurrentTask();this.publishEvent({type:"task_focused",instanceId:this.instanceId,payload:e,timestamp:Date.now()})}),this.provider.on(e.RooCodeEventName.TaskUnfocused,async t=>{const e=this.getCurrentTask();this.publishEvent({type:"task_unfocused",instanceId:this.instanceId,payload:e,timestamp:Date.now()})}),this.provider.on(e.RooCodeEventName.TaskActive,async t=>{const e=this.getCurrentTask();this.publishEvent({type:"task_active",instanceId:this.instanceId,payload:e,timestamp:Date.now()})}),this.provider.on(e.RooCodeEventName.TaskIdle,async t=>{const e=this.getCurrentTask();this.publishEvent({type:"task_idle",instanceId:this.instanceId,payload:e,timestamp:Date.now()})})}getCurrentTask(){const t=this.provider?.getCurrentCline();return t?{taskId:t.taskId,taskStatus:t.blockingAsk?"idle":"running"}:{taskId:"",taskStatus:"none"}}},ht=class{subscribedTasks=new Map;taskListeners=new Map;publishEvent;pendingTasks=new Map;constructor(t){this.publishEvent=t}async onConnect(t){for(const e of this.subscribedTasks.keys())t.emit("task:join",{taskId:e});for(const e of this.pendingTasks.values())await this.subscribeToTask(e,t);this.pendingTasks.clear()}onDisconnect(){}async onReconnect(t){for(const e of this.subscribedTasks.keys())t.emit("task:join",{taskId:e})}async cleanup(t){if(!t)return;const e=[];for(const s of this.subscribedTasks.keys())e.push(this.unsubscribeFromTask(s,t));await Promise.allSettled(e),this.subscribedTasks.clear(),this.taskListeners.clear(),this.pendingTasks.clear()}addPendingTask(t){this.pendingTasks.set(t.taskId,t)}async subscribeToTask(t,e){const s=t.taskId;this.subscribedTasks.set(s,t),this.setupTaskListeners(t);try{e.emit("task:join",{taskId:s})}catch(t){}}async unsubscribeFromTask(t,e){const s=this.subscribedTasks.get(t);s&&(this.removeTaskListeners(s),this.subscribedTasks.delete(t));try{e.emit("task:leave",{taskId:t})}catch(t){}}getSubscribedTasks(){return this.subscribedTasks}handleControlMessage(t){const{taskId:e}=t,s=this.subscribedTasks.get(e);s&&s.submitUserMessage(t.payload.text,t.payload.images)}setupTaskListeners(t){this.taskListeners.has(t.taskId)&&this.removeTaskListeners(t);const s=new Map,i=()=>{this.publishEvent({type:"task_started",payload:{taskId:t.taskId,taskStatus:t.blockingAsk?"idle":"running"},timestamp:Date.now()})};s.set(e.RooCodeEventName.TaskStarted,i),t.on(e.RooCodeEventName.TaskStarted,i);const n=(e,s,i)=>{this.publishEvent({type:"task_completed",payload:{taskId:t.taskId,taskStatus:t.blockingAsk?"idle":"running",tokenUsage:s,toolUsage:i},timestamp:Date.now()})};s.set(e.RooCodeEventName.TaskCompleted,n),t.on(e.RooCodeEventName.TaskCompleted,n);const a=async()=>{this.publishEvent({type:"task_aborted",payload:{taskId:t.taskId,taskStatus:t.blockingAsk?"idle":"running"},timestamp:Date.now()})};s.set(e.RooCodeEventName.TaskAborted,a),t.on(e.RooCodeEventName.TaskAborted,a);const r=()=>{this.publishEvent({type:"task_focused",payload:{taskId:t.taskId,taskStatus:t.blockingAsk?"idle":"running"},timestamp:Date.now()})};s.set(e.RooCodeEventName.TaskFocused,r),t.on(e.RooCodeEventName.TaskFocused,r);const o=()=>{this.publishEvent({type:"task_unfocused",payload:{taskId:t.taskId,taskStatus:t.blockingAsk?"idle":"running"},timestamp:Date.now()})};s.set(e.RooCodeEventName.TaskUnfocused,o),t.on(e.RooCodeEventName.TaskUnfocused,o);const h=async()=>{this.publishEvent({type:"task_active",payload:{taskId:t.taskId,taskStatus:t.blockingAsk?"idle":"running"},timestamp:Date.now()})};s.set(e.RooCodeEventName.TaskActive,h),t.on(e.RooCodeEventName.TaskActive,h);const c=()=>{this.publishEvent({type:"task_idle",payload:{taskId:t.taskId,taskStatus:t.blockingAsk?"idle":"running"},timestamp:Date.now()})};s.set(e.RooCodeEventName.TaskIdle,c),t.on(e.RooCodeEventName.TaskIdle,c),this.taskListeners.set(t.taskId,s)}removeTaskListeners(t){const e=this.taskListeners.get(t.taskId);e&&(e.forEach((e,s)=>{try{t.off(s,e)}catch(t){}}),this.taskListeners.delete(t.taskId))}};exports.BridgeNamespace=k,exports.CloudAPI=q,exports.CloudService=at,exports.ConnectionState=m,exports.ExtensionBridgeChannel=I,exports.ExtensionBridgeControlChannelMessageType=T,exports.ExtensionBridgeEventChannelMessageType=v,exports.ExtensionInstanceField=w,exports.HEARTBEAT_INTERVAL_MS=2e4,exports.INSTANCE_TTL_SECONDS=60,exports.ORGANIZATION_ALLOW_ALL=p,exports.ORGANIZATION_DEFAULT=g,exports.PRODUCTION_CLERK_BASE_URL=z,exports.PRODUCTION_ROO_CODE_API_URL=O,exports.TaskBridgeChannel=_,exports.TaskBridgeControlChannelMessageType=E,exports.TaskBridgeEventChannelMessageType=x,exports.TaskStatus=f,exports.UnifiedBridgeService=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(e){return t.instance=new t(e),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=o.default.randomUUID(),this.connectionManager=new rt("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 ot(this.instanceId,this.userId,this.provider,t=>this.publishExtensionEvent(t)),this.taskManager=new ht(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 e=this.connectionManager.getSocket();e&&(this.setupSocketListeners(),this.extensionManager&&await this.extensionManager.onReconnect(e),this.taskManager&&await this.taskManager.onReconnect(e))}getExtensionInstance(){return this.extensionManager?.getExtensionInstance()??null}updateExtensionTask(t,e){this.extensionManager?.updateTask(t,e)}async subscribeToTask(t){if(!this.taskManager)throw new Error("Task management is not enabled");const e=this.connectionManager.getSocket();if(!e||!this.connectionManager.isConnected()){this.taskManager.addPendingTask(t);const e=this.connectionManager.getConnectionState();return void("disconnected"!==e&&"failed"!==e||this.initialize())}await this.taskManager.subscribeToTask(t,e)}async unsubscribeFromTask(t){if(!this.taskManager)throw new Error("Task management is not enabled");const e=this.connectionManager.getSocket();e&&await this.taskManager.unsubscribeFromTask(t,e)}getSubscribedTasks(){return this.taskManager?.getSubscribedTasks()??new Map}async publishExtensionEvent(t){const e=this.connectionManager.getSocket();if(!e||!this.connectionManager.isConnected())return!1;try{return e.emit("extension:event",t),!0}catch(t){return!1}}async publishTaskEvent(t){const e=this.connectionManager.getSocket();if(!e||!this.connectionManager.isConnected())return!1;try{return e.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(e,s,i,n){if(e?.extensionBridgeEnabled&&s){const e=t.getInstance();if(e){const t=e.getConnectionState();"failed"!==t&&"disconnected"!==t||(n?.(`[UnifiedBridgeService#handleRemoteCont