@ohos-ports/slides-grab 1.5.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/LICENSE +21 -0
  2. package/README-ko.md +292 -0
  3. package/README.md +301 -0
  4. package/bin/ohos-postinstall.cjs +118 -0
  5. package/bin/ppt-agent.js +620 -0
  6. package/convert.cjs +20 -0
  7. package/native/@img/sharp-libvips-openharmony-arm64/lib/glib-2.0/include/glibconfig.h +220 -0
  8. package/native/@img/sharp-libvips-openharmony-arm64/lib/index.js +1 -0
  9. package/native/@img/sharp-libvips-openharmony-arm64/lib/libexpat.so +0 -0
  10. package/native/@img/sharp-libvips-openharmony-arm64/lib/libffi.so +0 -0
  11. package/native/@img/sharp-libvips-openharmony-arm64/lib/libjpeg.so +0 -0
  12. package/native/@img/sharp-libvips-openharmony-arm64/lib/libpcre2-8.so.0 +0 -0
  13. package/native/@img/sharp-libvips-openharmony-arm64/lib/libvips-cpp.so.42.20.3 +0 -0
  14. package/native/@img/sharp-libvips-openharmony-arm64/lib/libvips.so.42.20.3 +0 -0
  15. package/native/@img/sharp-libvips-openharmony-arm64/package.json +13 -0
  16. package/native/@img/sharp-openharmony-arm64/lib/sharp-openharmony-arm64.node +0 -0
  17. package/native/@img/sharp-openharmony-arm64/package.json +16 -0
  18. package/package.json +95 -0
  19. package/runtimes/claude-code/agents/design-critic-agent.md +23 -0
  20. package/runtimes/codex/agents/slides-grab-design-critic.md +22 -0
  21. package/scripts/build-viewer.js +444 -0
  22. package/scripts/design-gate.js +258 -0
  23. package/scripts/download-video.js +213 -0
  24. package/scripts/editor-server.js +1167 -0
  25. package/scripts/figma-export.js +169 -0
  26. package/scripts/generate-image.js +116 -0
  27. package/scripts/generate-images.js +164 -0
  28. package/scripts/html2pdf.js +822 -0
  29. package/scripts/html2png.js +246 -0
  30. package/scripts/html2pptx.js +162 -0
  31. package/scripts/import-template.js +86 -0
  32. package/scripts/install-runtime.js +216 -0
  33. package/scripts/render-tldraw.js +44 -0
  34. package/scripts/validate-slides.js +221 -0
  35. package/skills/slides-grab/SKILL.md +65 -0
  36. package/skills/slides-grab/references/presentation-workflow-reference.md +61 -0
  37. package/skills/slides-grab-card-news/SKILL.md +35 -0
  38. package/skills/slides-grab-design/SKILL.md +88 -0
  39. package/skills/slides-grab-design/references/beautiful-slide-defaults.md +88 -0
  40. package/skills/slides-grab-design/references/design-gate.md +349 -0
  41. package/skills/slides-grab-design/references/design-rules.md +76 -0
  42. package/skills/slides-grab-design/references/design-system-full.md +568 -0
  43. package/skills/slides-grab-design/references/detailed-design-rules.md +70 -0
  44. package/skills/slides-grab-export/SKILL.md +55 -0
  45. package/skills/slides-grab-export/references/export-rules.md +27 -0
  46. package/skills/slides-grab-export/references/html2pptx.md +627 -0
  47. package/skills/slides-grab-export/references/ooxml.md +427 -0
  48. package/skills/slides-grab-export/references/pptx-skill-reference.md +189 -0
  49. package/skills/slides-grab-html/SKILL.md +67 -0
  50. package/skills/slides-grab-image/SKILL.md +82 -0
  51. package/skills/slides-grab-plan/SKILL.md +68 -0
  52. package/skills/slides-grab-plan/references/design-md-to-slides-conversion.md +135 -0
  53. package/skills/slides-grab-plan/references/outline-format.md +47 -0
  54. package/skills/slides-grab-plan/references/plan-workflow-reference.md +140 -0
  55. package/src/codex-imagen.js +182 -0
  56. package/src/design-diversity-data.js +6932 -0
  57. package/src/design-gate-report.js +244 -0
  58. package/src/design-gate-state.js +329 -0
  59. package/src/design-import.js +164 -0
  60. package/src/design-md-parser.js +415 -0
  61. package/src/design-styles-data.js +1928 -0
  62. package/src/design-styles.js +209 -0
  63. package/src/editor/codex-edit.js +584 -0
  64. package/src/editor/edit-subprocess.js +170 -0
  65. package/src/editor/editor-codex-prompt.md +50 -0
  66. package/src/editor/editor.html +1785 -0
  67. package/src/editor/js/editor-bbox.js +332 -0
  68. package/src/editor/js/editor-chat.js +56 -0
  69. package/src/editor/js/editor-direct-edit.js +238 -0
  70. package/src/editor/js/editor-dom.js +59 -0
  71. package/src/editor/js/editor-init.js +405 -0
  72. package/src/editor/js/editor-navigation.js +54 -0
  73. package/src/editor/js/editor-select.js +558 -0
  74. package/src/editor/js/editor-send.js +175 -0
  75. package/src/editor/js/editor-sse.js +163 -0
  76. package/src/editor/js/editor-state.js +41 -0
  77. package/src/editor/js/editor-type.js +71 -0
  78. package/src/editor/js/editor-utils.js +167 -0
  79. package/src/editor/js/model-registry.js +37 -0
  80. package/src/editor/screenshot.js +82 -0
  81. package/src/export-resolution.cjs +68 -0
  82. package/src/figma.js +71 -0
  83. package/src/html2pptx-scale.cjs +120 -0
  84. package/src/html2pptx.cjs +1262 -0
  85. package/src/image-contract.js +329 -0
  86. package/src/image-native.js +468 -0
  87. package/src/nano-banana.js +841 -0
  88. package/src/ohos-browser-bridge.cjs +272 -0
  89. package/src/pptx-raster-export.cjs +299 -0
  90. package/src/resolve.js +110 -0
  91. package/src/slide-mode.cjs +72 -0
  92. package/src/template-fidelity.js +267 -0
  93. package/src/template-import.js +505 -0
  94. package/src/template-layout.js +261 -0
  95. package/src/template-pack.js +255 -0
  96. package/src/tldraw/render.js +473 -0
  97. package/src/validation/cli.js +120 -0
  98. package/src/validation/core.js +1023 -0
  99. package/templates/chart.html +121 -0
  100. package/templates/closing.html +54 -0
  101. package/templates/content.html +50 -0
  102. package/templates/contents.html +60 -0
  103. package/templates/cover.html +64 -0
  104. package/templates/custom/.gitkeep +0 -0
  105. package/templates/custom/README.md +7 -0
  106. package/templates/design-styles/README.md +20 -0
  107. package/templates/design-styles/preview.html +4438 -0
  108. package/templates/diagram-tldraw.html +56 -0
  109. package/templates/diagram.html +98 -0
  110. package/templates/quote.html +31 -0
  111. package/templates/section-divider.html +43 -0
  112. package/templates/split-layout.html +43 -0
  113. package/templates/statistics.html +55 -0
  114. package/templates/team.html +49 -0
  115. package/templates/timeline.html +59 -0
