Skip to content

Commit 80d13fc

Browse files
committed
updated plugin
1 parent d1b85a3 commit 80d13fc

File tree

5 files changed

+221
-11
lines changed

5 files changed

+221
-11
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ swift test
4141

4242
```bash
4343
osaurus manifest extract .build/release/libosaurus-pptx.dylib
44-
osaurus tools package dev.osaurus.pptx 0.1.0
45-
osaurus tools install ./dev.osaurus.pptx-0.1.0.zip
44+
osaurus tools package osaurus.pptx 0.1.0
45+
osaurus tools install ./osaurus.pptx-0.1.0.zip
4646
```
4747

4848
## Publishing

SKILL.md

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
# Osaurus PPTX — Agent Skill Guide
2+
3+
Use this guide when creating PowerPoint presentations with the Osaurus PPTX plugin.
4+
5+
## Overview
6+
7+
This plugin **creates** PowerPoint (.pptx) presentations from scratch. It is not a full round-trip editor — treat every presentation as a fresh build.
8+
9+
## Workflow
10+
11+
Always follow this sequence:
12+
13+
1. **create_presentation** — get a `presentation_id`, slide dimensions, and theme info
14+
2. **add_slide** (repeat) — add slides one at a time; each returns a `slide_number`
15+
3. **add_text / add_image / add_shape / add_table / add_chart / set_slide_background** — populate each slide with elements
16+
4. **save_presentation** — write the final `.pptx` file
17+
18+
Never skip steps. You must create slides before adding elements. You must save at the end — nothing is written to disk until `save_presentation`.
19+
20+
## Slide Coordinate System
21+
22+
All positions and sizes are in **inches** measured from the top-left corner of the slide.
23+
24+
### Default slide dimensions (16:9)
25+
26+
- Width: **13.33"**
27+
- Height: **7.5"**
28+
29+
### 4:3 slides
30+
31+
- Width: **10.0"**
32+
- Height: **7.5"**
33+
34+
The `create_presentation` response includes `width_inches` and `height_inches` — use these values for positioning calculations.
35+
36+
### Safe margins
37+
38+
Leave at least **0.5"** on all edges for a clean look. Usable area for 16:9:
39+
- X range: 0.5" to 12.83"
40+
- Y range: 0.5" to 7.0"
41+
42+
## Positioning Recipes
43+
44+
Use these coordinates for common slide layouts on 16:9 slides. Adjust proportionally for other sizes.
45+
46+
### Title Slide
47+
48+
```
49+
Title: x=1.0 y=2.0 w=11.33 h=1.5 font_size=40 bold=true alignment=center
50+
Subtitle: x=1.0 y=4.0 w=11.33 h=1.0 font_size=24 alignment=center
51+
```
52+
53+
### Section Header
54+
55+
```
56+
Heading: x=1.0 y=2.5 w=11.33 h=1.5 font_size=36 bold=true alignment=center
57+
```
58+
59+
### Title + Body Content
60+
61+
```
62+
Title: x=0.75 y=0.5 w=11.83 h=1.0 font_size=32 bold=true
63+
Body: x=0.75 y=1.75 w=11.83 h=5.0 font_size=18 bullets=true
64+
```
65+
66+
### Title + Two Columns
67+
68+
```
69+
Title: x=0.75 y=0.5 w=11.83 h=1.0 font_size=32 bold=true
70+
Left: x=0.75 y=1.75 w=5.67 h=5.0 font_size=16
71+
Right: x=6.67 y=1.75 w=5.67 h=5.0 font_size=16
72+
```
73+
74+
### Title + Table or Chart
75+
76+
```
77+
Title: x=0.75 y=0.5 w=11.83 h=1.0 font_size=32 bold=true
78+
Table: x=0.75 y=1.75 w=11.83 h=5.0
79+
Chart: x=1.5 y=1.75 w=10.33 h=5.0
80+
```
81+
82+
### Title + Image
83+
84+
```
85+
Title: x=0.75 y=0.5 w=11.83 h=1.0 font_size=32 bold=true
86+
Image: x=2.5 y=1.75 w=8.33 h=5.0
87+
```
88+
89+
## Themes
90+
91+
Five built-in themes. Choose at creation time with the `theme` parameter:
92+
93+
| Theme | Style | Best for |
94+
|-------|-------|----------|
95+
| **modern** (default) | Blue/orange, Calibri | General purpose |
96+
| **corporate** | Navy/steel blue, Georgia headings | Business, formal |
97+
| **creative** | Pink/purple, Avenir Next | Marketing, design |
98+
| **minimal** | Grayscale, Helvetica Neue | Clean, text-heavy |
99+
| **dark** | Purple/teal on dark bg, SF Pro | Technical, modern |
100+
101+
Do not hardcode colors when possible — the theme provides defaults for text, headers, table headers, and more. Let the theme do the styling work.
102+
103+
When using the **dark** theme, remember that the background is dark (`121212`). Set slide backgrounds explicitly if needed, and avoid dark text colors on dark slides.
104+
105+
## Tool Tips
106+
107+
### create_presentation
108+
- The `size` parameter controls aspect ratio, not layout. Default is `"16:9"`. Use `"4:3"` for standard or `"WxH"` for custom (e.g., `"10x7.5"`).
109+
110+
### add_slide
111+
- The `layout` parameter is **metadata only**. It does not auto-generate any content. Every slide starts blank regardless of layout type. You must add all elements manually.
112+
113+
### add_text
114+
- Use `\n` in the `text` parameter for line breaks / multiple paragraphs.
115+
- Set `bullets=true` for bullet-pointed lists.
116+
- Hex colors should omit the `#` prefix: use `"FF0000"` not `"#FF0000"`.
117+
- For centered titles, use `alignment: "center"` and `bold: true`.
118+
119+
### add_image
120+
- Paths can be relative to the workspace or absolute.
121+
- Supported formats: PNG, JPG, GIF, SVG, BMP, TIFF.
122+
- This tool requires user permission (`ask` policy).
123+
124+
### add_shape
125+
- 21 shape types available: `rect`, `round_rect`, `ellipse`, `triangle`, `diamond`, `pentagon`, `hexagon`, `octagon`, `star4`, `star5`, `star6`, `right_arrow`, `left_arrow`, `up_arrow`, `down_arrow`, `heart`, `cloud`, `lightning`, `line`, `parallelogram`, `trapezoid`.
126+
- Shapes can contain text via the `text` parameter — useful for labeled diagrams and flowcharts.
127+
128+
### add_table
129+
- `rows` is a 2D array of strings. The first row is the header by default (`has_header: true`).
130+
- Column widths auto-distribute evenly. Use `column_widths` for custom sizing (must match column count).
131+
132+
### add_chart
133+
- Types: `bar`, `column`, `line`, `pie`, `doughnut`.
134+
- Each series needs a `name` and `values` array. Optionally set a `color` per series.
135+
- `categories` are the x-axis labels.
136+
137+
### save_presentation
138+
- Always call this when done. Nothing is persisted until you save.
139+
- The `.pptx` extension is added automatically if missing.
140+
- This tool requires user permission (`ask` policy).
141+
142+
## Limitations
143+
144+
Be aware of these constraints:
145+
146+
1. **Creation-focused.** There are no tools to update or remove individual elements after adding them. If a slide needs correction, use `delete_slide` to remove it, re-add it with `add_slide`, and rebuild its elements.
147+
148+
2. **No element modification.** You cannot change text, reposition elements, or update properties on existing elements. Plan each slide fully before adding elements.
149+
150+
3. **No slide reordering.** Slides are ordered by insertion. Plan the slide sequence in advance.
151+
152+
4. **read_presentation is limited.** Reading an existing `.pptx` only preserves text elements and slide backgrounds. Images, shapes, tables, and charts are not parsed. Use `read_presentation` primarily for inspecting text content, not for full round-trip editing.
153+
154+
5. **One save at the end.** Build the entire presentation in memory, then call `save_presentation` once. You can save multiple times to different paths if needed.
155+
156+
## Strategy for Multi-Slide Presentations
157+
158+
1. Call `create_presentation` once.
159+
2. Plan all slides before building — decide the content and layout for each.
160+
3. Add slides sequentially: `add_slide` then immediately populate with elements before moving to the next slide. This keeps slide numbers predictable.
161+
4. Call `save_presentation` once at the end.
162+
5. If the user wants changes, use `delete_slide` on the affected slide, `add_slide` to re-add at the same position, rebuild its elements, and save again.
163+
164+
## Correction Strategy
165+
166+
Since elements cannot be modified after creation:
167+
168+
- **Wrong text/formatting on a slide:** `delete_slide` the slide, `add_slide` again, re-add all elements with corrections.
169+
- **Wrong slide order:** Unfortunately slides cannot be reordered. Rebuild the presentation if order matters.
170+
- **Want to inspect what was built:** Use `get_presentation_info` with `include_details: true` to see all elements on all slides.
171+
172+
## Example: Building a 3-Slide Presentation
173+
174+
```
175+
1. create_presentation(title="Q4 Report", theme="corporate")
176+
→ get presentation_id, note width=13.33, height=7.5
177+
178+
2. add_slide(presentation_id, layout="title")
179+
→ slide 1
180+
3. add_text(presentation_id, slide_number=1, text="Q4 2025 Report",
181+
x=1.0, y=2.0, width=11.33, height=1.5,
182+
font_size=40, bold=true, alignment="center")
183+
4. add_text(presentation_id, slide_number=1, text="Annual Review",
184+
x=1.0, y=4.0, width=11.33, height=1.0,
185+
font_size=24, alignment="center")
186+
187+
5. add_slide(presentation_id, layout="title_content")
188+
→ slide 2
189+
6. add_text(presentation_id, slide_number=2, text="Key Metrics",
190+
x=0.75, y=0.5, width=11.83, height=1.0,
191+
font_size=32, bold=true)
192+
7. add_chart(presentation_id, slide_number=2, chart_type="column",
193+
categories=["Oct", "Nov", "Dec"],
194+
series=[{name: "Revenue", values: [120, 135, 150]}],
195+
title="Monthly Revenue",
196+
x=1.5, y=1.75, width=10.33, height=5.0)
197+
198+
8. add_slide(presentation_id, layout="blank")
199+
→ slide 3
200+
9. add_text(presentation_id, slide_number=3, text="Thank You",
201+
x=1.0, y=2.5, width=11.33, height=1.5,
202+
font_size=36, bold=true, alignment="center")
203+
204+
10. save_presentation(presentation_id, path="Q4_Report.pptx")
205+
```

