Additional
Presentation Artifacts and PPTX Preview
Synced from github.com/CoWork-OS/CoWork-OS/docs
CoWork treats generated PowerPoint decks as first-class presentation artifacts. The current model is review-first: users can inspect slides in the task feed, a resizable right sidebar, or fullscreen mode, then request changes through the same follow-up composer used for spreadsheet and document artifacts. Direct slide editing controls are not part of v1.
Presentation artifacts are one surface of the broader Everything Workbench: generated knowledge-work files open in-place, can be reviewed in context, and keep the follow-up composer beside the artifact.
Supported Formats
In-app preview:
.pptx
Recognized PowerPoint-style artifacts with external-app and folder actions:
.ppt.pptm.potx.potm.ppsx.ppsm
The shared detection and labels live in src/shared/presentation-formats.ts. Cards are labeled as Presentation · PPTX, Presentation · PPT, and so on.
Artifact Surfaces
Generated presentations can appear from file_created, file_modified, artifact_created, task primary-output metadata, and assistant text that mentions a local presentation path such as artifacts/output.pptx.
The task feed renders a compact presentation card:
- orange PowerPoint-style icon
- filename
Presentation · <format>metadata- default Open action
- dropdown actions for external apps and Open in folder
For .pptx, default Open routes to the in-app right-sidebar preview. For legacy or non-previewable PowerPoint formats, default opening falls back to the external app path.
Viewer Experience
The reusable viewer is split between:
src/renderer/components/PresentationArtifactViewer.tsxsrc/renderer/components/PresentationViewer.tsx
Sidebar mode:
- opens in the persisted resizable artifact sidebar
- keeps the main task feed visible to the left
- includes fullscreen and close controls
- shows deck-level copy, external open, and folder actions
Fullscreen mode:
- expands the presentation viewer across the app content area
- keeps the functional follow-up composer overlay
- keeps the latest-turn or working context frame above the composer
- filters the context frame after a follow-up so only events emitted after that prompt are shown
- refreshes the active preview when a matching presentation output event is emitted
Viewer layout:
- slide thumbnails in the left rail
- previous/next navigation and a slide counter in the top toolbar
- zoom selector
- a white canvas with the active slide top-aligned and centered
- rendered slide image when available
- text fallback when rendered images are not available yet
- speaker notes below the slide
Loading Model
Presentation preview loading is intentionally two-phase so opening a deck is fast.
Fast phase:
- parses the
.pptxpackage directly - extracts slide titles, text, and speaker notes
- reuses already-cached slide PNGs when present
- returns immediately without invoking expensive renderers
Render phase:
- renders missing slide PNGs in the background
- updates the open viewer in place when high-fidelity images are ready
- shares in-flight rendering work across sidebar/fullscreen opens
- reuses cached slide images when reopening the same deck
The preview state is exposed through presentationPreview.renderStatus:
cached: all available slide images were loaded from cacherendering: text/notes are visible while image rendering continuesrendered: the full image render finishedtext_only: text/notes are available but image rendering did not produce slidesfailed: preview extraction or rendering failed in a recoverable way
renderMessage can explain the current state, for example Rendering slide previews....
IPC Contract
readFileForViewer accepts:
{
presentationRenderMode?: "fast" | "full";
}
fast returns text, notes, and cached images only. full runs the renderer pipeline and returns the enriched preview.
FileViewerResult.data.presentationPreview includes deck metadata, slide count, render status, and slide entries. Rendered slides prefer imageUrl so cached PNGs can be served as local preview media URLs instead of embedding every image as base64. imageDataUrl remains as a compatibility fallback.
The media URL helper is exported from src/electron/media/index.ts, and the CSP allows media: images in renderer surfaces.
Rendering Pipeline
The preview service is src/electron/utils/PptxPreviewService.ts.
Render priority:
- Codex bundled
@oai/artifact-toolpresentation renderer. - Local
sofficeconversion to PDF pluspdftoppmpage rendering. - Text-only slide and speaker-note preview.
PptxPreviewService is used as a singleton from the Electron IPC layer so render cache and in-flight render dedupe are shared across preview surfaces.
The cached PNGs live under the existing PPTX preview cache. The cache manifest lets fast mode reuse already-rendered slide images without rerunning artifact-tool or LibreOffice.
Generation Model
Both presentation generation tool names route through the shared generator:
generate_presentationcreate_presentation
The shared generator is src/electron/utils/document-generators/pptx-generator.ts.
Generation behavior:
- uses Codex's bundled
@oai/artifact-toolruntime first - falls back to
pptxgenjswhen the bundled runtime is missing or fails - registers the generated
.pptxas a task artifact with the correct MIME type
The bundled kami skill remains available for explicit editorial slide-deck workflows when the user asks for Kami by name. General presentation generation should use the native presentation tools and Codex presentation runtime by default.
Follow-Up Editing
Presentation artifacts do not expose direct slide-edit controls in v1. Edits happen through follow-up prompts:
- The user opens the deck in fullscreen mode.
- The user describes a change in the functional composer.
- The agent updates or regenerates the
.pptx. - The viewer waits until the follow-up work completes, then reloads
readFileForViewerfor the matching deck. - The preview shows fresh text immediately and refreshed slide images when rendering completes.
This keeps the deck review experience responsive without introducing a partial PowerPoint clone.
Implementation Files
src/shared/presentation-formats.tssrc/electron/utils/PptxPreviewService.tssrc/electron/utils/document-generators/pptx-generator.tssrc/electron/utils/codex-artifact-tool-runtime.tssrc/electron/ipc/handlers.tssrc/electron/preload.tssrc/electron/media/media-protocol.tssrc/renderer/components/PresentationArtifactCard.tsxsrc/renderer/components/PresentationArtifactViewer.tsxsrc/renderer/components/PresentationViewer.tsxsrc/renderer/components/InlinePresentationPreview.tsxsrc/renderer/styles/index.css
Verification
Focused tests:
npx vitest run \
src/electron/utils/__tests__/PptxPreviewService.test.ts \
src/renderer/components/__tests__/presentation-artifact-card.test.ts \
src/renderer/components/__tests__/presentation-artifact-viewer.test.ts
Build checks:
npm run build:react
npm run build:electron
npm run type-check
Manual smoke checks:
- Generate a small
.pptxdeck. - Confirm the compact presentation card appears without expanding a hidden output row.
- Click Open and verify the right-sidebar viewer opens.
- Confirm slide text or cached images appear immediately.
- Confirm rendered slide images replace text fallback after background rendering.
- Toggle fullscreen and verify the follow-up composer and latest-turn/working context frame remain functional.
- Submit a follow-up edit and confirm the preview refreshes after the deck is updated.