@@ -0,0 +1,82 @@
1
+ ---
2
+ name: slides-grab-image
3
+ description: Image-native presentation pipeline usable in Codex and Claude Code. Generate whole-slide raster images one slide at a time with slides-grab image, passing the reference template page as --reference so the model copies the layout and style and only swaps the content. Use when visual fidelity to an existing template matters more than editable text.
4
+ metadata:
5
+ short-description: Image-native pipeline — per-slide raster generation with template reference
6
+ ---
7
+
8
+ # slides-grab Image Skill
9
+
10
+ Generate whole-slide raster images where the generated PNG **is** the slide. Each slide is generated individually with `slides-grab image`, passing the matching reference template page image(s) via `--reference` so the model reproduces the template's layout, colors, fonts, and density — only swapping in the new slide's content. Use this pipeline when the user wants to match an existing corporate template, filled deck, or brand form visually.
11
+
12
+ ## Mode signal
13
+ The plan stage records `mode: image-native` in `slide-outline.md`. The user typically provides a reference template (PPTX, PDF, HTML examples) and says "make slides in this form."
14
+
15
+ ## Core rule: reference-guided per-slide generation
16
+ - **Generate one slide at a time** with `slides-grab image`. Do NOT use `slides-grab generate-images` (the batch command auto-assembles garbage prompts from markdown and produces inconsistent output).
17
+ - **Always pass at least one reference template page image** via `--reference <path>` (repeatable). The reference page(s) must be the same slide-type (cover, content, closing) from the source template. The model must copy the reference's layout, color bands, typography hierarchy, whitespace, and density — only the text content and any embedded photos change.
18
+ - The prompt must explicitly instruct: *"Follow the reference image's layout, composition, color palette, and typography hierarchy exactly. Keep the same band positions, spacing, and visual rhythm. Only replace the text content and photos with the new slide's content below."*
19
+ - Pass any real photos/assets to embed as additional `--reference` images so the model can place them into the template layout.
20
+
21
+ ## Prompt structure (use this pattern)
22
+ ```
23
+ slides-grab image \
24
+ --prompt "Follow the reference image layout exactly — same color bands, same typography hierarchy, same spacing and density. This is a [cover/content/closing] slide. Replace the text with: Title: '<new title>'. Body: '<new body text>'. Bullets: <bullet list>. Keep the template's visual style, fonts, and color palette. Render all text sharp and legible. 16:9, 720pt × 405pt." \
25
+ --slides-dir <path> \
26
+ --reference <template-page-cover.png> \
27
+ --reference <real-photo-to-embed.png>
28
+ ```
29
+
30
+ Key prompt principles:
31
+ - **Describe the content to inject**, not the visual design — the reference image defines the design.
32
+ - Name the slide type (cover, content, closing, stat) so the model picks the right reference density.
33
+ - List the exact title, body, and bullets as literal strings the model should render.
34
+ - If embedding real photos, name them in the prompt ("place photo-1 in the left grid cell") and pass them as `--reference`.
35
+ - Require sharp, legible, correctly spelled text.
36
+
37
+ ## Workflow
38
+
39
+ ### Stage 1 — Plan (template-driven dense outline)
40
+ Use the installed **slides-grab-plan** skill with image-native outline density rules.
41
+ 1. Take topic, audience, and tone.
42
+ 2. If the user provides a reference template/PDF/PPTX, import it with `slides-grab import-template --input <path>`. Also render the template pages to PNG (e.g. `pdftoppm -png -r 150 <input>.pdf <prefix>`) and store under `<slides-dir>/.slides-grab/template-previews/`. These page renders are the `--reference` images for Stage 2.
43
+ 3. **Read the template pages in order** (page-01, page-02, ...). For each page, identify its layout type and information density — how many text blocks, data points, bullets, captions, and visual elements it carries. This is the critical step: the outline must match the template's per-slide density, not write a thin HTML-style summary.
44
+ 4. **Write a dense outline**: one outline slide per template page, carrying the full content the user wants — titles, subtitles, body paragraphs, full bullet lists, stat values, table data, captions, and image placement notes — at the volume the template page demonstrates. Image-native slides are single rasters with no HTML structure limits, so they hold more text and data per slide than semantic HTML. Do not under-fill.
45
+ 5. Tag each outline slide with `template-page: NN` so Stage 2 knows which reference image to pass.
46
+ 6. Record `mode: image-native` and `style: template-pack` in `slide-outline.md` meta.
47
+ 7. Present outline, revise until approved.
48
+
49
+ ### Stage 2 — Design (per-slide image generation)
50
+ 1. Read approved `slide-outline.md`. For each slide, read its `template-page: NN` tag and pick that exact template page render from `.slides-grab/template-previews/page-NN.png` as the primary `--reference`. If the slide has no tag, pick 1–2 layout-similar pages by slide type (cover, content, stat, closing).
51
+ 2. For each slide, run `slides-grab image` with:
52
+ - `--prompt` containing ALL the content from the outline for that slide — the full title, subtitle, body paragraphs, every bullet, every stat value, every caption — not a summary. Precede the content with "Follow the reference image layout exactly — same color bands, same typography hierarchy, same spacing and density. Only replace the text content with the content below."
53
+ - `--reference` pointing to the matching template page render(s)
54
+ - `--reference` for any real photos to embed (member photos, product shots, logos)
55
+ - `--slides-dir <path>` and `--name slide-XX` (so the output is `assets/slide-XX.png`)
56
+ - `--image-native` so the command also writes the editor-compatible `slide-XX.html` wrapper and `.slides-grab/image-native/slide-XX.json` regeneration metadata
57
+ - `--provider codex` (default; reuses `~/.codex/auth.json`, run `codex login` once, no API key). Alternatives: `--provider openai` (OPENAI_API_KEY, gpt-image-2), `--provider nano-banana` (GOOGLE_API_KEY/GEMINI_API_KEY).
58
+ 3. Confirm each command reports `Created image-native slide wrapper: slide-XX.html`. Do not hand-write the wrapper; `--image-native` keeps the PNG, wrapper, and regeneration metadata contract aligned for `slides-grab edit-image`.
59
+ 4. Run `slides-grab validate --slides-dir <path>`. Auto-fix failures until it passes.
60
+ 5. Run the design gate (`../slides-grab-design/references/design-gate.md`): capture PNG evidence, run Pass A + Pass B, synthesize verdict. Resolve all Critical findings, re-generate the failing slide, re-render, re-review until `Proceed`. Record with `slides-grab design-gate --slides-dir <path> --verdict proceed --pass-a-report <a.md> --pass-b-report <b.md>`.
61
+ 6. For revisions, regenerate the specific slide with `slides-grab image` (same `--reference`, adjusted `--prompt`), or launch the image-native editor with `slides-grab edit-image --slides-dir <path>`.
62
+
63
+ ### Stage 3 — Export
64
+ Use the installed **slides-grab-export** skill. Requires a fresh `Proceed` gate receipt.
65
+ 1. Widescreen → `slides-grab pdf --slides-dir <path> --output <name>.pdf`.
66
+ 2. Per-slide PNG → `slides-grab png --slides-dir <path> --output-dir <path>/out-png --resolution 2160p`.
67
+ 3. PPTX/Figma (experimental / unstable) → `slides-grab convert` / `slides-grab figma`.
68
+
69
+ ## Rules
70
+ - Keep slide size 720pt × 405pt (16:9).
71
+ - **Always pass `--reference` template page images** — never generate image-native slides from a text-only prompt. The reference defines the visual design; the prompt defines the content.
72
+ - Generate one slide at a time with `slides-grab image`. Do not use `slides-grab generate-images`.
73
+ - `slides-grab image --image-native --name slide-XX` writes the wrapper and regeneration metadata. Do not hand-write semantic text into wrapper slides.
74
+ - Put generated assets under `<slides-dir>/assets/`, reference as `./assets/<file>`.
75
+ - Allow `data:` URLs when a slide must be self-contained; never leave remote `http(s)://` image URLs in saved HTML.
76
+ - Do not present slides for review until `slides-grab validate` passes.
77
+ - Do not advance to export while any Critical design-gate finding is unresolved.
78
+
79
+ ## Reference
80
+ - `../slides-grab-plan/SKILL.md` and `../slides-grab-plan/references/`
81
+ - `../slides-grab-design/SKILL.md` and `../slides-grab-design/references/`
82
+ - `../slides-grab-export/SKILL.md` and `../slides-grab-export/references/`
@@ -0,0 +1,68 @@
1
+ ---
2
+ name: slides-grab-plan
3
+ description: Stage 1 planning skill usable in Codex and Claude Code. Build and iterate slide-outline.md until explicit user approval.
4
+ metadata:
5
+ short-description: Create and revise slide outline before design stage
6
+ ---
7
+
8
+ # slides-grab Plan Skill
9
+
10
+ Use this when the user asks to start a new presentation from scratch.
11
+
12
+ ## Goal
13
+ Produce an approved `slide-outline.md` before any slide HTML generation.
14
+
15
+ ## Inputs
16
+ - Topic and intent
17
+ - Audience
18
+ - Tone and constraints
19
+ - Optional research findings
20
+
21
+ ## Output
22
+ - `slide-outline.md` (must include `style: <id>`, `style: template-pack`, or an approved custom style direction in meta section)
23
+ - For chart-heavy decks, explicit chart slide notes: chart type, data source, key comparison, and whether the design stage should use the default Chart.js canvas template.
24
+
25
+ ## Workflow
26
+ 1. Analyze user goal and audience.
27
+ 2. **Style selection (mandatory, before outline):** Four paths are accepted, in priority order:
28
+ a. **Imported template pack** — when the user provides a corporate deck, reference slides, HTML examples, or brand images, run `slides-grab import-template --input <path> --slides-dir <slides-dir>` (repeat `--input` for multiple examples). Prefer filled representative decks/examples over empty master templates: filled examples reveal density, schema field limits, font resolution, and layout stress cases; an empty master alone is insufficient. Confirm the generated `<slides-dir>/.slides-grab/template-pack.json` is the intended reference source. Record as `style: template-pack`.
29
+ b. **Bundled style** — run `slides-grab list-styles`, shortlist 2–3 styles, and get explicit user approval. Optionally offer `slides-grab preview-styles` for visual preview. Record as `style: <id>`.
30
+ c. **Custom DESIGN.md path** — if a local `DESIGN.md` exists (e.g. provided directly or fetched via `slides-grab import-design <https-url>`), inspect it with `slides-grab show-design ./DESIGN.md` and confirm with the user.
31
+ d. **Free-form custom direction** — if neither imported template pack, bundled style, nor DESIGN.md fits, propose a written custom direction and get approval.
32
+ 3. **DESIGN.md → DESIGN.slides.md conversion (mandatory when path 2c was chosen):**
33
+ - A `DESIGN.md` imported from `voltagent/awesome-design-md` or similar sources describes a **marketing website** (top-nav, hero-band, CTA buttons, pricing cards, footer-band). Slides are **single 720pt × 405pt frames** with no scroll, no nav, no clicks — copying web components into slides produces deck pages that look like landing pages.
34
+ - Read `references/design-md-to-slides-conversion.md` for the canonical conversion guide.
35
+ - Translate the imported `./DESIGN.md` into a sibling `./DESIGN.slides.md` next to it. Leave the original `DESIGN.md` untouched. The `DESIGN.slides.md` MUST follow the Output Contract in the reference and apply every row of the web → slide mapping table (top-nav → eyebrow strip, hero-band → cover layout, CTA buttons → kicker text, footer-band → thin footer strip, pricing grids → dropped, etc.).
36
+ - Present a 5–10 line summary of the conversion to the user (kept tokens + dropped web sections + new slide layouts inferred) and wait for explicit approval before continuing.
37
+ - After approval, run `slides-grab show-design ./DESIGN.slides.md` to confirm the parser reads it cleanly.
38
+ 4. Create or revise `slide-outline.md` with ordered slides and key messages. Record the approved style reference in the meta section:
39
+ - bundled style → `style: <id>`
40
+ - converted DESIGN.slides.md → `style: ./DESIGN.slides.md`
41
+ - imported template pack → `style: template-pack` and keep `<slides-dir>/.slides-grab/template-pack.json` with its `.slides-grab/template-previews/` assets
42
+ - free-form custom direction → leave a one-paragraph `style:` block describing it
43
+ - for chart slides, name the intended chart type and data payload in the slide notes so Stage 2 can build a real Chart.js canvas instead of placeholder bars or decorative pseudo-charts
44
+ - delivery mode → `mode: html` for semantic slide HTML, or `mode: image-native` for raster wrapper slides generated from the approved template/style; prefer `image-native` for existing corporate templates/forms when the user asks for visual matching rather than editable HTML
45
+ 4b. **Image-native outline density (mandatory when mode: image-native and a template is provided):** When the user provides a reference template (PDF/PPTX) for image-native generation, do NOT write a thin HTML-style outline. Instead:
46
+ - Render the template pages to PNG and open them in order (page-01, page-02, ...).
47
+ - For each template page, identify its layout type (cover, section divider, content grid, stat tiles, table, timeline, closing) and measure its **information density** — how many distinct text blocks, data points, bullets, captions, and visual elements it carries.
48
+ - Write one outline slide per template page (or per logical template section), matching that page's layout type and information volume. If template page 3 has a 2×3 stat grid with 6 data points and 3 captions, the corresponding outline slide must also list 6 data points and 3 captions — not just a one-line summary.
49
+ - Image-native slides are single raster images with no HTML structure constraints, so they can hold **more text and data per slide** than semantic HTML. Pack the outline with the full content the user wants on each slide — titles, subtitles, body paragraphs, bullet lists, data tables, stat values, captions, and image placement notes — at the density the template page demonstrates.
50
+ - Tag each outline slide with its matching template page number (e.g. `template-page: 03`) so Stage 2 knows which `--reference` image to pass.
51
+ - The result should be a noticeably denser outline than HTML mode: more bullets, more data, more text per slide, matching what the template's filled pages actually carry.
52
+ 5. Present a concise summary to user.
53
+ 6. Repeat revisions until explicit approval.
54
+
55
+ ## Rules
56
+ - **Do not write the outline before the user approves a style.** Style selection comes first.
57
+ - Do not generate slide HTML (`<slides-dir>/slide-*.html`) in this stage.
58
+ - Keep scope to structure, narrative, and style selection.
59
+ - For quantitative stories, plan charts as evidence: identify the source values, comparison axis, baseline, and intended takeaway. Do not invent filler metrics just to fill a chart.
60
+ - Ask for approval before moving to design.
61
+ - Assume later stages run through the packaged `slides-grab` CLI.
62
+ - Use the packaged CLI and bundled references only; do not depend on unpublished agent-specific files.
63
+
64
+ ## Reference
65
+ If needed, use the bundled outline reference:
66
+ - `references/outline-format.md`
67
+ - `references/plan-workflow-reference.md` — archived detailed planning workflow and runtime-neutral outline-worker guidance
68
+ - `references/design-md-to-slides-conversion.md` — DESIGN.md (web) → DESIGN.slides.md (slide) translation guide, including the structured output template and the web → slide mapping table
@@ -0,0 +1,135 @@
1
+ # DESIGN.md → DESIGN.slides.md Conversion
2
+
3
+ Web-flavored `DESIGN.md` files (Google Stitch / voltagent/awesome-design-md
4
+ convention) describe **marketing websites**: top-nav, hero-band, CTA buttons,
5
+ pricing cards, footer-band, multi-section scrolling pages.
6
+
7
+ A slide is a **720pt × 405pt single frame, no scroll, no clicks, no nav**.
8
+ Pasting a web design system into slides produces deck pages that look like
9
+ landing pages — wrong slot.
10
+
11
+ This document is the canonical reference the agent uses to translate a
12
+ DESIGN.md into a sibling `DESIGN.slides.md` that fits the slide medium.
13
+
14
+ ## Output contract
15
+
16
+ The agent MUST produce a file named `DESIGN.slides.md` next to the source
17
+ `DESIGN.md` at the deck root. The original `DESIGN.md` MUST be left untouched.
18
+
19
+ `DESIGN.slides.md` MUST contain the following sections, in this order:
20
+
21
+ ```markdown
22
+ ---
23
+ version: alpha
24
+ name: <inherited from DESIGN.md `name`>
25
+ description: <one-sentence slide-flavored mood — not a marketing paragraph>
26
+ derived-from: <relative path to source DESIGN.md, e.g. ./DESIGN.md>
27
+ medium: slides-16x9
28
+ colors:
29
+ <token-name>: <#hex>
30
+ ---
31
+
32
+ ## Overview
33
+ One short paragraph describing the slide deck's atmosphere — material, energy,
34
+ typographic voice. No mention of pages, scroll, nav, CTA, pricing, or routes.
35
+
36
+ ## Background
37
+ Solid fills only. List 1-3 canvas modes that alternate across slides.
38
+
39
+ ## Colors
40
+ Markdown table of the slide-active palette. Drop any role that exists only
41
+ for hover/focus/disabled states (those don't apply to static slides).
42
+
43
+ ## Typography
44
+ Two faces: a display face for headlines and a body face for everything else.
45
+ Optionally a mono face for eyebrows / IDs / code motifs. Include working
46
+ font-stack fallbacks (Google Fonts that render in Playwright capture).
47
+
48
+ ## Slide Layouts
49
+ Enumerate the slide archetypes this design system supports. ALWAYS include
50
+ at least these five:
51
+ - **Cover** — single dominant headline, no nav, no CTA buttons
52
+ - **Section divider** — short anchor headline, optional eyebrow
53
+ - **Content** — copy + single supporting visual (60/40 or 50/50 split)
54
+ - **Statistic** — one oversized number, one short caption
55
+ - **Closing** — final thesis line, footer/page-number strip
56
+
57
+ For each layout, describe the dominant rhythm in 1-3 bullets — what scale
58
+ carries the slide, what's allowed in the corners, what's NOT allowed.
59
+
60
+ ## Signature Motifs
61
+ Two-to-five small visual elements that make the deck recognizably this brand.
62
+ Examples: a colored underline, a strike-through wordmark, a dot cluster,
63
+ a serif italic accent on one word per slide. Each motif MUST be reproducible
64
+ purely with inline HTML + CSS on a single slide.
65
+
66
+ ## Avoid
67
+ Explicit list of web-only patterns the slides MUST NOT carry. ALWAYS include:
68
+ - top-nav bars, sticky headers, menu rows
69
+ - clickable CTA buttons ("Sign up", "Start free trial", "Read docs")
70
+ - multi-column footer-bands beyond a single thin strip with attribution + page number
71
+ - pricing tier grids
72
+ - hover/focus/active state styling
73
+ - atmospheric multi-stop gradients (unless the source spec mandates them)
74
+ Plus any AVOID rules carried over from the source DESIGN.md.
75
+
76
+ ## Source mapping (for traceability)
77
+ A short bullet list showing how each web concept was mapped. Format:
78
+ - `<web concept from DESIGN.md>` → `<slide concept in DESIGN.slides.md>` OR `dropped`
79
+ ```
80
+
81
+ ## Web → slide mapping rules
82
+
83
+ Apply these mappings while converting. The left column is what DESIGN.md
84
+ contains; the right column is the slide-appropriate replacement.
85
+
86
+ | DESIGN.md (web) | DESIGN.slides.md (slide) |
87
+ |---|---|
88
+ | `top-nav` / sticky header | A 12pt-tall mono **eyebrow strip** at the top of each slide with section number + brand wordmark — never a horizontal menu of items |
89
+ | `hero-band` (h1 + sub + dual CTA + illustration card) | **Cover layout** — single oversized headline, single sub, footer strip with page number. CTA buttons → discarded (no clicks possible). Illustration card → optional single visual anchor |
90
+ | `feature-card grid (3-up / 4-up)` | **Content layout** with 3-up grid OK, but cards must be cardless-leaning (whitespace-driven) — drop the marketing icon + blurb pattern, prefer pull quotes or per-track/per-member rows |
91
+ | `pricing tier grid` | **Discard entirely** — pricing has no slide analogue |
92
+ | `connector tile grid` | **Discard or convert to small badge row** — never a 4×4 grid of generic logos |
93
+ | `CTA banner` (full-bleed coral / brand) | **Section divider** or **closing** layout — keep the full-bleed color, replace CTA buttons with a thesis sentence and a page number |
94
+ | `product-mockup-card-dark` (code editor screenshot card) | **Content motif** — fine to keep as a single dark surface inside a content slide, but it can NOT dominate every slide |
95
+ | `footer-band` (4-column legal/sitemap) | **Single thin footer strip** — at most 1 line: brand wordmark left, page number right |
96
+ | `button-primary` / `button-secondary` | **Kicker text only** — write the verb as plain text ("Read the next issue") without box/border/click affordance |
97
+ | Hover / focus / pressed / disabled states | **Drop all of them** — slides are static |
98
+ | Multi-stop atmospheric gradients | **Drop unless source spec calls for one or two** — convert to a single accent shape |
99
+ | Spike-mark / asterisk-style brand glyph | **Keep as a small motif** — inline SVG at the slide eyebrow or footer |
100
+
101
+ ## Preservation rules (do NOT translate away)
102
+
103
+ The conversion MUST carry over from DESIGN.md unchanged:
104
+
105
+ - The **color palette** (canvas, surface, ink, primary accent, secondary accents)
106
+ - The **type pairing** — display face vs body face vs mono face
107
+ - The **mood / atmosphere** — warm-editorial vs dark-product vs pastel-pop is the
108
+ whole reason the user imported this DESIGN.md; the slide deck must still feel
109
+ like the source brand
110
+ - **Brand-specific signature motifs** (spike-mark, hard offset shadow, slab-serif italic
111
+ accent, etc.) — translate the surface, not the identity
112
+
113
+ ## Process checklist for the agent
114
+
115
+ 1. Read `./DESIGN.md` in full.
116
+ 2. Identify which sections are web-only and slot them through the mapping table.
117
+ 3. Identify the design tokens (colors, type, spacing) that survive unchanged.
118
+ 4. Draft `./DESIGN.slides.md` using the Output Contract template.
119
+ 5. Show the user a short summary: 5–10 lines covering kept tokens + dropped
120
+ web sections + new slide layouts inferred.
121
+ 6. Wait for explicit user approval ("looks good" or specific edits) before
122
+ moving to outline / slide generation.
123
+ 7. Once approved, record `style: ./DESIGN.slides.md` in `slide-outline.md`.
124
+
125
+ ## When DESIGN.slides.md should be re-converted
126
+
127
+ Suggest a re-conversion when:
128
+ - The source `DESIGN.md` is replaced / re-imported with a different brand
129
+ - The user explicitly asks for a different deck flavor (e.g. "more editorial",
130
+ "less code-heavy")
131
+ - A slide deck visibly carries web-only artifacts (nav bars, CTAs, footers
132
+ with link columns) that the current DESIGN.slides.md doesn't forbid
133
+
134
+ A `DESIGN.slides.md` is never regenerated automatically. It is the agent's
135
+ job, in conversation with the user.
@@ -0,0 +1,47 @@
1
+ # slides-grab Plan Reference
2
+
3
+ Use this bundled reference when planning a new deck.
4
+
5
+ ## Stage boundary
6
+ - Planning stops at an approved `slide-outline.md`.
7
+ - Do not generate `slide-*.html` in this stage.
8
+ - Do not start design until the user explicitly approves the outline.
9
+
10
+ ## Expected `slide-outline.md` shape
11
+
12
+ ```markdown
13
+ # [Presentation Title]
14
+
15
+ ## Meta
16
+ - **Topic**: ...
17
+ - **Target Audience**: ...
18
+ - **Tone/Mood**: ...
19
+ - **Slide Count**: N slides
20
+ - **Aspect Ratio**: 16:9
21
+
22
+ ## Slide Composition
23
+
24
+ ### Slide 1 - Cover
25
+ - **Type**: Cover
26
+ - **Title**: ...
27
+ - **Subtitle**: ...
28
+
29
+ ### Slide 2 - Table of Contents
30
+ - **Type**: Contents
31
+ - **Items**: ...
32
+
33
+ ### Slide 3 - [Title]
34
+ - **Type**: Section Divider / Content / Statistics / Quote / Timeline / ...
35
+ - **Key Message**: ...
36
+ - **Details**:
37
+ - ...
38
+
39
+ ### Slide N - Closing
40
+ - **Type**: Closing
41
+ - **Message**: ...
42
+ ```
43
+
44
+ ## Planning reminders
45
+ - Keep the outline concise and reviewable.
46
+ - Present total slides, slide order, and each slide's role to the user.
47
+ - Revise until explicit approval.
@@ -0,0 +1,140 @@
1
+ # Plan Skill - Presentation Outline Planning
2
+
3
+ A **supervisor skill** that takes a user topic, generates a `slide-outline.md` outline, and manages a revision loop until the user approves.
4
+
5
+ Keeps the outline process separate from slide design. Use a runtime-native subagent/task for drafting when available, or draft directly from this reference when the current runtime has no subagent mechanism.
6
+
7
+ ---
8
+
9
+ ## Role Assignment
10
+
11
+ | Role | Owner | Responsibility |
12
+ |------|-------|----------------|
13
+ | **Supervisor** | plan-skill (you) | User communication, quality control, revision loop management |
14
+ | **Worker** | Outline worker | Draft and revise `slide-outline.md` |
15
+
16
+ ---
17
+
18
+ ## Input
19
+
20
+ - User topic (required)
21
+ - Research results (optional)
22
+ - Reference materials, tone/mood requests, etc.
23
+
24
+ ## Output
25
+
26
+ - User-approved `slide-outline.md`
27
+
28
+ ---
29
+
30
+ ## Workflow
31
+
32
+ ### 1. Create the Outline Draft
33
+
34
+ Use a runtime-native task/subagent to generate a `slide-outline.md` draft when available. If the runtime has no such mechanism, write the draft directly using the format below.
35
+
36
+ **Include in the prompt:**
37
+ - User topic and requirements
38
+ - Research results (if available)
39
+ - Tone/mood requests
40
+ - Expected format for `slide-outline.md` (see format below)
41
+
42
+ ### 2. Present Outline to User
43
+
44
+ Read the generated `slide-outline.md` and present to the user:
45
+
46
+ - Total number of slides
47
+ - Slide order and each slide's role
48
+ - Key message summary
49
+ - Design tone/mood
50
+
51
+ ### 3. Feedback Revision Loop
52
+
53
+ When user provides feedback:
54
+ 1. Organize the feedback
55
+ 2. Revise the existing `slide-outline.md` with the feedback, using a runtime-native task/subagent when available
56
+ 3. Present the revised outline to the user
57
+ 4. Repeat until user approves
58
+
59
+ ### 4. Approval Confirmation
60
+
61
+ Complete the outline stage when the user explicitly approves.
62
+
63
+ ---
64
+
65
+ ## Absolute Rules
66
+
67
+ 1. **Never proceed to the next stage without approval** — Maintain the revision loop until the user explicitly signals approval ("looks good", "approved", "OK", "proceed", etc.).
68
+ 2. **Keep the outline stage separate** — Do not generate slide HTML while drafting or revising the outline.
69
+ 3. **Never start HTML generation** — This skill's scope ends at `slide-outline.md` approval. HTML generation is the responsibility of `design-skill`.
70
+
71
+ ---
72
+
73
+ ## Expected slide-outline.md Format
74
+
75
+ ```markdown
76
+ # [Presentation Title]
77
+
78
+ ## Meta
79
+ - **Topic**: ...
80
+ - **Target Audience**: ...
81
+ - **Tone/Mood**: ...
82
+ - **Slide Count**: N slides
83
+ - **Aspect Ratio**: 16:9
84
+
85
+ ## Slide Composition
86
+
87
+ ### Slide 1 - Cover
88
+ - **Type**: Cover
89
+ - **Title**: ...
90
+ - **Subtitle**: ...
91
+
92
+ ### Slide 2 - Table of Contents
93
+ - **Type**: Contents
94
+ - **Items**: ...
95
+
96
+ ### Slide 3 - [Title]
97
+ - **Type**: Section Divider / Content / Statistics / Quote / Timeline / ...
98
+ - **Key Message**: ...
99
+ - **Details**:
100
+ - ...
101
+ - ...
102
+
103
+ ...
104
+
105
+ ### Slide N - Closing
106
+ - **Type**: Closing
107
+ - **Message**: ...
108
+ ```
109
+
110
+ ---
111
+
112
+ ## Outline Worker Prompt Examples
113
+
114
+ ```
115
+ Runtime-native task/subagent prompt:
116
+
117
+ ```text
118
+ Create a presentation outline for the following topic.
119
+
120
+ Topic: [user topic]
121
+ Requirements: [user requirements]
122
+ Research results: [if available]
123
+
124
+ Save as slide-outline.md.
125
+ [include expected format]
126
+ ```
127
+
128
+ For feedback revisions:
129
+
130
+ ```
131
+ Runtime-native task/subagent prompt:
132
+
133
+ ```text
134
+ Revise the existing outline.
135
+
136
+ Current outline: [slide-outline.md content]
137
+ User feedback: [feedback content]
138
+
139
+ Save the revised slide-outline.md.
140
+ ```
@@ -0,0 +1,182 @@
1
+ import { mkdir, readFile, readFile as readFileAsync, rm } from 'node:fs/promises';
2
+ import { existsSync } from 'node:fs';
3
+ import { join, isAbsolute } from 'node:path';
4
+ import { tmpdir } from 'node:os';
5
+ import { randomUUID } from 'node:crypto';
6
+
7
+ import {
8
+ createProvider as defaultCreateProvider,
9
+ resolveConfig as defaultResolveConfig,
10
+ } from 'god-tibo-imagen';
11
+
12
+ export const CODEX_DEFAULT_MODEL = 'gpt-5.4';
13
+ export const CODEX_PROVIDER_AUTO = 'auto';
14
+ export const CODEX_PROVIDER_PRIVATE_CODEX = 'private-codex';
15
+ export const CODEX_PROVIDER_CODEX_CLI = 'codex-cli';
16
+
17
+ const ASPECT_RATIO_HINTS = new Map([
18
+ ['16:9', 'wide landscape 16:9 aspect ratio'],
19
+ ['9:16', 'tall portrait 9:16 aspect ratio'],
20
+ ['1:1', 'square 1:1 aspect ratio'],
21
+ ['4:3', '4:3 aspect ratio'],
22
+ ['3:4', 'portrait 3:4 aspect ratio'],
23
+ ['3:2', 'landscape 3:2 aspect ratio'],
24
+ ['2:3', 'portrait 2:3 aspect ratio'],
25
+ ]);
26
+
27
+ export function injectAspectRatioHint(prompt, aspectRatio) {
28
+ if (typeof prompt !== 'string' || prompt.trim() === '') {
29
+ throw new Error('injectAspectRatioHint: prompt must be a non-empty string.');
30
+ }
31
+ if (!aspectRatio || typeof aspectRatio !== 'string') {
32
+ return prompt;
33
+ }
34
+ const trimmed = aspectRatio.trim();
35
+ const explicit = ASPECT_RATIO_HINTS.get(trimmed);
36
+ if (explicit) {
37
+ return `${prompt} (${explicit})`;
38
+ }
39
+ if (/^\d+(?:\.\d+)?:\d+(?:\.\d+)?$/.test(trimmed)) {
40
+ return `${prompt} (${trimmed} aspect ratio)`;
41
+ }
42
+ return prompt;
43
+ }
44
+
45
+ export function resolveCodexConfig({ providerMode = CODEX_PROVIDER_AUTO, resolveConfigImpl = defaultResolveConfig } = {}) {
46
+ return resolveConfigImpl({ provider: providerMode });
47
+ }
48
+
49
+ function isCodexAuthError(error) {
50
+ if (!error || typeof error !== 'object') return false;
51
+ const code = String(error.code || '').toUpperCase();
52
+ if (code === 'UNAUTHORIZED' || code === 'ENOENT') return true;
53
+ const message = String(error.message || '').toLowerCase();
54
+ return (
55
+ message.includes('auth.json') ||
56
+ message.includes('unauthorized') ||
57
+ message.includes('chatgpt auth') ||
58
+ message.includes('codex login')
59
+ );
60
+ }
61
+
62
+ export function getCodexFallbackMessage(reason) {
63
+ const summary = typeof reason === 'string' && reason.trim()
64
+ ? reason.trim()
65
+ : 'codex-imagen image generation failed.';
66
+ return `${summary} codex-imagen is the default image provider and reuses your local Codex ChatGPT login (~/.codex/auth.json). Run \`codex login\` once to enable it. Optional fallbacks: set OPENAI_API_KEY (OpenAI gpt-image-2) or GOOGLE_API_KEY/GEMINI_API_KEY (Nano Banana). If image generation credentials are unavailable, use web search and download the chosen image into ./assets/<file>.`;
67
+ }
68
+
69
+ const MIME_BY_EXTENSION = {
70
+ '.png': 'image/png',
71
+ '.jpg': 'image/jpeg',
72
+ '.jpeg': 'image/jpeg',
73
+ '.webp': 'image/webp',
74
+ '.gif': 'image/gif',
75
+ };
76
+
77
+ /**
78
+ * Read reference image file paths into data URLs suitable for the Codex
79
+ * /responses input_image blocks. Accepts absolute paths or paths relative
80
+ * to process.cwd(). Already-formed data: URLs and http(s) URLs are passed
81
+ * through as-is.
82
+ */
83
+ export async function resolveReferenceImages(paths) {
84
+ const list = Array.isArray(paths) ? paths : [];
85
+ const dataUrls = [];
86
+ for (const entry of list) {
87
+ if (typeof entry !== 'string' || !entry.trim()) continue;
88
+ const value = entry.trim();
89
+ if (value.startsWith('data:') || value.startsWith('http://') || value.startsWith('https://')) {
90
+ dataUrls.push(value);
91
+ continue;
92
+ }
93
+ const resolved = isAbsolute(value) ? value : join(process.cwd(), value);
94
+ if (!existsSync(resolved)) {
95
+ throw new Error(`Reference image not found: ${value} (resolved ${resolved})`);
96
+ }
97
+ const ext = resolved.toLowerCase().match(/\.(png|jpe?g|webp|gif)$/);
98
+ const mime = ext ? MIME_BY_EXTENSION[`.${ext[1]}`] : 'image/png';
99
+ const bytes = await readFileAsync(resolved);
100
+ const base64 = bytes.toString('base64');
101
+ dataUrls.push(`data:${mime};base64,${base64}`);
102
+ }
103
+ return dataUrls;
104
+ }
105
+
106
+ export async function generateCodexImage({
107
+ prompt,
108
+ model = CODEX_DEFAULT_MODEL,
109
+ aspectRatio,
110
+ providerMode = CODEX_PROVIDER_AUTO,
111
+ dryRun = false,
112
+ referenceImages = [],
113
+ deps = {},
114
+ } = {}) {
115
+ if (typeof prompt !== 'string' || prompt.trim() === '') {
116
+ throw new Error('generateCodexImage: prompt must be a non-empty string.');
117
+ }
118
+
119
+ const createProviderImpl = deps.createProvider || defaultCreateProvider;
120
+ const resolveConfigImpl = deps.resolveConfig || defaultResolveConfig;
121
+
122
+ const enrichedPrompt = injectAspectRatioHint(prompt, aspectRatio);
123
+ const config = resolveCodexConfig({ providerMode, resolveConfigImpl });
124
+ const provider = createProviderImpl(config);
125
+
126
+ // Reference images are read into data URLs so the codex provider can
127
+ // pass them as input_image blocks in the Codex /responses request.
128
+ // buildResponsesRequest already accepts an images: string[] array of
129
+ // data URLs / URLs — we just need to surface them here.
130
+ const images = await resolveReferenceImages(referenceImages);
131
+
132
+ // codex's provider.generateImage writes a PNG to outputPath as a side
133
+ // effect. slides-grab centralizes asset path resolution in
134
+ // saveNanoBananaImage (src/nano-banana.js) - so we route codex's write
135
+ // to a tmp file and read the bytes back, letting the caller persist via
136
+ // the existing asset contract. This keeps the asset path policy single-sourced.
137
+ const tempDir = join(tmpdir(), `slides-grab-codex-${randomUUID()}`);
138
+ await mkdir(tempDir, { recursive: true });
139
+ const tempPath = join(tempDir, 'image.png');
140
+
141
+ try {
142
+ const result = await provider.generateImage({
143
+ prompt: enrichedPrompt,
144
+ model,
145
+ outputPath: tempPath,
146
+ dryRun: Boolean(dryRun),
147
+ images: images.length > 0 ? images : undefined,
148
+ });
149
+
150
+ if (dryRun) {
151
+ return {
152
+ mimeType: 'image/png',
153
+ bytes: Buffer.alloc(0),
154
+ mode: result?.mode || 'dry-run',
155
+ warnings: Array.isArray(result?.warnings) ? result.warnings : [],
156
+ revisedPrompt: result?.revisedPrompt ?? null,
157
+ };
158
+ }
159
+
160
+ const bytes = await readFile(tempPath);
161
+ return {
162
+ mimeType: 'image/png',
163
+ bytes,
164
+ mode: result?.mode || 'live',
165
+ warnings: Array.isArray(result?.warnings) ? result.warnings : [],
166
+ revisedPrompt: result?.revisedPrompt ?? null,
167
+ };
168
+ } catch (error) {
169
+ const wrapped = new Error(getCodexFallbackMessage(error?.message || String(error)));
170
+ wrapped.cause = error;
171
+ wrapped.isAuthError = isCodexAuthError(error);
172
+ throw wrapped;
173
+ } finally {
174
+ await rm(tempDir, { recursive: true, force: true }).catch(() => {});
175
+ }
176
+ }
177
+
178
+ export const __test_only__ = {
179
+ ASPECT_RATIO_HINTS,
180
+ isCodexAuthError,
181
+ resolveReferenceImages,
182
+ };