@qvac/skills 0.1.11 → 0.1.12

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.
@@ -1,118 +1,142 @@
1
1
  ---
2
2
  name: presentations
3
- description: Create, edit, or read PowerPoint (.pptx) decks with python-pptx — deliver decks as chat attachments, or read an attached one to summarize it or answer questions in the chat. Can embed images the user attached to the chat as well as images generated in it.
4
- tools: [exec(python)]
5
- platform: [darwin, linux, win32]
6
- metadata:
7
- {
8
- "openclaw":
9
- {
10
- "setup":
11
- {
12
- "summary": "Runs python-pptx in the in-process Python runtime, from packages that ship with the app. The first use waits for the runtime to start."
13
- }
14
- }
15
- }
3
+ description: Create, edit, or read PowerPoint (.pptx) decks — deliver decks as chat attachments, or read an attached one to summarize it or answer questions in the chat. Can embed images the user attached to the chat as well as images generated in it.
4
+ tools: [pptx]
5
+ platform: [darwin, linux, win32, ios, android]
16
6
  ---
17
7
 
18
8
  # Presentations
19
9
 
20
- Build, edit, or read `.pptx` decks by running python-pptx through the `exec`
21
- tool with `language: "python"`. Declare a produced deck in `outputs` and it
22
- comes back as a chat attachment the user can save — exactly like a
23
- `generate_image` result, the `exec` result carries
24
- `attachments: [{ attachmentId, fileName, byteLength }]`. To answer *from* a
25
- deck instead of building one, run a read call alone — no `outputs` — and reply
26
- in the chat.
27
-
28
- ## Load the Recipe File First
29
-
30
- This file contains no Python. The working recipes live in three reference
31
- files — load the one for the job with the `skill` tool BEFORE writing any
32
- Python, then copy its recipe and change the content:
33
-
34
- Each load is a real `skill` tool call — printing the call as JSON or text in
35
- your reply loads nothing.
36
-
37
- - **Building a new deck** (no existing deck involved; includes embedding
38
- images generated or uploaded in this chat): call the `skill` tool with
39
- `name: "presentations"` and `file: "references/create.md"`.
40
- - **Editing a deck already in this chat** (retitle, recolor, add or revise
41
- slides on a deck the user attached or a prior call built): call the `skill`
42
- tool with `name: "presentations"` and `file: "references/edit.md"`.
43
- - **Answering from an attached deck** (a summary, a question answered,
44
- content pulled into the chat — no file produced): call the `skill` tool
45
- with `name: "presentations"` and `file: "references/read.md"`.
46
- - **A summary delivered as a new file** is a read followed by a build: load
47
- both `references/read.md` and `references/create.md`.
48
-
49
- Never write the Python from memory. The recipes carry required rules (typed
50
- `Inches`/`Pt` lengths, layout reuse, the read-before-edit flow, exact version
51
- pins, attachment staging) that fail in non-obvious ways when improvised;
52
- loading the file is one cheap read-only call.
53
-
54
- ## When to Use
55
-
56
- - The user asks for a presentation, deck, slides, `.pptx`, PowerPoint, or Keynote-openable file.
57
- - The user attaches a `.pptx` and asks what it says — a summary, a question
58
- answered, or content pulled out into the chat.
59
- - The user wants a slide deck that embeds images generated in this chat.
60
- - The user attaches an image — a photo, a logo, a screenshot — and wants it on a
61
- slide. You can see the image, and you can also stage the file it came from:
62
- load `references/create.md` (new deck) or `references/edit.md` (existing
63
- deck). Generating a lookalike instead is a failed turn.
64
-
65
- ## When NOT to Use
66
-
67
- - The user wants markdown or a document in the chat and no deck is involved —
68
- just write it. Summarizing or answering from an attached `.pptx` **is** this
69
- skill: load `references/read.md`.
70
- - The user wants a single image — call `generate_image` alone.
10
+ Every deck job is one or two `pptx` tool calls. A call with `ops` saves a new
11
+ file named `output` and attaches it to the chat; a call without `ops` changes
12
+ nothing and returns what the deck holds.
13
+
14
+ ## Pick the Call
15
+
16
+ | The user wants | The calls |
17
+ | ------------------------------------------------------------------------ | -------------------------------------------------------------------------- |
18
+ | A new deck — "make slides about …", "a deck with this image" | one call: `create` + `ops` + `output` |
19
+ | A mechanical edit — "make the title red", "retitle slide 1 to …" | one call: `attachmentId` + `ops` + `output` |
20
+ | An edit whose words depend on the deck — "add a summary slide", "fix typos" | read (`attachmentId` alone), then one edit call |
21
+ | An answer in the chat — "summarize this deck", "what does slide 3 say?" | read (`attachmentId` alone), then reply in the chat — no second call |
22
+ | A summary of the deck as a new file | read, then one `create` call written from what the read returned |
23
+
24
+ A deck already in this chat is never rebuilt with `create` — that throws away
25
+ every slide the user has. Its `attachmentId` is in the tool result that
26
+ produced it, or on the user's `[Attached file …]` line:
27
+
28
+ ```
29
+ [Attached file "quarterly.pptx" (application/vnd.openxmlformats-officedocument.presentationml.presentation) — attachmentId: 4f9c2ab1]
30
+ ```
31
+
32
+ Copy the id verbatim. Never make one up.
33
+
34
+ ## A New Deck
35
+
36
+ ```json
37
+ {
38
+ "create": { "size": "16:9" },
39
+ "ops": [
40
+ { "op": "addSlide", "layout": "Title Slide", "title": "Why the Sky Is Blue", "body": "Rayleigh scattering, in four points" },
41
+ { "op": "addSlide", "title": "What Happens", "body": [
42
+ "Sunlight carries every visible wavelength",
43
+ "Air scatters short wavelengths hardest",
44
+ { "text": "Blue scatters far more than red", "level": 1 },
45
+ "So the sky reads blue in every direction"
46
+ ] },
47
+ { "op": "addSlide", "layout": "Title Only", "title": "By Wavelength" },
48
+ { "op": "addChart", "slide": 2, "type": "column", "title": "Scattered light",
49
+ "categories": ["Blue", "Green", "Red"], "series": [{ "name": "Relative", "values": [5.5, 3.1, 1] }] }
50
+ ],
51
+ "output": "sky.pptx"
52
+ }
53
+ ```
54
+
55
+ Layouts in a new deck: `Title Slide`, `Title and Content` (the default),
56
+ `Section Header`, `Two Content`, `Title Only`, `Blank`. Each bullet is its own
57
+ item in `body` — never type `-`, `•` or `1.` in front of it; the slide draws
58
+ the bullet. Five bullets per slide at most; a sixth is a new slide titled
59
+ `… (cont.)`.
60
+
61
+ ## Reading a Deck
62
+
63
+ ```json
64
+ { "attachmentId": "4f9c2ab1" }
65
+ ```
66
+
67
+ It returns every slide with its index, layout and shapes — each shape's `id`,
68
+ `name`, and its paragraphs or table rows — plus speaker notes. You cannot write
69
+ a summary or a closing slide in the same call that reads, because the words
70
+ are fixed before the deck is opened. Read, then write from what came back.
71
+
72
+ ## Editing a Deck
73
+
74
+ ```json
75
+ {
76
+ "attachmentId": "4f9c2ab1",
77
+ "ops": [
78
+ { "op": "setText", "slide": 0, "shape": "title", "text": "Why the Sky Is Blue — Revised" },
79
+ { "op": "setStyle", "slide": 0, "shape": "title", "style": { "color": "C0392B", "bold": true } },
80
+ { "op": "addSlide", "title": "What Changed", "body": ["Retitled the cover", "Recoloured the title"] }
81
+ ],
82
+ "output": "quarterly-v2.pptx"
83
+ }
84
+ ```
85
+
86
+ Slides count from 0. A `shape` is `"title"`, `"subtitle"`, `"body"`, or the
87
+ `id` a read returned.
88
+
89
+ | The change | The op |
90
+ | ---------------------------- | ------------------------------------------------------------------------------------------ |
91
+ | Replace a shape's text | `{ "op": "setText", "slide": 1, "shape": "body", "text": ["First", "Second"] }` |
92
+ | Replace one table cell | `{ "op": "setCellText", "slide": 2, "shape": 4, "row": 1, "column": 1, "text": "450 nm" }` |
93
+ | Size, colour, font, bold | `{ "op": "setStyle", "slide": 0, "shape": "title", "style": { "size": 40, "font": "Georgia" } }` |
94
+ | Add a slide like its neighbours | `{ "op": "addSlide", "title": "Next Steps", "body": ["Ship it"] }` |
95
+ | Add a slide at a position | `{ "op": "addSlide", "at": 1, "title": "Agenda", "body": ["Why", "How"] }` |
96
+ | Delete a slide | `{ "op": "deleteSlide", "slide": 3 }` |
97
+ | Move a slide | `{ "op": "moveSlide", "from": 4, "to": 1 }` |
98
+ | Add a picture | `{ "op": "addPicture", "slide": 2, "image": { "attachmentId": "9be07c12" }, "width": 6 }` |
99
+ | Add a free text box | `{ "op": "addTextBox", "slide": 5, "text": "Thanks", "style": { "size": 54, "align": "center" } }` |
100
+ | Add a table | `{ "op": "addTable", "slide": 3, "rows": [["Band", "nm"], ["Blue", 450]], "header": true }` |
101
+ | Change a chart's numbers | `{ "op": "setChartData", "slide": 2, "shape": 4, "categories": ["Q1", "Q2"], "series": [{ "name": "2026", "values": [11, 13] }] }` |
102
+ | Retitle a chart | `{ "op": "setChartTitle", "slide": 2, "shape": 4, "title": "Revenue by quarter" }` |
103
+ | Solid background | `{ "op": "setBackground", "slide": 5, "color": "101820" }` |
104
+
105
+ `addSlide` without `layout` copies the layout of the deck's last content slide,
106
+ so the new slide matches its neighbours. Never pick `Blank` for an ordinary
107
+ title-and-bullets slide on a deck the user gave you. Positions and sizes (`x`,
108
+ `y`, `width`, `height`) are inches; give one of `width`/`height` and the
109
+ picture keeps its shape. Colours are six hex digits, no `#`.
110
+
111
+ Name the output after the deck you opened and bump a version: `quarterly.pptx`
112
+ → `quarterly-v2.pptx`, and an edit of that → `quarterly-v3.pptx`. Never the
113
+ input's own name.
114
+
115
+ ## Images
116
+
117
+ - An image this chat generated: `"image": { "attachmentId": "<id from the generate_image result>" }`.
118
+ - An image the user attached to their latest message: `"image": {}` — an
119
+ uploaded image shows no id, and the empty form picks it up.
120
+ - An image behind a URL cannot be downloaded. Say so, and ask the user to attach
121
+ it or offer `generate_image`.
71
122
 
