File size: 5,671 Bytes
088cdb2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
"""
pptx‑toolkit β€” Create, edit, and extract content from PowerPoint (.pptx) presentations.
============================================================================================

Slide‑level operations: read text, inspect structure, extract speaker notes,
and create presentations from structured content.
"""

from pathlib import Path

try:
    from toolstore.toolset import tool
except ImportError:
    def tool(fn):
        return fn


# ── pptx_read ──────────────────────────────────────────────────────────

@tool
def pptx_read(*, filepath: str) -> dict:
    """Extract all text from a PowerPoint presentation, slide by slide.

    Args:
        filepath: Path to the .pptx file.

    Returns:
        dict with:
          slides β€” list of {index, title, body_text, notes, shape_count}
          count  β€” total number of slides
    """
    try:
        from pptx import Presentation
    except ImportError:
        return {"error": "python-pptx not installed β€” run: pip install python-pptx"}

    p = Path(filepath).expanduser().resolve()
    if not p.exists():
        return {"error": f"File not found: {p}"}

    try:
        prs = Presentation(str(p))
    except Exception as exc:
        return {"error": f"Cannot open presentation: {exc}"}

    slides = []
    for i, slide in enumerate(prs.slides):
        title = ""
        body_parts = []
        notes_text = ""

        for shape in slide.shapes:
            if shape.is_placeholder and shape.placeholder_format.idx == 0:
                title = shape.text_frame.text if shape.has_text_frame else ""
            elif shape.has_text_frame:
                body_parts.append(shape.text_frame.text)
            elif shape.has_table:
                tbl_text = []
                for row in shape.table.rows:
                    tbl_text.append(" | ".join(cell.text for cell in row.cells))
                body_parts.append("\n".join(tbl_text))

        if slide.has_notes_slide:
            notes_text = slide.notes_slide.notes_text_frame.text

        slides.append({
            "index": i + 1,
            "title": title.strip(),
            "body_text": "\n".join(bp for bp in body_parts if bp.strip()),
            "notes": notes_text.strip(),
            "shape_count": len(slide.shapes),
        })

    return {"slides": slides, "count": len(slides)}


# ── pptx_info ──────────────────────────────────────────────────────────

@tool
def pptx_info(*, filepath: str) -> dict:
    """Inspect presentation structure: slide count, layout, dimensions.

    Args:
        filepath: Path to the .pptx file.

    Returns:
        dict with: slides, slide_width, slide_height, layouts, filename
    """
    try:
        from pptx import Presentation
    except ImportError:
        return {"error": "python-pptx not installed β€” run: pip install python-pptx"}

    p = Path(filepath).expanduser().resolve()
    if not p.exists():
        return {"error": f"File not found: {p}"}

    try:
        prs = Presentation(str(p))
    except Exception as exc:
        return {"error": f"Cannot open presentation: {exc}"}

    layouts = [ly.name for ly in prs.slide_layouts]

    return {
        "slides": len(prs.slides),
        "slide_width": prs.slide_width,
        "slide_height": prs.slide_height,
        "layouts": layouts,
        "filename": p.name,
    }


# ── pptx_create ────────────────────────────────────────────────────────

@tool
def pptx_create(*, filepath: str, title: str = "",
                slides_data: list = None) -> dict:
    """Create a new PowerPoint presentation from structured slide data.

    Args:
        filepath:    Where to write the new .pptx file.
        title:       Presentation title (used as first slide).
        slides_data: List of dicts: [{title, bullets: [...]}, ...].

    Returns:
        dict with "written" (absolute path) or "error".
    """
    try:
        from pptx import Presentation
        from pptx.util import Inches, Pt
    except ImportError:
        return {"error": "python-pptx not installed β€” run: pip install python-pptx"}

    p = Path(filepath).expanduser().resolve()
    p.parent.mkdir(parents=True, exist_ok=True)

    prs = Presentation()

    # Title slide
    if title:
        slide_layout = prs.slide_layouts[0]  # Title slide layout
        slide = prs.slides.add_slide(slide_layout)
        if slide.shapes.title:
            slide.shapes.title.text = title

    # Content slides
    for sd in (slides_data or []):
        slide_layout = prs.slide_layouts[1]  # Title and Content
        slide = prs.slides.add_slide(slide_layout)
        if slide.shapes.title and sd.get("title"):
            slide.shapes.title.text = sd["title"]

        # Add bullets
        bullets = sd.get("bullets", [])
        if bullets and len(slide.shapes) > 1:
            body_shape = slide.shapes[1]
            if body_shape.has_text_frame:
                tf = body_shape.text_frame
                tf.clear()
                for i, bullet in enumerate(bullets):
                    if i == 0:
                        tf.text = bullet
                    else:
                        p2 = tf.add_paragraph()
                        p2.text = bullet
                        p2.level = 0

    prs.save(str(p))
    return {"written": str(p), "slides": len(prs.slides)}