Repository navigation
Expand file tree
/
Copy pathphoenix-builder-boot.js
More file actions
1 lines (1 loc) · 9.59 KB
/
Copy pathphoenix-builder-boot.js
File metadata and controls
1 lines (1 loc) · 9.59 KB
1
!function(){if("true"!==localStorage.getItem("phoenixBuilderEnabled"))return;if(!window.AppConfig)return;function _prodInstrumentationAllowedToday(){const stored=localStorage.getItem("prodMCPOverrideDate");if(!/^\d{4}-\d{2}-\d{2}$/.test(stored||""))return!1;const now=new Date,today=now.getFullYear()+"-"+String(now.getMonth()+1).padStart(2,"0")+"-"+String(now.getDate()).padStart(2,"0");return stored===today}if("dev"!==AppConfig.config.environment&&!_prodInstrumentationAllowedToday())return;if(window.Phoenix&&window.Phoenix.isTestWindow&&!window.Phoenix.isSpecRunnerWindow)return;const LOG_TO_CONSOLE_KEY="logToConsole",INSTANCE_NAME_KEY="phoenixBuilderInstanceName",FLUSH_INTERVAL=500,FLUSH_THRESHOLD=50,MAX_BUFFER_SIZE=1e3,MAX_MESSAGE_LENGTH=2e3,RECONNECT_BASE_MS=500,RECONNECT_MAX_MS=5e3,DEFAULT_WS_URL="ws://localhost:38571",METADATA_URL="http://localhost:38572/v1/metadata",METADATA_TIMEOUT_MS=500;let _kernalModeTrust=null,_onConnectionChange=null;function _notifyConnectionChange(connected){if("function"==typeof _onConnectionChange)try{_onConnectionChange(connected)}catch(e){console.error("Phoenix Builder: connection listener failed",e)}}async function _dismantleTrustRing(){try{_kernalModeTrust&&_kernalModeTrust.dismantleKeyring&&await Promise.race([_kernalModeTrust.dismantleKeyring(),new Promise(resolve=>setTimeout(resolve,5e3))])}catch(e){console.error("Error dismantling trust ring before reload:",e)}}let ws=null,logBuffer=[];const capturedLogs=[];let totalLogsPushed=0,flushTimer=null,reconnectTimer=null,reconnectDelay=RECONNECT_BASE_MS,currentUrl=null,autoReconnect=!0,connectionGeneration=0,discoveryAbort=null,displayInstanceName=null;const handlers={};localStorage.setItem("logToConsole","true");const originalConsoleLog=console.log,originalConsoleInfo=console.info,originalConsoleWarn=console.warn,originalConsoleError=console.error;function _getPlatformTag(){if(window.__TAURI__)return"tauri";if(window.__ELECTRON__)return"electron";const desktop=Phoenix.browser&&Phoenix.browser.desktop;if(desktop){if(desktop.isFirefox)return"firefox";if(desktop.isEdgeChromium)return"edge";if(desktop.isOperaChromium||desktop.isOpera)return"opera";if(desktop.isChrome)return"chrome";if(desktop.isSafari)return"safari";if(desktop.isChromeBased)return"chromium"}return"browser"}function _getOrCreateInstanceName(){let name=sessionStorage.getItem(INSTANCE_NAME_KEY);if(!name){const hex=window.crypto&&window.crypto.randomUUID?window.crypto.randomUUID().replace(/-/g,"").slice(0,12):Math.floor(4294967296*Math.random()).toString(16).padStart(8,"0"),prefix=window._phoenixBuilderNamePrefix||"phoenix";name=prefix+"-"+_getPlatformTag()+"-"+hex,sessionStorage.setItem(INSTANCE_NAME_KEY,name)}return name}async function _discoverInstanceIdentity(){const base={name:_getOrCreateInstanceName()},controller=new AbortController;discoveryAbort=controller;const timeout=setTimeout(()=>controller.abort(),METADATA_TIMEOUT_MS);try{const response=await fetch(METADATA_URL,{signal:controller.signal,cache:"no-store",credentials:"omit"});if(!response.ok||!response.body)return base;const reader=response.body.getReader(),decoder=new TextDecoder;let text="",bytes=0;try{for(;;){const item=await reader.read();if(item.done)break;if((bytes+=item.value.byteLength)>16384)return await reader.cancel(),base;text+=decoder.decode(item.value,{stream:!0})}}finally{reader.releaseLock()}text+=decoder.decode();const metadata=JSON.parse(text);return 1===metadata.version&&!0===metadata.orchestratorConnected&&"string"==typeof metadata.machineId&&metadata.machineId&&"string"==typeof metadata.machineName&&/^[a-zA-Z0-9][a-zA-Z0-9_-]{0,79}$/.test(metadata.machineName)?{name:metadata.machineName+"-"+base.name,machineId:metadata.machineId}:base}catch{return base}finally{clearTimeout(timeout),discoveryAbort===controller&&(discoveryAbort=null)}}function _serializeArg(arg){if(null===arg)return"null";if(void 0===arg)return"undefined";if("string"==typeof arg)return arg.length>MAX_MESSAGE_LENGTH?arg.substring(0,MAX_MESSAGE_LENGTH)+"...":arg;if("number"==typeof arg||"boolean"==typeof arg)return String(arg);if(arg instanceof Error)return arg.stack||arg.message||String(arg);try{const seen=new Set,json=JSON.stringify(arg,function(key,value){if("object"==typeof value&&null!==value){if(seen.has(value))return"[Circular]";seen.add(value)}return value});return json.length>MAX_MESSAGE_LENGTH?json.substring(0,MAX_MESSAGE_LENGTH)+"...":json}catch(e){return String(arg)}}function _pushLogEntry(level,args){const message=Array.from(args).map(_serializeArg).join(" "),entry={level:level,message:message,timestamp:(new Date).toISOString()};logBuffer.push(entry),capturedLogs.push(entry),totalLogsPushed++,logBuffer.length>MAX_BUFFER_SIZE&&(logBuffer=logBuffer.slice(logBuffer.length-MAX_BUFFER_SIZE)),capturedLogs.length>MAX_BUFFER_SIZE&&capturedLogs.splice(0,capturedLogs.length-MAX_BUFFER_SIZE),logBuffer.length>=FLUSH_THRESHOLD&&ws&&ws.readyState===WebSocket.OPEN&&_flushLogs()}function _flushLogs(){if(!ws||ws.readyState!==WebSocket.OPEN||0===logBuffer.length)return;const entries=logBuffer;logBuffer=[];try{ws.send(JSON.stringify({type:"console_log",entries:entries}))}catch(e){logBuffer=entries.concat(logBuffer)}}function _sendMessage(msg){if(ws&&ws.readyState===WebSocket.OPEN)try{ws.send(JSON.stringify(msg))}catch(e){}}function _scheduleReconnect(){autoReconnect&¤tUrl&&!reconnectTimer&&(reconnectTimer=setTimeout(function(){reconnectTimer=null,!ws&¤tUrl&&autoReconnect&&connect(currentUrl)},reconnectDelay),reconnectDelay=Math.min(2*reconnectDelay,RECONNECT_MAX_MS))}function _cleanup(){flushTimer&&(clearInterval(flushTimer),flushTimer=null),ws=null}async function connect(url){disconnect();const generation=++connectionGeneration;currentUrl=url,autoReconnect=!0;const identity=await _discoverInstanceIdentity();if(!autoReconnect||generation!==connectionGeneration)return;let socket;displayInstanceName=identity.name;try{socket=new WebSocket(url),ws=socket}catch(e){return ws=null,void _scheduleReconnect()}socket.onopen=function(){ws===socket&&generation===connectionGeneration&&(reconnectDelay=RECONNECT_BASE_MS,_sendMessage({type:"hello",version:"1.0.0",name:identity.name,machineId:identity.machineId}),flushTimer=setInterval(_flushLogs,FLUSH_INTERVAL),_flushLogs(),_notifyConnectionChange(!0))},socket.onmessage=function(event){if(ws!==socket)return;let msg;try{msg=JSON.parse(event.data)}catch(e){return}msg.type&&handlers[msg.type]?handlers[msg.type](msg):"ping"===msg.type&&_sendMessage({type:"pong"})},socket.onclose=function(){ws===socket&&(_cleanup(),_notifyConnectionChange(!1),_scheduleReconnect())},socket.onerror=function(){}}function disconnect(){if(autoReconnect=!1,connectionGeneration++,discoveryAbort&&(discoveryAbort.abort(),discoveryAbort=null),reconnectTimer&&(clearTimeout(reconnectTimer),reconnectTimer=null),ws){try{ws.close(1e3,"Disconnecting")}catch(e){}_cleanup()}}function isConnected(){return null!==ws&&ws.readyState===WebSocket.OPEN}function getInstanceName(){return displayInstanceName||_getOrCreateInstanceName()}function sendMessage(msg){_sendMessage(msg)}function registerHandler(type,fn){handlers[type]=fn}console.log=function(){_pushLogEntry("log",arguments),originalConsoleLog.apply(console,arguments)},console.info=function(){_pushLogEntry("info",arguments),originalConsoleInfo.apply(console,arguments)},console.warn=function(){_pushLogEntry("warn",arguments),originalConsoleWarn.apply(console,arguments)},console.error=function(){_pushLogEntry("error",arguments),originalConsoleError.apply(console,arguments)},window.addEventListener("error",function(event){_pushLogEntry("error",["[Uncaught Error] "+(event.message||"")+(event.filename?" at "+event.filename+":"+event.lineno:"")])}),window.addEventListener("unhandledrejection",function(event){const reason=event.reason,msg=reason instanceof Error?reason.stack||reason.message:String(reason);_pushLogEntry("error",["[Unhandled Promise Rejection] "+msg])}),registerHandler("get_logs_request",function(msg){const tail="number"==typeof msg.tail?msg.tail:50,before="number"==typeof msg.before?msg.before:null,filterStr=msg.filter||null;let source=capturedLogs;if(filterStr)try{const re=new RegExp(filterStr,"i");source=capturedLogs.filter(function(e){return re.test(e.message)})}catch(e){source=capturedLogs}const matchedEntries=source.length,endIdx=null!=before?Math.max(0,Math.min(matchedEntries,before)):matchedEntries;let entries;if(0===tail)entries=source.slice(0,endIdx);else{const startIdx=Math.max(0,endIdx-tail);entries=source.slice(startIdx,endIdx)}_sendMessage({type:"get_logs_response",id:msg.id,entries:entries,totalEntries:totalLogsPushed,matchedEntries:matchedEntries,rangeEnd:endIdx})}),registerHandler("reload_request",function(msg){_sendMessage({type:"reload_response",id:msg.id,success:!0}),setTimeout(async function(){await _dismantleTrustRing(),location.reload()},100)}),registerHandler("exec_js_request",function(msg){const AsyncFunction=async function(){}.constructor,fn=new AsyncFunction("__kernalModeTrust",msg.code);fn(_kernalModeTrust).then(function(result){_sendMessage({type:"exec_js_response",id:msg.id,result:_serializeArg(result)})}).catch(function(err){_sendMessage({type:"exec_js_response",id:msg.id,error:err&&err.stack||err&&err.message||String(err)})})}),window._phoenixBuilder={connect:connect,disconnect:disconnect,isConnected:isConnected,getInstanceName:getInstanceName,sendMessage:sendMessage,registerHandler:registerHandler,getLogBuffer:function(){return capturedLogs.slice()},setConnectionListener:function(fn){_onConnectionChange=fn,fn(isConnected())},dismantleTrustRing:_dismantleTrustRing,setKernalModeTrust:function(trust){_kernalModeTrust=trust,delete window._phoenixBuilder.setKernalModeTrust}};const wsUrl=localStorage.getItem("phoenixBuilderWsUrl")||DEFAULT_WS_URL;connect(wsUrl)}();