mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-19 06:01:14 +00:00
Add runtime bridge architecture and fix HTML escaping
Major refactoring to unify runtime providers across sandbox and user script contexts: 1. Runtime Bridge & Router - Add RuntimeMessageBridge for unified messaging abstraction - Rename SandboxMessageRouter → RuntimeMessageRouter - Router now handles both iframe and user script messages - Guard for non-extension environments 2. Provider Refactoring - ArtifactsRuntimeProvider: Add offline mode with snapshot fallback - AttachmentsRuntimeProvider: Remove returnDownloadableFile (moved to dedicated provider) - ConsoleRuntimeProvider: Add message collection, remove lifecycle logic - FileDownloadRuntimeProvider: New provider for file downloads 3. HTML Escaping Fix - Escape </script> in JSON.stringify output to prevent premature tag closure - Applies when injecting provider data into <script> tags - JavaScript engine automatically unescapes, no runtime changes needed 4. Function Renaming - listFiles → listAttachments - readTextFile → readTextAttachment - readBinaryFile → readBinaryAttachment - returnFile → returnDownloadableFile 5. Updated Exports - Export new RuntimeMessageBridge and RuntimeMessageRouter - Export FileDownloadRuntimeProvider - Update all cross-references This sets the foundation for reusing providers in browser-javascript tool.
This commit is contained in:
parent
d7d79bd533
commit
c2793d8017
11 changed files with 722 additions and 385 deletions
|
|
@ -7,6 +7,7 @@ import type { SandboxRuntimeProvider } from "./SandboxRuntimeProvider.js";
|
|||
*
|
||||
* OPTIONAL provider that provides file access APIs to sandboxed code.
|
||||
* Only needed when attachments are present.
|
||||
* Attachments are read-only snapshot data - no messaging needed.
|
||||
*/
|
||||
export class AttachmentsRuntimeProvider implements SandboxRuntimeProvider {
|
||||
constructor(private attachments: Attachment[]) {}
|
||||
|
|
@ -26,9 +27,10 @@ export class AttachmentsRuntimeProvider implements SandboxRuntimeProvider {
|
|||
|
||||
getRuntime(): (sandboxId: string) => void {
|
||||
// This function will be stringified, so no external references!
|
||||
return (sandboxId: string) => {
|
||||
// Helper functions for attachments
|
||||
(window as any).listFiles = () =>
|
||||
// These functions read directly from window.attachments
|
||||
// Works both online AND offline (no messaging needed!)
|
||||
return (_sandboxId: string) => {
|
||||
(window as any).listAttachments = () =>
|
||||
((window as any).attachments || []).map((a: any) => ({
|
||||
id: a.id,
|
||||
fileName: a.fileName,
|
||||
|
|
@ -36,7 +38,7 @@ export class AttachmentsRuntimeProvider implements SandboxRuntimeProvider {
|
|||
size: a.size,
|
||||
}));
|
||||
|
||||
(window as any).readTextFile = (attachmentId: string) => {
|
||||
(window as any).readTextAttachment = (attachmentId: string) => {
|
||||
const a = ((window as any).attachments || []).find((x: any) => x.id === attachmentId);
|
||||
if (!a) throw new Error("Attachment not found: " + attachmentId);
|
||||
if (a.extractedText) return a.extractedText;
|
||||
|
|
@ -47,7 +49,7 @@ export class AttachmentsRuntimeProvider implements SandboxRuntimeProvider {
|
|||
}
|
||||
};
|
||||
|
||||
(window as any).readBinaryFile = (attachmentId: string) => {
|
||||
(window as any).readBinaryAttachment = (attachmentId: string) => {
|
||||
const a = ((window as any).attachments || []).find((x: any) => x.id === attachmentId);
|
||||
if (!a) throw new Error("Attachment not found: " + attachmentId);
|
||||
const bin = atob(a.content);
|
||||
|
|
@ -55,46 +57,6 @@ export class AttachmentsRuntimeProvider implements SandboxRuntimeProvider {
|
|||
for (let i = 0; i < bin.length; i++) bytes[i] = bin.charCodeAt(i);
|
||||
return bytes;
|
||||
};
|
||||
|
||||
(window as any).returnFile = async (fileName: string, content: any, mimeType?: string) => {
|
||||
let finalContent: any, finalMimeType: string;
|
||||
|
||||
if (content instanceof Blob) {
|
||||
const arrayBuffer = await content.arrayBuffer();
|
||||
finalContent = new Uint8Array(arrayBuffer);
|
||||
finalMimeType = mimeType || content.type || "application/octet-stream";
|
||||
if (!mimeType && !content.type) {
|
||||
throw new Error(
|
||||
"returnFile: MIME type is required for Blob content. Please provide a mimeType parameter (e.g., 'image/png').",
|
||||
);
|
||||
}
|
||||
} else if (content instanceof Uint8Array) {
|
||||
finalContent = content;
|
||||
if (!mimeType) {
|
||||
throw new Error(
|
||||
"returnFile: MIME type is required for Uint8Array content. Please provide a mimeType parameter (e.g., 'image/png').",
|
||||
);
|
||||
}
|
||||
finalMimeType = mimeType;
|
||||
} else if (typeof content === "string") {
|
||||
finalContent = content;
|
||||
finalMimeType = mimeType || "text/plain";
|
||||
} else {
|
||||
finalContent = JSON.stringify(content, null, 2);
|
||||
finalMimeType = mimeType || "application/json";
|
||||
}
|
||||
|
||||
window.parent.postMessage(
|
||||
{
|
||||
type: "file-returned",
|
||||
sandboxId,
|
||||
fileName,
|
||||
content: finalContent,
|
||||
mimeType: finalMimeType,
|
||||
},
|
||||
"*",
|
||||
);
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue