mirror of
https://github.com/alkimake/paperclip.git
synced 2026-06-16 19:00:38 +09:00
[codex] Sandbox dynamic adapter UI parsers (#4225)
## Thinking Path > - Paperclip is a control plane for AI-agent companies. > - External adapters can provide UI parser code that the board loads dynamically for run transcript rendering. > - Running adapter-provided parser code directly in the board page gives that parser access to same-origin browser state. > - This PR narrows that surface by evaluating dynamically loaded external adapter UI parser code in a dedicated browser Web Worker with a constrained postMessage protocol. > - The worker here is a frontend isolation boundary for adapter UI parser JavaScript; it is not Paperclip's server plugin-worker system and it is not a server-side job runner. ## What Changed - Runs dynamically loaded external adapter UI parsers inside a dedicated Web Worker instead of importing/evaluating them directly in the board page. - Adds a narrow postMessage protocol for parser initialization and line parsing. - Caches completed async parse results and notifies the adapter registry so transcript recomputation can synchronously drain the final parsed line. - Disables common worker network, persistence, child worker, Blob/object URL, and WebRTC escape APIs inside the parser worker bootstrap. - Handles worker error messages after initialization and drains pending callbacks on worker termination or mid-session worker error. - Adds focused regression coverage for the parser worker lockdown and unused protocol removal. ## Verification - `pnpm exec vitest run --config ui/vitest.config.ts ui/src/adapters/sandboxed-parser-worker.test.ts` - `pnpm exec tsc --noEmit --target es2021 --moduleResolution bundler --module esnext --jsx react-jsx --lib dom,es2021 --skipLibCheck ui/src/adapters/dynamic-loader.ts ui/src/adapters/sandboxed-parser-worker.ts ui/src/adapters/sandboxed-parser-worker.test.ts` - `pnpm --filter @paperclipai/ui typecheck` was attempted; it reached existing unrelated failures in HeartbeatRun test/storybook fixtures and missing Storybook type resolution, with no adapter-module errors surfaced. - PR #4225 checks on current head `34c9da00`: `policy`, `e2e`, `verify`, `security/snyk`, and `Greptile Review` are all `SUCCESS`. - Greptile Review on current head `34c9da00` reached 5/5. ## Risks - Medium risk: parser execution is now asynchronous through a worker while the existing parser interface is synchronous, so transcript updates should be watched with external adapters. - Some adapter parser bundles may rely on direct ESM `export` syntax or browser APIs that are no longer available inside the worker lockdown. - The worker lockdown is a hardening layer around external parser code, not a complete browser security sandbox for arbitrary untrusted applications. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used - OpenAI Codex, GPT-5-based coding agent runtime, shell/git tool use enabled. Exact hosted model build and context window are not exposed in this Paperclip heartbeat environment. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] If this change affects the UI, I have included before/after screenshots - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge
This commit is contained in:
parent
a26e1288b6
commit
73ef40e7be
4 changed files with 445 additions and 73 deletions
|
|
@ -9,7 +9,7 @@ import { openClawGatewayUIAdapter } from "./openclaw-gateway";
|
|||
import { hermesLocalUIAdapter } from "./hermes-local";
|
||||
import { processUIAdapter } from "./process";
|
||||
import { httpUIAdapter } from "./http";
|
||||
import { loadDynamicParser, invalidateDynamicParser } from "./dynamic-loader";
|
||||
import { loadDynamicParser, invalidateDynamicParser, setDynamicParserResultNotifier } from "./dynamic-loader";
|
||||
import { SchemaConfigFields, buildSchemaAdapterConfig } from "./schema-config-fields";
|
||||
|
||||
const uiAdapters: UIAdapterModule[] = [];
|
||||
|
|
@ -45,6 +45,8 @@ function notifyAdapterChange(): void {
|
|||
for (const fn of adapterChangeListeners) fn();
|
||||
}
|
||||
|
||||
setDynamicParserResultNotifier(notifyAdapterChange);
|
||||
|
||||
function registerBuiltInUIAdapters() {
|
||||
for (const adapter of [
|
||||
claudeLocalUIAdapter,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue