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
32 changes: 32 additions & 0 deletions .skillware.yaml.example
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,35 @@ legacy:
# task_id: host.task_id
# current_token_count: host.current_token_count
# max_allowed_tokens: host.max_allowed_tokens
# deck_build_pipeline:
# description: Validate, lint, and render a deck_spec from host variables.
# when: Automated pipeline generating and quality-checking presentations.
# steps:
# - id: validate
# skill: creative/deck_builder
# params:
# action: validate_spec
# strict: true
# input_from:
# deck_spec: host.deck_spec
# - id: lint
# skill: creative/deck_builder
# when:
# prior_step: validate
# field: valid
# equals: true
# params:
# action: lint_deck
# min_score: 70
# input_from:
# deck_spec: host.deck_spec
# - skill: creative/deck_builder
# when:
# prior_step: lint
# field: passed
# equals: true
# params:
# action: render
# input_from:
# deck_spec: host.deck_spec
# output_path: host.output_path
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ Contributors add user-facing entries under `[Unreleased]` in the same PR. Mainta
- **Core:** `SkillLoader.to_bedrock_tool()` for AWS Bedrock Converse tool-use API — maps manifest parameters to `toolSpec` / `inputSchema.json` (#262).
- **Docs:** Enterprise cloud usage guides — [enterprise_cloud.md](docs/usage/enterprise_cloud.md) (hosting + adapter routing), [bedrock.md](docs/usage/bedrock.md), [azure_openai.md](docs/usage/azure_openai.md), [vertex.md](docs/usage/vertex.md) (#262).
- **Examples:** [`bedrock_tos_evaluator.py`](examples/bedrock_tos_evaluator.py) — Bedrock Converse loop with `to_bedrock_tool()` (#262).
- **Skill (`creative/deck_builder` v0.2.0):** Enterprise presentation platform baseline — procedural Pillow placeholders, image fit policies, layouts (`timeline`, `metrics`, `comparison`), `lint_deck` quality gates, `suggest_outline` archetypes, governance ribbons/footers, and [`deck_builder_chain_demo.py`](examples/deck_builder_chain_demo.py) (#336, #337).
- **Examples:** [`deck_builder_chain_demo.py`](examples/deck_builder_chain_demo.py) — `suggest_outline` → `bg_remover` → `lint_deck` → `render` via `SkillContext` (#337).

### Changed

Expand Down
2 changes: 1 addition & 1 deletion docs/skills/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Skills for image processing, media editing, and creative utilities.
| Skill | ID | Version | Issuer | Description |
| :--- | :--- | :--- | :--- | :--- |
| **[Background Remover](bg_remover.md)** | `creative/bg_remover` | `0.2.0` (2 Aug 2026) | [@AyushSrivastava1818](https://github.com/AyushSrivastava1818) ([@ARPAHLS](https://github.com/ARPAHLS)) | Removes image backgrounds locally using rembg and returns transparent PNGs. |
| **[Deck Builder](deck_builder.md)** | `creative/deck_builder` | `0.1.0` (3 Sep 2026) | [@tusharjamunkar](https://github.com/tusharjamunkar) ([@ARPAHLS](https://github.com/ARPAHLS)) | Deterministic PowerPoint (.pptx) presentation assembly from structured JSON deck specs. |
| **[Deck Builder](deck_builder.md)** | `creative/deck_builder` | `0.2.0` (16 Sep 2026) | [@tusharjamunkar](https://github.com/tusharjamunkar) ([@ARPAHLS](https://github.com/ARPAHLS)) | Offline PPTX assembly from JSON deck specs — placeholders, lint_deck, suggest_outline, and 13 layouts. |

## Finance
Tools for financial analysis, blockchain interaction, and regulatory compliance.
Expand Down
66 changes: 39 additions & 27 deletions docs/skills/deck_builder.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,26 @@
**ID**: `creative/deck_builder`
**Issuer**: [@tusharjamunkar](https://github.com/tusharjamunkar) ([@ARPAHLS](https://github.com/ARPAHLS))
<!-- skill-doc-meta:begin -->
**Version**: `0.1.0`
**Version**: `0.2.0` — 16 Sep 2026
<!-- skill-doc-meta:end -->

**Recommended install:** `pip install "skillware[creative_deck_builder]"`. See [Install extras](../usage/install_extras.md).
**Category**: Creative

[Skill Library](README.md) · [Testing](../TESTING.md)

Deterministic, offline assembly of Microsoft PowerPoint (`.pptx`) presentations from structured JSON deck specifications. Supports multi-slide layouts (title, section, bullets, two-column, image, image with caption, quote, table, chart, blank), custom theme token overrides, speaker notes, and pre-flight validation.
Deterministic, offline assembly of Microsoft PowerPoint (`.pptx`) presentations from structured JSON deck specifications. Supports 13 slide layouts (title, section, bullets, two-column, image, image with caption, quote, table, chart, timeline, metrics, comparison, blank), smart image placeholders, `fit` policies, presentation quality linting (`lint_deck`), archetype outline generation (`suggest_outline`), custom theme token overrides, speaker notes, and pre-flight validation.

## Capabilities

- **Deterministic Assembly**: Generates standard editable `.pptx` documents without remote network calls or image generation APIs.
- **10 Layout Types**: Supports cover titles, section headers, bullet lists, two-column comparisons, images, image captions, pull-quotes, tables, native OpenXML charts (bar, line, pie), and blank canvases.
- **13 Layout Types**: Supports cover titles, section headers, bullet lists, two-column comparisons, images, image captions, pull-quotes, tables, native OpenXML charts (bar, line, pie), milestone timelines, KPI metric cards, comparative matrices, and blank canvases.
- **Smart Image Engine & Placeholders**: Normalizes images via Pillow (EXIF orientation, CMYK to RGB) with configurable `fit` policies (`contain`, `cover`, `crop_center`, `stretch`) and neutral offline placeholders (`hero`, `logo`, `icon`, `chart_backdrop`, `headshot`).
- **Quality Gates (`lint_deck`)**: Heuristic deck scoring (0–100) assessing bullet density, text length caps, image alt tags, orphan bullets, and visual monotony.
- **Archetype Outlines (`suggest_outline`)**: Offline template outline generator for `investor_pitch`, `technical_brief`, `quarterly_review`, `product_launch`, and `training_workshop`.
- **Pre-flight Validation (`validate_spec`)**: Validates JSON specifications against strict JSON Schema and flags soft-limit warnings (e.g. text truncations, missing assets) before writing to disk.
- **Widescreen 16:9 Templates**: Bundles 3 distinct master templates (`pitch_v1`, `corporate_v1`, `minimal_v1`) with configurable font and accent color tokens.
- **Inspection (`inspect`)**: Examines existing `.pptx` files and extracts slide counts, layout hints, titles, and speaker notes presence.
- **Asset Normalization**: Ingests local file paths or Base64 image payloads with Pillow validation and directory traversal defenses.

## Actions

Expand All @@ -30,6 +32,8 @@ Deterministic, offline assembly of Microsoft PowerPoint (`.pptx`) presentations
| `render` | `deck_spec`, `output_path`, `template_id` *(optional)*, `theme` *(optional)*, `strict` *(optional)* | Assembles slides, applies theme tokens, inserts images/charts, writes `.pptx` to disk. |
| `inspect` | `input_path` | Reads an existing `.pptx` presentation and returns slide counts, titles, layout names, and notes presence. |
| `list_templates` | *(none)* | Enumerates bundled template IDs, names, descriptions, and aspect ratios. |
| `lint_deck` | `deck_spec`, `min_score` *(optional)*, `strict_a11y` *(optional)* | Analyzes deck specification for presentation design and accessibility best practices. |
| `suggest_outline` | `archetype`, `topic` *(optional)*, `constraints` *(optional)* | Generates a structured slide outline and skeleton `deck_spec` for an archetype. |

## Slide Layouts

Expand All @@ -39,11 +43,14 @@ Deterministic, offline assembly of Microsoft PowerPoint (`.pptx`) presentations
| `section` | Section divider | `title`, optional `subtitle`, optional `speaker_notes` |
| `bullets` | Bulleted takeaways | `title`, `bullets` (array of strings; >120 chars emits warning), `speaker_notes` |
| `two_column` | Comparison / two-panel layout | `title`, `left` (text/bullets), `right` (text/bullets), `speaker_notes` |
| `image` | Visual showcase | `title`, `image` (path or base64), optional `caption`, `speaker_notes` |
| `image` | Visual showcase | `title`, `image` (path, base64, or placeholder_id), optional `caption`, `speaker_notes` |
| `image_caption` | Image with side text | `title`, `image`, `body` (explanatory text), `speaker_notes` |
| `quote` | Pull quote | `quote`, `attribution`, `speaker_notes` |
| `table` | Tabular data grid | `title`, `columns`, `rows`, `speaker_notes` |
| `chart` | Data visualization | `title`, `chart` (`kind`: `bar`/`line`/`pie`, `categories`, `series`), `speaker_notes` |
| `timeline` | Milestone roadmap | `title`, `items` (array of `{date, title, description, status}`), `speaker_notes` |
| `metrics` | KPI big numbers | `title`, `metrics` (array of `{value, label, delta, trend}`), `speaker_notes` |
| `comparison` | Comparative cards | `title`, `left`, `right` (or `columns`), `speaker_notes` |
| `blank` | Clean canvas | optional `speaker_notes` |

## Usage Examples
Expand Down Expand Up @@ -218,39 +225,43 @@ print(json.dumps(result, indent=2))

### Skill Chaining (with `creative/bg_remover`)

Compose with other skills using host orchestration or `SkillContext` (see [Skill chaining](../usage/skill_chaining.md)). For example, remove backgrounds from brand logos or product photos with [`creative/bg_remover`](bg_remover.md) before passing the transparent PNG into `creative/deck_builder`:
Compose with other skills using host orchestration or `SkillContext` (see [Skill chaining](../usage/skill_chaining.md)). For example, bootstrap an archetype outline, remove backgrounds from brand logos with [`creative/bg_remover`](bg_remover.md), evaluate deck quality gates (`lint_deck`), and assemble the final presentation (see full runnable script in [`examples/deck_builder_chain_demo.py`](../../examples/deck_builder_chain_demo.py)):

```python
from skillware import SkillContext

ctx = SkillContext(skills=["creative/bg_remover", "creative/deck_builder"])

# Step 1: Strip background from raw logo or product image
bg_res = ctx.execute("creative/bg_remover", {"input_path": "assets/raw_logo.jpg"})

# Step 2: Assemble presentation using the transparent PNG
deck_spec = {
"title": "Product Launch",
"template_id": "pitch_v1",
"slides": [
{
"type": "title",
"title": "Autonomous Infrastructure",
"subtitle": "Q4 Executive Review",
"image": {"base64": bg_res["image_base64"], "mime_type": "image/png"},
},
{
"type": "bullets",
"title": "Highlights",
"bullets": ["100% offline assembly", "Deterministic slide layout"],
},
],
# Step 1: Suggest outline via archetype
outline = ctx.execute(
"creative/deck_builder",
{
"action": "suggest_outline",
"archetype": "product_launch",
"topic": "Skillware Autonomous Runtime",
"constraints": ["no pricing"],
},
)
deck_spec = outline["deck_spec_skeleton"]

# Step 2: Strip background from brand mark
bg_res = ctx.execute("creative/bg_remover", {"input_path": "assets/raw_logo.png"})
deck_spec["slides"][0]["image"] = {
"base64": bg_res["image_base64"],
"mime_type": "image/png",
"fit": "contain",
}

# Step 3: Run presentation quality linting
lint_res = ctx.execute("creative/deck_builder", {"action": "lint_deck", "deck_spec": deck_spec, "min_score": 80})
assert lint_res["passed"] is True, f"Quality gate failed: score={lint_res['score']}"

# Step 4: Render final presentation
render_res = ctx.execute(
"creative/deck_builder",
{"action": "render", "deck_spec": deck_spec, "output_path": "launch_deck.pptx"},
)
print("Rendered:", render_res["output_path"], "with", render_res["slide_count"], "slides")
print("Rendered:", render_res["output_path"], "with", render_res["slide_count"], "slides (score:", lint_res["score"], ")")
```

---
Expand All @@ -262,6 +273,7 @@ Commits that touched this skill bundle or its catalog page ([`creative/deck_buil

| Commit | Description | Date | Version | Contributors |
| :--- | :--- | :--- | :--- | :--- |
| _#337_ | feat(creative): deck_builder v0.2.0 baseline — placeholders, quality linting, archetypes, and new layouts (#336) | 16 Sep 2026 | `0.2.0` | [@tusharjamunkar](https://github.com/tusharjamunkar) |
| [`790787d`](https://github.com/ARPAHLS/skillware/commit/790787d0e72262ddfeb26f747f880012ca2b1ca6) | docs: five-provider Usage Examples guard and catalog loop backfill (#347) | 10 Sep 2026 | `0.1.0` | [@rosspeili](https://github.com/rosspeili) |
| [`1903f30`](https://github.com/ARPAHLS/skillware/commit/1903f30f32bd75567270058f3b255452d8bddd97) | feat(creative): add deck_builder skill for deterministic PPTX assembly (#276) (#331) | 4 Sep 2026 | `0.1.0` | [@tusharjamunkar](https://github.com/tusharjamunkar) |
<!-- skill-history:end -->
Expand Down
2 changes: 1 addition & 1 deletion docs/usage/agent_loops.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ skills in one harness.
| `security/prompt_injection_firewall` | `prompt_injection_firewall_demo.py`, `sanitize_input_chain_demo.py` (local execute) | (catalog page) | (catalog page) | (catalog page) | (catalog page) | (catalog page) |
| `security/deceptive_ui_guard` | `deceptive_ui_guard_demo.py` (local execute) | (catalog page) | (catalog page) | (catalog page) | (catalog page) | (catalog page) |
| `creative/bg_remover` | `bg_remover_demo.py` (local execute) | (catalog page) | (catalog page) | (catalog page) | (catalog page) | (catalog page) |
| `creative/deck_builder` | `deck_builder_demo.py` (local execute) | (catalog page) | (catalog page) | (catalog page) | (catalog page) | (catalog page) |
| `creative/deck_builder` | `deck_builder_demo.py`, `deck_builder_chain_demo.py` (local execute) | (catalog page) | (catalog page) | (catalog page) | (catalog page) | (catalog page) |
| `optimization/prompt_rewriter` | `prompt_compression_demo.py`, `sanitize_input_chain_demo.py` (local execute) | (catalog page) | (catalog page) | (catalog page) | (catalog page) | `ollama_skills_test.py` (multi-skill) |
| `data_engineering/synthetic_generator` | `build_dataset_demo.py` (local execute, Gemini backend) | (catalog page) | (catalog page) | (catalog page) | (catalog page) | (catalog page) |
| `data_engineering/novelty_extractor` | `novelty_extractor_demo.py` (local execute) | `gemini_novelty_extractor.py` | (catalog page) | (catalog page) | (catalog page) | `ollama_novelty_extractor.py` |
Expand Down
1 change: 1 addition & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ pip install -e ".[dev,all,agents]"
| `uk_companies_house_handler_demo.py` | `finance/uk_companies_house_handler` | Local execute | `[finance_uk_companies_house_handler]` | None | Mocked v1.2.1 flows: composite, turn-by-turn run_pipeline, disambiguation resume, record truncation limits. |
| `bg_remover_demo.py` | `creative/bg_remover` | Local execute | `[creative_bg_remover]` | None | Demonstrates offline background removal from a local image and optionally writes a transparent PNG. |
| `deck_builder_demo.py` | `creative/deck_builder` | Local execute | `[creative_deck_builder]` | None | Demonstrates offline presentation assembly from JSON deck specs with charts, tables, bullets, and speaker notes. |
| `deck_builder_chain_demo.py` | `creative/bg_remover`, `creative/deck_builder` | Local execute | `[creative_bg_remover]`, `[creative_deck_builder]` | None | Demonstrates SkillContext chaining for outline suggestion, transparent logo generation, deck linting, and final rendering. |
| `semantic_web_proxy_demo.py` | `data_engineering/semantic_web_proxy` | Local execute | `[data_engineering_semantic_web_proxy]` | None | Demonstrates offline boilerplate stripping, opt-in comments, the JavaScript-render warning, and the SSRF guard using bundled fixture HTML. |
| `gmail_handler_demo.py` | `office/gmail_handler` | Local execute | `[office_gmail_handler]` | None | Mocked resolve, preview/send gate, search, and read flow (no Gmail credentials). |
| `gmail_signature_test_send.py` | `office/gmail_handler` | Local execute | `[office_gmail_handler]` | `GMAIL_ADDRESS`, `GMAIL_APP_PASSWORD`; run `skillware mail signature init` first | Preview or send one test message to verify plain + HTML signature. |
Expand Down
100 changes: 100 additions & 0 deletions examples/deck_builder_chain_demo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
"""Chain execution demo for creative/bg_remover and creative/deck_builder.

Demonstrates host orchestration via SkillContext:
1. Suggest deck outline via archetype (creative/deck_builder)
2. Remove background from raw brand mark to produce transparent PNG (creative/bg_remover)
3. Quality lint the presentation specification (creative/deck_builder)
4. Render the final presentation to an editable .pptx (creative/deck_builder)
Runs entirely offline without remote API keys.
"""

from pathlib import Path
import tempfile
from PIL import Image
import io
import base64

from skillware import SkillContext


def run_demo():
print("Loading SkillContext with creative/bg_remover and creative/deck_builder...")
ctx = SkillContext(skills=["creative/bg_remover", "creative/deck_builder"])

# Step 1: Suggest outline via archetype
print("\n=== Step 1: Suggest Outline via Archetype ===")
outline_res = ctx.execute(
"creative/deck_builder",
{
"action": "suggest_outline",
"archetype": "product_launch",
"topic": "Skillware Autonomous Runtime",
"constraints": ["no pricing"],
},
)
print(f" archetype: {outline_res.get('archetype')}")
print(f" recommended_slides: {outline_res.get('recommended_slide_count')}")
deck_spec = outline_res["deck_spec_skeleton"]

# Step 2: Background removal on brand mark
print("\n=== Step 2: Background Removal on Brand Mark ===")
sample_img_path = Path("examples/sample_input.png")
if sample_img_path.exists():
bg_res = ctx.execute(
"creative/bg_remover", {"input_path": str(sample_img_path)}
)
transparent_logo_b64 = bg_res.get("image_base64")
print(
f" bg_remover processed {sample_img_path}: success={bg_res.get('success')}"
)
else:
print(" sample_input.png not present; using synthetic transparent brand asset")
logo_img = Image.new("RGBA", (120, 120), color=(110, 87, 224, 255))
buf = io.BytesIO()
logo_img.save(buf, format="PNG")
transparent_logo_b64 = base64.b64encode(buf.getvalue()).decode("utf-8")
print(f" transparent_logo length: {len(transparent_logo_b64)} chars")

# Embed transparent logo into cover slide
deck_spec["slides"][0]["image"] = {
"base64": transparent_logo_b64,
"mime_type": "image/png",
"fit": "contain",
}

# Step 3: Lint deck specification
print("\n=== Step 3: Lint Deck Specification ===")
lint_res = ctx.execute(
"creative/deck_builder",
{
"action": "lint_deck",
"deck_spec": deck_spec,
"min_score": 70,
},
)
print(f" lint_score: {lint_res.get('score')}/100")
print(f" passed: {lint_res.get('passed')}")
print(f" findings_count: {lint_res.get('findings_count')}")

# Step 4: Render final presentation
print("\n=== Step 4: Render Final Presentation ===")
with tempfile.TemporaryDirectory() as tmp_dir:
output_pptx = Path(tmp_dir) / "skillware_launch.pptx"
render_res = ctx.execute(
"creative/deck_builder",
{
"action": "render",
"deck_spec": deck_spec,
"output_path": str(output_pptx),
},
)
print(f" render success: {render_res.get('success')}")
print(f" output_path: {render_res.get('output_path')}")
print(f" file_size_bytes: {render_res.get('file_size_bytes')}")
print(f" rendered_slides: {len(render_res.get('slides', []))}")

print("\nChain demo complete.")


if __name__ == "__main__":
run_demo()
Loading
Loading