sliccy 1.22.3 → 1.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/node-server/electron-controller.js +15 -6
- package/dist/node-server/electron-runtime.js +9 -10
- package/dist/node-server/index.js +6 -4
- package/dist/ui/assets/{___vite-browser-external_commonjs-proxy-HEKiI6EW.js → ___vite-browser-external_commonjs-proxy-50mizaS1.js} +1 -1
- package/dist/ui/assets/{bsh-watchdog-DDiweuEz.js → bsh-watchdog-CczyJzjN.js} +1 -1
- package/dist/ui/assets/index-BQr4jU2K.js +1 -0
- package/dist/ui/assets/index-BTswoVMz.js +131 -0
- package/dist/ui/assets/index-BlSQnyL2.css +1 -0
- package/dist/ui/assets/{index-BSBZClnJ.js → index-BpDEWpj8.js} +1 -1
- package/dist/ui/assets/{index-CM2CRGkL.js → index-Bv_aqUU6.js} +1 -1
- package/dist/ui/assets/{index-B73vno6G.js → index-CIHgLbGj.js} +9 -9
- package/dist/ui/assets/index-CMQA9DY9.js +43 -0
- package/dist/ui/assets/index-Dgu92772.js +8814 -0
- package/dist/ui/assets/{index-DtM-71bP.js → index-Dxn4RFzC.js} +1 -1
- package/dist/ui/assets/{index-DaQtug-G.js → index-HsoH0Sk6.js} +1 -1
- package/dist/ui/assets/{index-B0F7PxWn.js → index-NCsQEpn3.js} +1146 -831
- package/dist/ui/assets/{index-DT33yILt.js → index-WwWPiryP.js} +1 -1
- package/dist/ui/assets/{offscreen-client-PiUvXXMe.js → offscreen-client-CH6VFyiS.js} +1 -1
- package/dist/ui/assets/{sql-wasm-r2NFfZ6X.js → sql-wasm-CcBbLZgC.js} +1 -1
- package/dist/ui/index.html +2 -2
- package/dist/ui/logos/logo-editor.html +944 -839
- package/dist/ui/logos/macos-icon.icon/icon.json +19 -24
- package/dist/ui/packages/webapp/index.html +2 -2
- package/package.json +33 -27
- package/dist/ui/assets/index-B15Vjr8J.css +0 -1
- package/dist/ui/assets/index-BjJrFm2K.js +0 -43
- package/dist/ui/assets/index-CqKk1FTy.js +0 -131
- package/dist/ui/assets/index-D3Enm5ux.js +0 -13091
- package/dist/ui/assets/index-MTjFRzVr.js +0 -1
|
@@ -242,7 +242,8 @@ export function decodePngPixels(base64Data) {
|
|
|
242
242
|
case 3: // Average
|
|
243
243
|
row[i] = (row[i] + ((a + b) >>> 1)) & 0xff;
|
|
244
244
|
break;
|
|
245
|
-
case 4: {
|
|
245
|
+
case 4: {
|
|
246
|
+
// Paeth
|
|
246
247
|
const p = a + b - c;
|
|
247
248
|
const pa = Math.abs(p - a);
|
|
248
249
|
const pb = Math.abs(p - b);
|
|
@@ -401,7 +402,7 @@ export class ElectronOverlayInjector {
|
|
|
401
402
|
throw new Error(`CDP target listing failed with ${response.status} ${response.statusText}`);
|
|
402
403
|
}
|
|
403
404
|
const targets = (await response.json());
|
|
404
|
-
const pageCount = targets.filter(t => t.type === 'page').length;
|
|
405
|
+
const pageCount = targets.filter((t) => t.type === 'page').length;
|
|
405
406
|
const injectableTargets = selectBestOverlayTargets(targets);
|
|
406
407
|
if (injectableTargets.length < pageCount) {
|
|
407
408
|
console.log(`[electron-float] Selected ${injectableTargets.length}/${pageCount} page targets for overlay injection`);
|
|
@@ -469,7 +470,9 @@ export class ElectronOverlayInjector {
|
|
|
469
470
|
resolve(value === 'ok');
|
|
470
471
|
}
|
|
471
472
|
}
|
|
472
|
-
catch {
|
|
473
|
+
catch {
|
|
474
|
+
/* ignore */
|
|
475
|
+
}
|
|
473
476
|
};
|
|
474
477
|
const cleanup = () => {
|
|
475
478
|
clearTimeout(timeout);
|
|
@@ -515,7 +518,10 @@ export class ElectronOverlayInjector {
|
|
|
515
518
|
void detectAppThemeFromScreenshot(ws, send).then((theme) => {
|
|
516
519
|
if (ws.readyState !== WebSocket.OPEN)
|
|
517
520
|
return;
|
|
518
|
-
send('Runtime.evaluate', {
|
|
521
|
+
send('Runtime.evaluate', {
|
|
522
|
+
expression: buildThemedBootstrap(theme),
|
|
523
|
+
awaitPromise: false,
|
|
524
|
+
});
|
|
519
525
|
});
|
|
520
526
|
return;
|
|
521
527
|
}
|
|
@@ -566,7 +572,10 @@ export class ElectronOverlayInjector {
|
|
|
566
572
|
void detectAppThemeFromScreenshot(ws, send).then((theme) => {
|
|
567
573
|
if (ws.readyState !== WebSocket.OPEN)
|
|
568
574
|
return;
|
|
569
|
-
send('Runtime.evaluate', {
|
|
575
|
+
send('Runtime.evaluate', {
|
|
576
|
+
expression: buildThemedBootstrap(theme),
|
|
577
|
+
awaitPromise: false,
|
|
578
|
+
});
|
|
570
579
|
});
|
|
571
580
|
// If this was a simple reload (no proxy), check if the iframe loads now.
|
|
572
581
|
// If it still doesn't, escalate to the Fetch proxy as a last resort.
|
|
@@ -650,7 +659,7 @@ export class ElectronOverlayInjector {
|
|
|
650
659
|
continue;
|
|
651
660
|
}
|
|
652
661
|
if (Array.isArray(value)) {
|
|
653
|
-
value.forEach(v => responseHeaders.push({ name, value: v }));
|
|
662
|
+
value.forEach((v) => responseHeaders.push({ name, value: v }));
|
|
654
663
|
}
|
|
655
664
|
else if (value) {
|
|
656
665
|
responseHeaders.push({ name, value });
|
|
@@ -16,7 +16,7 @@ export function hashString(str, max) {
|
|
|
16
16
|
let hash = 0;
|
|
17
17
|
for (let i = 0; i < str.length; i++) {
|
|
18
18
|
const char = str.charCodeAt(i);
|
|
19
|
-
hash = (
|
|
19
|
+
hash = (hash << 5) - hash + char;
|
|
20
20
|
hash = hash & hash; // Convert to 32-bit integer
|
|
21
21
|
}
|
|
22
22
|
return Math.abs(hash) % max;
|
|
@@ -119,14 +119,7 @@ export function resolveElectronAppExecutablePath(appPath, platform = process.pla
|
|
|
119
119
|
// Scan MacOS directory for the main executable
|
|
120
120
|
// Many Electron apps use "Electron" as the executable name
|
|
121
121
|
// Prefer known main executable names, filter out helper processes
|
|
122
|
-
const helperPatterns = [
|
|
123
|
-
/helper/i,
|
|
124
|
-
/crash/i,
|
|
125
|
-
/gpu/i,
|
|
126
|
-
/renderer/i,
|
|
127
|
-
/plugin/i,
|
|
128
|
-
/utility/i,
|
|
129
|
-
];
|
|
122
|
+
const helperPatterns = [/helper/i, /crash/i, /gpu/i, /renderer/i, /plugin/i, /utility/i];
|
|
130
123
|
try {
|
|
131
124
|
const entries = readdirSync(macOSDir);
|
|
132
125
|
// Helper to check if a file is executable
|
|
@@ -235,7 +228,13 @@ export function buildElectronServerSpawnConfig(projectRoot, options) {
|
|
|
235
228
|
if (options.dev) {
|
|
236
229
|
return {
|
|
237
230
|
command: (options.platform ?? process.platform) === 'win32' ? 'npx.cmd' : 'npx',
|
|
238
|
-
args: [
|
|
231
|
+
args: [
|
|
232
|
+
'tsx',
|
|
233
|
+
'packages/node-server/src/index.ts',
|
|
234
|
+
'--dev',
|
|
235
|
+
'--serve-only',
|
|
236
|
+
`--cdp-port=${options.cdpPort}`,
|
|
237
|
+
],
|
|
239
238
|
};
|
|
240
239
|
}
|
|
241
240
|
return {
|
|
@@ -447,7 +447,7 @@ async function main() {
|
|
|
447
447
|
await ensureQaProfileScaffold(PROJECT_ROOT);
|
|
448
448
|
}
|
|
449
449
|
if (chromeProfile.extensionPath && !existsSync(chromeProfile.extensionPath)) {
|
|
450
|
-
console.error(`Extension profile requires ${chromeProfile.extensionPath}. Run \`npm run
|
|
450
|
+
console.error(`Extension profile requires ${chromeProfile.extensionPath}. Run \`npm run build -w @slicc/chrome-extension\` first.`);
|
|
451
451
|
process.exit(1);
|
|
452
452
|
}
|
|
453
453
|
if (chromeProfile.id) {
|
|
@@ -790,8 +790,7 @@ async function main() {
|
|
|
790
790
|
if (Object.keys(headers).length > 0)
|
|
791
791
|
fetchInit.headers = headers;
|
|
792
792
|
if (rawBody.length > 0 && !['GET', 'HEAD'].includes(req.method)) {
|
|
793
|
-
// Buffer extends Uint8Array
|
|
794
|
-
// prove the backing ArrayBuffer is non-shared, so double-cast is needed.
|
|
793
|
+
// Buffer extends Uint8Array which is a valid fetch body at runtime.
|
|
795
794
|
fetchInit.body = rawBody;
|
|
796
795
|
}
|
|
797
796
|
const upstream = await fetch(targetUrl, fetchInit);
|
|
@@ -828,6 +827,7 @@ async function main() {
|
|
|
828
827
|
const { createServer: createViteServer } = await import('vite');
|
|
829
828
|
const webappIndexHtml = resolve(process.cwd(), 'packages/webapp/index.html');
|
|
830
829
|
const vite = await createViteServer({
|
|
830
|
+
configFile: resolve(process.cwd(), 'packages/webapp/vite.config.ts'),
|
|
831
831
|
server: {
|
|
832
832
|
middlewareMode: true,
|
|
833
833
|
hmr: {
|
|
@@ -839,7 +839,9 @@ async function main() {
|
|
|
839
839
|
});
|
|
840
840
|
app.use(vite.middlewares);
|
|
841
841
|
app.use(async (req, res, next) => {
|
|
842
|
-
if (req.method !== 'GET' ||
|
|
842
|
+
if (req.method !== 'GET' ||
|
|
843
|
+
!req.headers.accept?.includes('text/html') ||
|
|
844
|
+
req.path.includes('.')) {
|
|
843
845
|
next();
|
|
844
846
|
return;
|
|
845
847
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{_ as e}from"./__vite-browser-external-D7Ct-6yo.js";import{g as r}from"./index-
|
|
1
|
+
import{_ as e}from"./__vite-browser-external-D7Ct-6yo.js";import{g as r}from"./index-NCsQEpn3.js";const a=r(e);export{a as r};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{c as u}from"./index-
|
|
1
|
+
import{c as u}from"./index-NCsQEpn3.js";const l=["/workspace","/shared"];async function d(s){const t=[],e=new Set;for(const r of l)await s.exists(r)&&await p(s,r,t,e);return t}async function p(s,t,e,r){for await(const n of s.walk(t)){if(!n.endsWith(".bsh")||r.has(n))continue;r.add(n);const i=g(n);if(!i)continue;const a=await s.readFile(n,{encoding:"utf-8"}),c=typeof a=="string"?a:new TextDecoder().decode(a),f=m(c);e.push({path:n,hostnamePattern:i,matchPatterns:f})}}function g(s){const t=s.split("/").pop()??"";if(!t.endsWith(".bsh"))return null;const e=t.slice(0,-4);return e?e.startsWith("-.")?"*"+e.slice(1):e:null}function m(s){const t=s.split(`
|
|
2
2
|
`).slice(0,10),e=[];for(const r of t){const n=r.match(/^\s*\/\/\s*@match\s+(.+)$/);n&&e.push(n[1].trim())}return e}function h(s,t){if(t.startsWith("*.")){const e=t.slice(1);return s.endsWith(e)&&s.length>e.length}return s===t}function v(s,t){try{const e=new URL(s),r=t.match(/^(\*|https?):\/\/([^/]+)(\/.*)?$/);if(!r)return!1;const[,n,i,a]=r;return n!=="*"&&e.protocol.slice(0,-1)!==n||!h(e.hostname,i)?!1:a?x(e.pathname+e.search,a):!0}catch{return!1}}function x(s,t){const e="^"+t.replace(/[.+^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*")+"$";return new RegExp(e).test(s)}function w(s,t){try{const e=new URL(t);return s.filter(r=>h(e.hostname,r.hostnamePattern)?r.matchPatterns.length>0?r.matchPatterns.some(n=>v(t,n)):!0:!1)}catch{return[]}}const o=u("bsh-watchdog");class S{transport;fs;execute;discoveryIntervalMs;entries=[];discoveryTimer=null;running=!1;executing=new Set;constructor(t){this.transport=t.transport,this.fs=t.fs,this.execute=t.execute,this.discoveryIntervalMs=t.discoveryIntervalMs??3e4}async start(){this.running||(this.running=!0,await this.discover(),this.discoveryTimer=setInterval(()=>{this.discover()},this.discoveryIntervalMs),this.transport.on("Page.frameNavigated",this.onFrameNavigated),o.info("BSH watchdog started",{scriptCount:this.entries.length}))}stop(){this.running&&(this.running=!1,this.transport.off("Page.frameNavigated",this.onFrameNavigated),this.discoveryTimer&&(clearInterval(this.discoveryTimer),this.discoveryTimer=null),this.entries=[],this.executing.clear(),o.info("BSH watchdog stopped"))}async discover(){try{this.entries=await d(this.fs),o.debug("BSH discovery complete",{count:this.entries.length})}catch(t){o.error("BSH discovery failed",{error:t instanceof Error?t.message:String(t)})}}getEntries(){return this.entries}onFrameNavigated=t=>{const e=t.frame;if(e?.parentId||!e?.url)return;const r=e.url;if(!r.startsWith("http://")&&!r.startsWith("https://")||this.entries.length===0)return;const n=w(this.entries,r);if(n.length!==0)for(const i of n){const a=`${i.path}::${r}`;this.executing.has(a)||(this.executing.add(a),o.info("BSH watchdog executing script",{script:i.path,url:r}),this.execute(i.path).then(c=>{c.exitCode!==0?o.warn("BSH script failed",{script:i.path,url:r,exitCode:c.exitCode,stderr:c.stderr.slice(0,200)}):o.info("BSH script completed",{script:i.path,url:r})}).catch(c=>{o.error("BSH script execution error",{script:i.path,url:r,error:c instanceof Error?c.message:String(c)})}).finally(()=>{this.executing.delete(a)}))}}}export{S as BshWatchdog};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{c as f,B as C}from"./index-NCsQEpn3.js";import{C as P,H as v,R as H}from"./index-NCsQEpn3.js";const u="[slicc-tab-group]";let g=null;async function p(a){try{if(g!==null)try{await chrome.tabs.group({tabIds:a,groupId:g});return}catch(e){console.info(u,"Tab group removed by user, recreating",{tabId:a,previousGroupId:g,error:e instanceof Error?e.message:String(e)}),g=null}g=await chrome.tabs.group({tabIds:a}),await chrome.tabGroups.update(g,{title:"slicc",color:"pink",collapsed:!1})}catch(e){console.warn(u,"Tab grouping failed (best-effort, continuing without group)",{tabId:a,error:e instanceof Error?e.message:String(e)})}}const h=f("cdp:debugger");class y{_state="disconnected";listeners=new Map;sessionToTab=new Map;attachedTabs=new Set;onEventHandler=(e,s,t)=>{if(!this.attachedTabs.has(e.tabId))return;let n;for(const[o,i]of this.sessionToTab)if(i===e.tabId){n=o;break}h.debug("Event",{tabId:e.tabId,method:s,sessionId:n});const r=this.listeners.get(s);if(r){const o=n?{...t,sessionId:n}:t??{};for(const i of r)try{i(o)}catch(d){h.error("CDP event listener error",{method:s,error:d instanceof Error?d.message:String(d)})}}};onDetachHandler=(e,s)=>{h.warn("Debugger detached",{tabId:e.tabId,reason:s}),this.attachedTabs.delete(e.tabId);for(const[t,n]of this.sessionToTab)n===e.tabId&&this.sessionToTab.delete(t);this.attachedTabs.size===0&&(this._state="disconnected")};get state(){return this._state}async connect(e){if(this._state!=="disconnected")throw new Error(`Cannot connect: state is ${this._state}`);chrome.debugger.onEvent.addListener(this.onEventHandler),chrome.debugger.onDetach.addListener(this.onDetachHandler),this._state="connected",h.info("DebuggerClient connected (extension mode)")}disconnect(){for(const e of this.attachedTabs)chrome.debugger.detach({tabId:e}).catch(s=>{h.debug("Detach during disconnect",{tabId:e,error:s instanceof Error?s.message:String(s)})});chrome.debugger.onEvent.removeListener(this.onEventHandler),chrome.debugger.onDetach.removeListener(this.onDetachHandler),this.attachedTabs.clear(),this.sessionToTab.clear(),this._state="disconnected",h.info("DebuggerClient disconnected")}async send(e,s,t,n){if(this._state!=="connected")throw new Error("DebuggerClient is not connected");switch(e){case"Target.getTargets":return this.handleGetTargets();case"Target.attachToTarget":return this.handleAttachToTarget(s);case"Target.detachFromTarget":return this.handleDetachFromTarget(s);case"Target.createTarget":return this.handleCreateTarget(s);case"Target.closeTarget":return this.handleCloseTarget(s);default:return this.sendCdpCommand(e,s,t)}}on(e,s){let t=this.listeners.get(e);t||(t=new Set,this.listeners.set(e,t)),t.add(s)}off(e,s){const t=this.listeners.get(e);t&&(t.delete(s),t.size===0&&this.listeners.delete(e))}once(e,s=3e4){return new Promise((t,n)=>{const r=setTimeout(()=>{this.off(e,o),n(new Error(`Timed out waiting for event: ${e}`))},s),o=i=>{clearTimeout(r),this.off(e,o),t(i)};this.on(e,o)})}async handleGetTargets(){const[e,s]=await Promise.all([chrome.tabs.query({}),chrome.tabs.query({active:!0,currentWindow:!0})]),t=new Set(s.map(r=>r.id));return{targetInfos:e.map(r=>({targetId:String(r.id),type:"page",title:r.title??"",url:r.url??"",attached:this.attachedTabs.has(r.id),active:t.has(r.id)}))}}async handleAttachToTarget(e){const s=e.targetId,t=parseInt(s,10);if(!Number.isFinite(t)||t<=0)throw new Error(`Invalid targetId: ${s}`);this.attachedTabs.has(t)||(await chrome.debugger.attach({tabId:t},"1.3"),this.attachedTabs.add(t));const n=s;return this.sessionToTab.set(n,t),{sessionId:n}}async handleDetachFromTarget(e){const s=e.sessionId;return this.sessionToTab.get(s)!==void 0&&this.sessionToTab.delete(s),{}}async handleCreateTarget(e){const s=e.url??"about:blank",t=await chrome.tabs.create({url:s,active:!1});return await p(t.id),{targetId:String(t.id)}}async handleCloseTarget(e){const s=e.targetId,t=parseInt(s,10);if(!Number.isFinite(t)||t<=0)throw new Error(`Invalid targetId: ${s}`);for(const[n,r]of this.sessionToTab)r===t&&this.sessionToTab.delete(n);return this.attachedTabs.has(t)&&(this.attachedTabs.delete(t),await chrome.debugger.detach({tabId:t}).catch(n=>{h.debug("Detach before close failed",{tabId:t,error:n instanceof Error?n.message:String(n)})})),await chrome.tabs.remove(t),{success:!0}}async sendCdpCommand(e,s,t){const n=t?this.sessionToTab.get(t):void 0;if(n===void 0)throw new Error(`No tab attached for sessionId: ${t??"(none)"}. Attach to a target first.`);return h.debug("Send",{method:e,tabId:n,sessionId:t}),await chrome.debugger.sendCommand({tabId:n},e,s)??{}}}class I{_state="disconnected";nextCommandId=1;listeners=new Map;pendingCommands=new Map;messageHandler=null;get state(){return this._state}async connect(e){if(this._state!=="disconnected")throw new Error(`Cannot connect: state is ${this._state}`);this.messageHandler=s=>{if(!T(s))return;const t=s;if(t.source!=="service-worker")return;const n=t.payload;n.type==="cdp-response"?this.handleCdpResponse(n):n.type==="cdp-event"&&this.handleCdpEvent(n)},chrome.runtime.onMessage.addListener(this.messageHandler),this._state="connected"}disconnect(){this.messageHandler&&(chrome.runtime.onMessage.removeListener(this.messageHandler),this.messageHandler=null);for(const[,e]of this.pendingCommands)clearTimeout(e.timer),e.reject(new Error("CDP proxy disconnected"));this.pendingCommands.clear(),this.listeners.clear(),this._state="disconnected"}async send(e,s,t,n=3e4){if(this._state!=="connected")throw new Error("OffscreenCdpProxy is not connected");const r=this.nextCommandId++,o={type:"cdp-command",id:r,method:e,params:s,sessionId:t};return new Promise((i,d)=>{let c=!1;const m=setTimeout(()=>{c||(c=!0,this.pendingCommands.delete(r),d(new Error(`CDP command timed out after ${n}ms: ${e}`)))},n);this.pendingCommands.set(r,{resolve:i,reject:d,timer:m}),chrome.runtime.sendMessage({source:"offscreen",payload:o}).catch(l=>{c||(c=!0,this.pendingCommands.delete(r),clearTimeout(m),d(new Error(`Failed to send CDP command: ${l instanceof Error?l.message:String(l)}`)))})})}on(e,s){let t=this.listeners.get(e);t||(t=new Set,this.listeners.set(e,t)),t.add(s)}off(e,s){const t=this.listeners.get(e);t&&(t.delete(s),t.size===0&&this.listeners.delete(e))}once(e,s=3e4){return new Promise((t,n)=>{const r=setTimeout(()=>{this.off(e,o),n(new Error(`Timed out waiting for event: ${e}`))},s),o=i=>{clearTimeout(r),this.off(e,o),t(i)};this.on(e,o)})}handleCdpResponse(e){const s=this.pendingCommands.get(e.id);s&&(this.pendingCommands.delete(e.id),clearTimeout(s.timer),e.error?s.reject(new Error(e.error)):s.resolve(e.result??{}))}handleCdpEvent(e){const s=this.listeners.get(e.method);if(s)for(const t of s)try{t(e.params??{})}catch{}}}function T(a){return typeof a=="object"&&a!==null&&"source"in a&&"payload"in a}class E{_state="disconnected";nextCommandId=1;listeners=new Map;pendingCommands=new Map;messageHandler=null;get state(){return this._state}async connect(e){if(this._state!=="disconnected")throw new Error(`Cannot connect: state is ${this._state}`);this.messageHandler=s=>{try{if(!b(s))return;const t=s;t.source==="offscreen"&&t.payload.type==="panel-cdp-response"&&this.handleCdpResponse(t.payload),t.source==="service-worker"&&t.payload.type==="cdp-event"&&this.handleCdpEvent(t.payload)}catch(t){console.error("[panel-cdp-proxy] Error in message handler:",t)}},chrome.runtime.onMessage.addListener(this.messageHandler),this._state="connected"}disconnect(){this.messageHandler&&(chrome.runtime.onMessage.removeListener(this.messageHandler),this.messageHandler=null);for(const[,e]of this.pendingCommands)clearTimeout(e.timer),e.reject(new Error("Panel CDP proxy disconnected"));this.pendingCommands.clear(),this.listeners.clear(),this._state="disconnected"}async send(e,s,t,n=3e4){if(this._state!=="connected")throw new Error("PanelCdpProxy is not connected");const r=this.nextCommandId++,o={type:"panel-cdp-command",id:r,method:e,params:s,sessionId:t};return new Promise((i,d)=>{let c=!1;const m=setTimeout(()=>{c||(c=!0,this.pendingCommands.delete(r),d(new Error(`CDP command timed out after ${n}ms: ${e}`)))},n);this.pendingCommands.set(r,{resolve:i,reject:d,timer:m}),chrome.runtime.sendMessage({source:"panel",payload:o}).catch(l=>{c||(c=!0,this.pendingCommands.delete(r),clearTimeout(m),d(new Error(`Failed to send CDP command: ${l instanceof Error?l.message:String(l)}`)))})})}on(e,s){let t=this.listeners.get(e);t||(t=new Set,this.listeners.set(e,t)),t.add(s)}off(e,s){const t=this.listeners.get(e);t&&(t.delete(s),t.size===0&&this.listeners.delete(e))}once(e,s=3e4){return new Promise((t,n)=>{const r=setTimeout(()=>{this.off(e,o),n(new Error(`Timed out waiting for event: ${e}`))},s),o=i=>{clearTimeout(r),this.off(e,o),t(i)};this.on(e,o)})}handleCdpResponse(e){const s=this.pendingCommands.get(e.id);if(!s){console.warn(`[panel-cdp-proxy] Ignoring CDP response with unknown id ${e.id}`);return}this.pendingCommands.delete(e.id),clearTimeout(s.timer),e.error?s.reject(new Error(e.error)):s.resolve(e.result??{})}handleCdpEvent(e){const s=this.listeners.get(e.method);if(s)for(const t of s)try{t(e.params??{})}catch(n){console.error(`[panel-cdp-proxy] Listener error for event "${e.method}":`,n)}}}function b(a){return typeof a=="object"&&a!==null&&"source"in a&&"payload"in a}export{C as BrowserAPI,P as CDPClient,y as DebuggerClient,v as HarRecorder,I as OffscreenCdpProxy,E as PanelCdpProxy,H as RemoteCDPTransport};
|