Integrate JailJS for CSP-restricted execution in browser extension

Major changes:
- Migrate browser-extension to use web-ui package (85% code reduction)
- Add JailJS content script with ES6+ transform support
- Expose DOM constructors (Event, KeyboardEvent, etc.) to JailJS
- Support top-level await by wrapping code in async IIFE
- Add returnFile() support in JailJS execution
- Refactor KeyStore into pluggable storage-adapter pattern
- Make ChatPanel configurable with sandboxUrlProvider and additionalTools
- Update jailjs to 0.1.1

Files deleted (33 duplicate files):
- All browser-extension components, dialogs, state, tools, utils
- Now using web-ui versions via @mariozechner/pi-web-ui

Files added:
- packages/browser-extension/src/content.ts (JailJS content script)
- packages/web-ui/src/state/storage-adapter.ts
- packages/web-ui/src/state/key-store.ts

Browser extension now has only 5 source files (down from 38).
This commit is contained in:
Mario Zechner 2025-10-05 16:58:31 +02:00
parent f2eecb78d2
commit aaea0f4600
61 changed files with 633 additions and 9270 deletions

View file

@ -1,13 +1,24 @@
import { Button, icon } from "@mariozechner/mini-lit";
import "@mariozechner/mini-lit/dist/ThemeToggle.js";
import { ApiKeysDialog, ChromeStorageAdapter, LocalStorageKeyStore, setKeyStore } from "@mariozechner/pi-web-ui";
import "@mariozechner/pi-web-ui"; // Import all web-ui components
import { html, LitElement, render } from "lit";
import { customElement, state } from "lit/decorators.js";
import { Plus, RefreshCw, Settings } from "lucide";
import "./ChatPanel.js";
import "./components/SandboxedIframe.js";
import { ApiKeysDialog } from "./dialogs/ApiKeysDialog.js";
import { browserJavaScriptTool } from "./tools/index.js";
import "./utils/live-reload.js";
declare const browser: any;
// Initialize browser extension storage
setKeyStore(new LocalStorageKeyStore(new ChromeStorageAdapter()));
// Get sandbox URL for extension CSP restrictions
const getSandboxUrl = () => {
const isFirefox = typeof browser !== "undefined" && browser.runtime !== undefined;
return isFirefox ? browser.runtime.getURL("sandbox.html") : chrome.runtime.getURL("sandbox.html");
};
async function getDom() {
const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
if (!tab || !tab.id) return;
@ -98,6 +109,8 @@ class App extends LitElement {
const newPanel = document.createElement("pi-chat-panel") as any;
newPanel.className = "flex-1 min-h-0";
newPanel.systemPrompt = systemPrompt;
newPanel.additionalTools = [browserJavaScriptTool];
newPanel.sandboxUrlProvider = getSandboxUrl;
const container = this.querySelector(".w-full");
if (container) {
@ -109,7 +122,12 @@ class App extends LitElement {
return html`
<div class="w-full h-full flex flex-col bg-background text-foreground overflow-hidden">
<pi-chat-header class="shrink-0" .onNewSession=${() => this.handleNewSession()}></pi-chat-header>
<pi-chat-panel class="flex-1 min-h-0" .systemPrompt=${systemPrompt}></pi-chat-panel>
<pi-chat-panel
class="flex-1 min-h-0"
.systemPrompt=${systemPrompt}
.additionalTools=${[browserJavaScriptTool]}
.sandboxUrlProvider=${getSandboxUrl}
></pi-chat-panel>
</div>
`;
}