Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 25 additions & 5 deletions docs/platformclaw/web-ingress-runtime.md
Original file line number Diff line number Diff line change
Expand Up @@ -361,13 +361,33 @@ Gateway validates each file against the owning Agent's allowed media roots.
Plain-text file claims do not grant access. Browser cookies, Gateway
credentials, redirects, and unapproved response headers never cross the bridge.

Images from Basic server execution and assigned VMs open in the image viewer.
PDF, PPT, and PPTX attachments offer **Preview** alongside their original
download. PDF bytes are loaded through the owned media bridge and shown in the
browser's PDF reader. PowerPoint previews convert the authorized attachment
snapshot to PDF; the downloadable PPT or PPTX stays unchanged. Reopening the
Images from Basic server execution and assigned VMs appear inline and open in the
image viewer when selected. PDF, PPT, and PPTX attachments open their preview
automatically when their card is visible, alongside the original download. Closing
a preview keeps that file closed until **Preview** is selected again. Both formats
use the same built-in PDF.js viewer, with page navigation and thumbnail contents,
zoom, **Fit page**, **Fit width**, and **Expand document preview** for a larger view.
PowerPoint previews convert the authorized attachment snapshot to PDF before
rendering; the downloadable PPT or PPTX stays unchanged. Reopening the
conversation uses the same saved snapshot and checks the current browser owner.

The document fits the existing inline attachment box. Page or slide navigation and
**Request changes** stay below it, inside that box. Selection is off until
**Request changes** is chosen. Click a part or drag a region to open a small input
beside that selection, inside the preview. Describe the change and choose **Send request**.
**Preview options** contains zoom, fitting, and **Expand document preview**.
The ordinary chat outbox sends the request to the owning conversation, replies to
the source message, and attaches a bounded image crop for region selections.
The original document is referenced rather than reattached. A rejected request
keeps the instructions; an admitted request uses the existing queue and Retry.
Closing the preview clears the selection and unsent instructions.

The viewer, worker, fonts, and character maps are bundled with the app; previews
need no external viewer service or CDN. The browser receives only the authorized
PDF bytes. PDF JavaScript, forms, and external link actions are not executed.
No Canvas setting or `blob:` frame permission is required. A reverse proxy should
preserve the application's CSP rather than replace it with a static policy.

PDF and PowerPoint previews are limited to 16 MiB, including the converted PDF.
PowerPoint conversion requires the existing rootless sandbox Docker service and
the configured sandbox image with LibreOffice Impress. The PlatformClaw Jammy
Expand Down
21 changes: 16 additions & 5 deletions docs/reference/rich-output-protocol.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,22 @@ Legacy final-reply text may still be normalized for compatibility, but this is n

### Image and document previews

In web chat, select an attached image to open the image viewer. Authorized PDF,
PPT, and PPTX attachments offer **Preview** alongside the original download.
PDF files open in the browser's PDF reader. PowerPoint files are converted to PDF
from the saved attachment snapshot; downloading still returns the original PPT
or PPTX bytes. Previewing does not start another model turn.
In web chat, images appear inline; select one to open the image viewer. Authorized
PDF, PPT, and PPTX attachments open their preview automatically when visible.
Closing a preview keeps that file closed; select **Preview** to reopen it.
PDF and PowerPoint use the same built-in PDF.js viewer inside the attachment box,
fitted to its width, with page navigation below the preview. **Contents** opens
thumbnails; **Preview options** contains zoom, fitting, and an optional expanded view.
Select **Request changes**, then click the part to change or drag a region. A small
input opens beside the selection, inside the same preview. Describe the change and
select **Send request** to send it to the current agent.
The request replies to the original message and includes a crop when a region is
selected; it does not reattach the original document. Closing or changing the
document clears the local selection. The renderer and its assets
ship with the app and do not use an external viewer service. PowerPoint files
are converted to PDF from the saved attachment snapshot; downloading still
returns the original PPT or PPTX bytes. Viewing, navigating, and selecting do not
start another model turn; only submitting the change request sends a chat message.

PDF and PowerPoint previews accept files up to 16 MiB. PowerPoint conversion also
limits its PDF output to 16 MiB. It requires the rootless sandbox Docker service
Expand Down
35 changes: 35 additions & 0 deletions patches/pdfjs-dist@6.4.299.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
--- a/build/pdf.mjs
+++ b/build/pdf.mjs
@@ -15964,6 +15964,11 @@
isEditing = false
} = {}) {
function operatorListChanged() {
+ if (intentState.operatorList.error) {
+ intentState.opListReadCapability.reject(intentState.operatorList.error);
+ intentState.renderTasks.delete(opListTask);
+ return;
+ }
if (intentState.operatorList.lastChunk) {
intentState.opListReadCapability.resolve(intentState.operatorList);
intentState.renderTasks.delete(opListTask);
@@ -16133,6 +16138,7 @@
return;
}
if (intentState.operatorList) {
+ intentState.operatorList.error = reason;
intentState.operatorList.lastChunk = true;
for (const internalRenderTask of intentState.renderTasks) {
internalRenderTask.operatorListChanged();
@@ -17118,6 +17124,12 @@
this.task.onError?.(error);
}
operatorListChanged() {
+ if (this.operatorList.error) {
+ if (!this.cancelled) {
+ this.cancel(this.operatorList.error);
+ }
+ return;
+ }
if (!this.graphicsReady) {
this.graphicsReadyCallback ||= this._continueBound;
return;
135 changes: 135 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pnpm-workspace.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -196,5 +196,6 @@ packageExtensions:
patchedDependencies:
"@azure/msal-node@5.4.2": patches/@azure__msal-node@5.4.2.patch
"@discord/embedded-app-sdk@2.5.0": patches/@discord__embedded-app-sdk@2.5.0.patch
pdfjs-dist@6.4.299: patches/pdfjs-dist@6.4.299.patch
zod@3.25.76: patches/zod@3.25.76.patch
zod@4.6.6: patches/zod@4.6.6.patch
3 changes: 3 additions & 0 deletions scripts/check-control-ui-performance.d.mts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ export type ControlUiPerformanceMetrics = {
assets: ControlUiAssetMetrics[];
};
total: { js: ControlUiAssetSummary; css: ControlUiAssetSummary };
workers: { js: ControlUiAssetSummary; largestJs?: ControlUiAssetMetrics };
/** Ordinary/main-thread JavaScript retains its independent ceiling. */
largest: { js: ControlUiAssetMetrics; css: ControlUiAssetMetrics };
};

Expand All @@ -30,6 +32,7 @@ export type ControlUiPerformanceBudgets = {
startupJsGzipBytes: number;
startupCssGzipBytes: number;
largestJsGzipBytes: number;
largestWorkerJsGzipBytes: number;
largestCssGzipBytes: number;
};

Expand Down
Loading
Loading