72
123
  ## Rules for Every Job
73
124
 
74
- **You build it, not the user.** Deliver the deck, never the recipe. Do NOT
75
- print the python source in chat, do NOT tell the user to install python-pptx,
76
- run a script, or open a terminal — they have no terminal in this chat and the
77
- code would not run there. The deck exists only if an `exec` call with
78
- `outputs` succeeds and returns the attachment. Falling back to "here is the
79
- script, run it yourself" is a failed turn, and so is writing slides as
80
- markdown/chat text instead of the `.pptx` the user asked for — answering a
81
- *read* request as chat text is the read flow's finish, not this failure.
82
-
83
- **Success = stop.** When `exitCode` is `0` and `attachments` lists the
84
- `.pptx`, the deck is done. Do not call `exec` again for the same request —
85
- not to "confirm", not to "improve", not a second identical build; a second
86
- deck attach is rejected. Exactly one successful **build** `exec` per deck
87
- request — a no-`outputs` read delivers nothing and is not one of them: it
88
- belongs before the build on an edit, never after it, and on a read request it
89
- stands alone. Reply with a single line: file name + slide count from stdout.
90
- If the result has `missingOutputs` instead, the file was never written: check
91
- the `save()` name matches the declared output and rerun once.
92
-
93
- **Failures are fixed in the code, not around it.** If a run fails, fix the
94
- Python against the loaded reference file's recipes and errors table and call
95
- `exec` again. If two consecutive calls fail with the same error, the fix from
96
- the first attempt did not land — re-read the traceback line-by-line before a
97
- third call; retrying the identical `command`, or a version with only cosmetic
98
- changes, is a loop, not a fix. An error in your code is never a fault in
99
- python-pptx or in the runtime: do not switch package pins or hunt a "more
100
- compatible" version — keep `packages: ["python-pptx==1.0.2"]` — do not wrap
101
- source in `python -c "…"`, `python3`, `pip`, or shell, and do not "debug" with
102
- `os.listdir`, `print`, or a non-deck script while `outputs` still lists the
103
- deck. Never search the web about an error; the answer is always in the result
104
- you already have.
105
-
106
- **The runtime is sealed.** There is no shell — `ls`, `cat` and `file` raise
107
- `SyntaxError`, because the `command` is Python source — and no filesystem to
108
- check outside the `exec` result. There is no network: `requests`, `urllib`,
109
- and `socket` all fail, and `http_request` returns truncated text, never image
110
- bytes — an image behind a URL cannot be downloaded; ask the user to attach it
111
- or offer `generate_image`. The working directory starts empty on every call:
112
- a file from an earlier call is gone unless staged again by its attachment id,
113
- and a file you write but do not declare in `outputs` is discarded.
114
-
115
- **Never overwrite a staged input.** An edit always saves under a new,
116
- version-bumped name — `deck.pptx` → `deck-v2.pptx` — and a corrected rebuild
117
- after a broken delivery goes out under the next version, never the name
118
- already attached this turn.
125
+ **You build it, not the user.** The deck exists only when a `pptx` call with
126
+ `ops` returns its attachment. Never write the slides as chat text instead, and
127
+ never tell the user to run anything.
128
+
129
+ **Success = stop.** When the result lists the attachment, reply with one line —
130
+ the file name and the slide count — and call nothing else. Check `slides` in
131
+ the result against the request first: one slide added to a 2-slide deck is
132
+ `3`; `4` means an op ran twice, so fix the ops and send them again under the
133
+ next version name.
134
+
135
+ **Errors name the fix.** A failed call returns a message that says what exists
136
+ — `slide 7 does not exist; the deck has 3 slides (0 to 2)`, or the shapes on
137
+ the slide. Correct that one op and call again. Never repeat an identical call.
138
+
139
+ ## What This Cannot Do
140
+
141
+ Say so instead of faking it: writing speaker notes, editing scatter, bubble or
142
+ stock charts, SmartArt, and legacy `.ppt` files.
@@ -0,0 +1,93 @@
1
+ ---
2
+ name: sheet-music
3
+ description: Turn audio into sheet music. Transcribe a recording or a generated track into a score you can read, print, or open in any notation app.
4
+ tools: [transcribe_music]
5
+ platform: [darwin, linux, win32]
6
+ ---
7
+
8
+ # Sheet music
9
+
10
+ Call `transcribe_music` when the user wants notation for audio that already
11
+ exists: sheet music, a score, the chords, the notes, the melody, "write this
12
+ out". It reads an audio attachment from the chat and saves a `.musicxml` score,
13
+ which the app shows as readable sheet music in the conversation with a PDF
14
+ download; it also opens in MuseScore, Sibelius or Dorico.
15
+
16
+ ```json
17
+ { "title": "kitchen demo" }
18
+ ```
19
+
20
+ **Do not invent an `attachmentId`.** An attached audio file never appears in the
21
+ conversation with an id, so there is nothing to copy: leaving the field out is
22
+ how you say "the track the user just attached".
23
+
24
+ ## When to Use
25
+
26
+ - The user attached audio and wants it written out as notation.
27
+ - A track was generated earlier in this chat and the user now asks for its sheet
28
+ music, chords, or notes.
29
+ - The user asks what notes or chords are in a recording.
30
+
31
+ ## When NOT to Use
32
+
33
+ - The user is asking for a *new* song — that is `generate_music`. If they want the
34
+ track and its sheet music together, call `generate_music` with
35
+ `sheetMusic: true` instead of making two calls.
36
+ - The user wants spoken words written down — that is speech transcription, not
37
+ this.
38
+
39
+ **If `transcribe_music` returns an error, report it and stop.** Never fall back to
40
+ `generate_music`: that writes a brand new piece, and presenting it as the user's
41
+ transcription is a lie about their own audio. The error text says what to change,
42
+ usually to omit `attachmentId`, so read it and retry the same tool.
43
+
44
+ ## Parameters
45
+
46
+ - `attachmentId` — **omit it** to transcribe the most recent audio in the chat,
47
+ which is what an attached track means. Pass one only to reach back to an older
48
+ track whose id a previous `generate_music` actually returned.
49
+ - `title` — a short title, 2 to 5 words; it names the saved files.
50
+ - `bpm` — pass it whenever the tempo is known. **If you generated the track in
51
+ this chat with a `bpm`, pass that same value here.** Tempo estimated from audio
52
+ is right about the beat but can land an octave off (60 where the track is 120),
53
+ and a known tempo removes that guess entirely.
54
+ - `keyscale` — same idea for the key, e.g. `C minor`. Estimated when omitted.
55
+
56
+ ## What comes back
57
+
58
+ The result names the score attachment and reports what was transcribed: `notes`,
59
+ `bars`, `bpm`, `key`, how many artifacts were filtered out, and two flags worth
60
+ reading before you reply:
61
+
62
+ - `tempoFromRequest` — false means the tempo was estimated. Worth a word to the
63
+ user if the rhythm looks doubled or halved.
64
+ - `melodyMissing` — nothing was found above middle C. Say so plainly: on a dense
65
+ mix the transcription captures the bass and the loudest lines, and the melody
66
+ is buried. Do not present that score as a full transcription.
67
+
68
+ ## Honesty about quality
69
+
70
+ This is automatic transcription, not a human copyist, and the result depends
71
+ almost entirely on how dense the audio is.
72
+
73
+ - **A solo instrument or a small ensemble transcribes well.** Piano, guitar,
74
+ a single voice, a duo.
75
+ - **A full band mix does not.** Distortion and cymbals mask everything in the
76
+ middle, so what survives is the bass line and whichever line is loudest.
77
+ - Percussion is not pitched and is not transcribed.
78
+ - Sustained notes are approximate: the score reads the right pitches with
79
+ quantized rhythm, not a performance-accurate transcription.
80
+
81
+ Tell the user which of these they are getting rather than letting them discover
82
+ it.
83
+
84
+ ## A track and its score together
85
+
86
+ Sheet music never changes the track. Generate what the user asked for: their
87
+ duration, their instrumentation, their genre.
88
+
89
+ Dense or long material makes a crowded score, and that is worth saying. Before
90
+ generating, when they have left the choice open, offer it: a sparse 30-60 second
91
+ piece gives a score a person can actually read. After generating, say plainly
92
+ what they got when the result comes back with `melodyMissing` or sixty-odd bars.
93
+ Never quietly substitute something shorter or sparser than they asked for.