From 7fa06ce50083658511c6f46cb5424771a8b6846b Mon Sep 17 00:00:00 2001 From: Dorian Date: Wed, 4 Mar 2026 00:02:36 +0000 Subject: [PATCH] feat(renderer): sandboxed code runner for HTML/JS/CSS (M10.11) - CodeRunner.vue: sandboxed iframe with srcdoc, allow-scripts only - Console capture via postMessage (log + error) - Run button, clear output, code preview - Extracts runnable code blocks from markdown Co-Authored-By: Claude Opus 4.6 --- .../app/src/components/chat/ChatMessage.vue | 16 +++ .../src/components/renderers/CodeRunner.vue | 133 ++++++++++++++++++ .../src/composables/useCodeBlockExtractor.ts | 32 +++++ 3 files changed, 181 insertions(+) create mode 100644 packages/app/src/components/renderers/CodeRunner.vue create mode 100644 packages/app/src/composables/useCodeBlockExtractor.ts diff --git a/packages/app/src/components/chat/ChatMessage.vue b/packages/app/src/components/chat/ChatMessage.vue index 44ccd43e..0b4d2d29 100644 --- a/packages/app/src/components/chat/ChatMessage.vue +++ b/packages/app/src/components/chat/ChatMessage.vue @@ -214,6 +214,15 @@ /> +
+ +
+
{ return extractEvents(props.message.content) }) +const runnableCodeBlocks = computed(() => { + if (isUser.value) return [] + return extractRunnableCodeBlocks(props.message.content) +}) + const isCodeResponse = computed(() => !isUser.value && props.triggeringQuery.trim().toLowerCase() === '/code' ) diff --git a/packages/app/src/components/renderers/CodeRunner.vue b/packages/app/src/components/renderers/CodeRunner.vue new file mode 100644 index 00000000..fb0e0480 --- /dev/null +++ b/packages/app/src/components/renderers/CodeRunner.vue @@ -0,0 +1,133 @@ +