Sources/osaurus_pptx/Plugin.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,8 @@ nonisolated(unsafe) private var api: osr_plugin_api = {
7373
api.get_manifest = { ctxPtr in
7474
let manifest = """
7575
{
76-
"plugin_id": "dev.osaurus.pptx",
77-
"name": "Osaurus Presentation",
76+
"plugin_id": "osaurus.pptx",
77+
"name": "Osaurus PPTX",
7878
"version": "0.1.0",
7979
"description": "Create, modify, and export PowerPoint presentations. Supports text, images, shapes, tables, charts, themes, and more.",
8080
"license": "MIT",
@@ -90,7 +90,7 @@ nonisolated(unsafe) private var api: osr_plugin_api = {
9090
"type": "object",
9191
"properties": {
9292
"title": {"type": "string", "description": "Presentation title"},
93-
"layout": {"type": "string", "description": "Slide size: '16:9' (default), '4:3', or 'WxH' in inches (e.g. '10x7.5')"},
93+
"size": {"type": "string", "description": "Slide size: '16:9' (default), '4:3', or 'WxH' in inches (e.g. '10x7.5')"},
9494
"theme": {"type": "string", "description": "Theme preset: modern (default), corporate, creative, minimal, dark"}
9595
},
9696
"required": ["title"]
@@ -100,7 +100,7 @@ nonisolated(unsafe) private var api: osr_plugin_api = {
100100
},
101101
{
102102
"id": "add_slide",
103-
"description": "Add a new slide to a presentation.",
103+
"description": "Add a new slide to a presentation. The layout parameter is metadata only — you must add elements (text, images, shapes, etc.) manually using add_text, add_image, and other tools.",
104104
"parameters": {
105105
"type": "object",
106106
"properties": {

Sources/osaurus_pptx/Tools.swift

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ struct CreatePresentationTool {
4747

4848
struct Args: Decodable {
4949
let title: String
50-
let layout: String? // "16:9", "4:3", or "WxH" in inches
50+
let size: String? // "16:9", "4:3", or "WxH" in inches
5151
let theme: String? // "modern", "corporate", "creative", "minimal", "dark"
5252
let _context: FolderContext?
5353
}
@@ -60,15 +60,15 @@ struct CreatePresentationTool {
6060
}
6161

6262
let slideSize: SlideSize
63-
if let layout = input.layout {
64-
switch layout {
63+
if let size = input.size {
64+
switch size {
6565
case "16:9", "widescreen":
6666
slideSize = .widescreen
6767
case "4:3", "standard":
6868
slideSize = .standard
6969
default:
7070
// Try to parse "WxH" format
71-
let parts = layout.split(separator: "x")
71+
let parts = size.split(separator: "x")
7272
if parts.count == 2,
7373
let w = Double(parts[0]),
7474
let h = Double(parts[1])
@@ -87,11 +87,16 @@ struct CreatePresentationTool {
8787

8888
presentations[pres.id] = pres
8989

90+
let widthInches = Double(pres.slideWidth) / Double(Units.emuPerInch)
91+
let heightInches = Double(pres.slideHeight) / Double(Units.emuPerInch)
92+
9093
return jsonSuccess([
9194
"presentation_id": pres.id,
9295
"title": pres.title,
9396
"theme": theme.name,
9497
"slide_count": 0,
98+
"width_inches": widthInches,
99+
"height_inches": heightInches,
95100
])
96101
}
97102
}

Tests/osaurus_pptx_tests/PresentationTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ struct ToolExecutionTests {
263263
var presentations: [String: Presentation] = [:]
264264
let tool = CreatePresentationTool()
265265
let result = tool.run(
266-
args: "{\"title\": \"Custom\", \"layout\": \"4:3\", \"theme\": \"dark\"}",
266+
args: "{\"title\": \"Custom\", \"size\": \"4:3\", \"theme\": \"dark\"}",
267267
presentations: &presentations)
268268
let json = parseJSON(result)
269269
#expect(json?["theme"] as? String == "Dark")

0 commit comments

Comments
 (0)