From 4d8fb85b6314dfcdfaac30b8db6d47330bc04e1a Mon Sep 17 00:00:00 2001 From: pika-ai-code Date: Wed, 20 May 2026 16:58:44 -0700 Subject: [PATCH] =?UTF-8?q?feat:=20v1.3.0=20=E2=80=94=20Pika=20Creative=20?= =?UTF-8?q?Suite=20repositioning=20+=20cross-agent=20distribution=20(#3)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: v1.3.0 — Pika Creative Suite repositioning + cross-agent distribution Brings Pika-Plugins forward to match the cross-agent reality. Same backend (mcp.pika.me, 58 atomic tools), same 5 curated /pika:* skills, now positioned and packaged for use beyond Claude Code. Repositioning - "Pikafy your Claude" -> "Pika Creative Suite — give any AI agent a face, a voice, and a full creative studio." README hero, all plugin manifest descriptions, and the marketplace metadata description aligned to this. Structure / new files - .cursor-plugin/plugin.json — native Cursor plugin manifest mirroring the first-party shape used in cursor/plugins (category, tags, single- string skills: "./skills/"). Lets Cursor pick up Pika via its own plugin format. - .codex-plugin/plugin.json — native Codex plugin manifest with documented interface block (displayName, defaultPrompt capped at 3, capabilities, brandColor, etc.). - .claude-plugin/marketplace.json gains an explicit skills:[] array in the canonical Anthropic string-array form ["./skills/", ...] matching anthropics/skills. Manifest cleanups - .claude-plugin/plugin.json description rewritten, version 1.2.3 -> 1.3.0. - .claude-plugin/marketplace.json description rewritten, owner.url added, plugin version bumped. - All four manifests now agree on the Pika Creative Suite positioning, the 58 canonical tool count, and the 5 skill set. Tool surface - tools-manifest.json re-vendored from pika-mcp-server with the current 58 canonical primitives plus the 9 deprecation aliases (sora_edit mode discriminator, pika_* renames, edit_audio_denoise, etc.). 16 net new canonical tools since v1.2.3 — most prominently html_to_pdf, the connect_* Composio trio, scrape_ads / scrape_social, web_publish, analyze_clip_highlights. README - Full v3 rewrite: hero, 3 independent install surfaces (MCP / Skills / Plugin) as parallel orthogonal mechanisms, install matrix with per-client config shapes (Claude type:http vs Cursor bare url vs Codex --url), Featured-workflows table linking to each SKILL.md, Capabilities table for the 11 tool families summing to 58. - 479 lines (Pikafy hero, prose-heavy) -> 220 lines (Pika Creative Suite hero, table-driven). All claims fact-checked against vercel-labs/skills source, cursor/plugins first-party manifests, anthropics/skills canonical marketplace, and openai/codex plugin docs. * fix: add repository field to marketplace.json plugin entry Codex review flagged this — the plugin entry inside marketplace.json plugins[] lacked the canonical repository field. Aligns with the top-level plugin.json which already has it. Two other codex flags triaged as false positives: - "parrot-staging/animate" in tools-manifest.json is the upstream pika-mcp-server animation backend endpoint name (vendored verbatim from pika-mcp-server@staging), not the staging plugin variant. - "Pikafy your Claude" / "Pika-fy your Claude" in CHANGELOG.md v1.3.0 entry are intentional quoted references documenting what the entry is RETIRING. Documenting history, not active usage. --- .claude-plugin/marketplace.json | 17 +- .claude-plugin/plugin.json | 14 +- .codex-plugin/plugin.json | 34 + .cursor-plugin/plugin.json | 23 + CHANGELOG.md | 34 + README.md | 434 ++--- tools-manifest.json | 2778 +++++++++++++++++++++++++++++-- 7 files changed, 2920 insertions(+), 414 deletions(-) create mode 100644 .codex-plugin/plugin.json create mode 100644 .cursor-plugin/plugin.json diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index de33fce..d66d21d 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -1,24 +1,33 @@ { "name": "pika-plugins", "metadata": { - "description": "Pika Claude Code plugin marketplace — distributes /pika:podcast (any URL or topic → 1-minute two-host video), /pika:explainer (any URL → 60–80s walkthrough video), /pika:ugc-ads (product URL → 15s creator-style multi-cut UGC ad), /pika:baseball-trend (name + photo → 15s viral ESPN behind-home-plate broadcast cutaway), and /pika:kiss-cam (two photos → 15s viral in-arena Jumbotron Kiss Cam moment with PA-announcer commentary)." + "description": "Pika Claude Code plugin marketplace — distributes the /pika:* plugin (5 curated slash commands: podcast, explainer, ugc-ads, baseball-trend, kiss-cam)." }, "owner": { "name": "Pika Labs", - "email": "support@pika.art" + "email": "support@pika.art", + "url": "https://pika.me" }, "plugins": [ { "name": "pika", - "description": "Pika-fy your Claude — give Claude a face, name, voice, and personality, plus a full creative stack of image, video, audio, and editing tools. 5 curated /pika:* slash commands backed by 42 atomic media tools at mcp.pika.me.", + "description": "Pika Creative Suite — give any AI agent a face, a voice, and a full creative studio. 5 curated /pika:* slash commands backed by 58 atomic media tools at mcp.pika.me.", "source": "./", "category": "creative", - "version": "1.2.3", + "version": "1.3.0", "author": { "name": "Pika Labs", "email": "support@pika.art" }, "homepage": "https://pika.me", + "repository": "https://github.com/Pika-Labs/Pika-Plugins", + "skills": [ + "./skills/podcast", + "./skills/explainer", + "./skills/ugc-ads", + "./skills/baseball-trend", + "./skills/kiss-cam" + ], "tags": ["pika", "video", "podcast", "explainer", "ads", "ugc", "baseball", "mlb", "espn", "broadcast", "trend", "lipsync", "creative", "mcp", "claude-code", "agent", "kiss-cam", "nba", "knicks", "msg", "jumbotron"] } ] diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index e0da3e8..01c688c 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,9 +1,15 @@ { "name": "pika", - "description": "Pika-fy your Claude — give Claude a face, name, voice, and personality, plus a full creative stack of image, video, audio, and editing tools. 5 curated /pika:* slash commands backed by 42 atomic media tools at mcp.pika.me.", - "version": "1.2.3", - "author": { "name": "Pika Labs", "email": "support@pika.art" }, + "description": "Pika Creative Suite — give any AI agent a face, a voice, and a full creative studio. 5 curated /pika:* slash commands backed by 58 atomic media tools at mcp.pika.me.", + "version": "1.3.0", + "author": { "name": "Pika Labs", "email": "support@pika.art", "url": "https://pika.me" }, "homepage": "https://pika.me", "repository": "https://github.com/Pika-Labs/Pika-Plugins", - "license": "Apache-2.0" + "license": "Apache-2.0", + "keywords": [ + "pika", "video", "podcast", "explainer", "ads", "ugc", + "baseball", "mlb", "espn", "broadcast", "trend", + "lipsync", "creative", "mcp", "claude-code", "agent", + "kiss-cam", "nba", "knicks", "msg", "jumbotron" + ] } diff --git a/.codex-plugin/plugin.json b/.codex-plugin/plugin.json new file mode 100644 index 0000000..9744f98 --- /dev/null +++ b/.codex-plugin/plugin.json @@ -0,0 +1,34 @@ +{ + "name": "pika", + "version": "1.3.0", + "description": "Pika Creative Suite — give any AI agent a face, a voice, and a full creative studio. 5 curated Pika skills (podcast, explainer, ugc-ads, baseball-trend, kiss-cam) backed by 58 atomic media tools at mcp.pika.me.", + "author": { + "name": "Pika Labs", + "email": "support@pika.art", + "url": "https://pika.me" + }, + "homepage": "https://pika.me", + "repository": "https://github.com/Pika-Labs/Pika-Plugins", + "license": "Apache-2.0", + "keywords": [ + "pika", "video", "podcast", "explainer", "ads", "ugc", + "baseball", "kiss-cam", "lipsync", "creative", "mcp", + "codex", "agent" + ], + "skills": "./skills", + "interface": { + "displayName": "Pika", + "shortDescription": "Image, video, audio, and editing tools for your Codex agent", + "longDescription": "Pika Skills give your agent a face, a voice, and a full creative stack. Use /pika:podcast for two-host podcast videos, /pika:explainer for ~60–80s URL walkthroughs, /pika:ugc-ads for 15s creator-style multi-cut UGC ads, /pika:baseball-trend for viral ESPN-style behind-home-plate broadcast cutaways, and /pika:kiss-cam for Jumbotron Kiss Cam moments. All skills share the 58-tool MCP surface at mcp.pika.me.", + "developerName": "Pika Labs", + "category": "Creative", + "capabilities": ["Read", "Write"], + "websiteURL": "https://pika.me", + "defaultPrompt": [ + "Make a two-host podcast video about this URL", + "Make a 60-second explainer for github.com/anthropics/claude-code", + "Make a UGC ad for this product page" + ], + "brandColor": "#FF3D71" + } +} diff --git a/.cursor-plugin/plugin.json b/.cursor-plugin/plugin.json new file mode 100644 index 0000000..2e396f1 --- /dev/null +++ b/.cursor-plugin/plugin.json @@ -0,0 +1,23 @@ +{ + "name": "pika", + "displayName": "Pika", + "version": "1.3.0", + "description": "Pika Creative Suite — give any AI agent a face, a voice, and a full creative studio. 5 curated Pika skills (podcast, explainer, ugc-ads, baseball-trend, kiss-cam) backed by 58 atomic media tools at mcp.pika.me.", + "author": { + "name": "Pika Labs", + "email": "support@pika.art" + }, + "homepage": "https://pika.me", + "repository": "https://github.com/Pika-Labs/Pika-Plugins", + "license": "Apache-2.0", + "keywords": [ + "pika", "video", "podcast", "explainer", "ads", "ugc", + "baseball", "kiss-cam", "lipsync", "creative", "mcp", + "cursor", "agent" + ], + "category": "creative", + "tags": [ + "video", "podcast", "ads", "creative", "lipsync", "agent" + ], + "skills": "./skills/" +} diff --git a/CHANGELOG.md b/CHANGELOG.md index 40920b0..f84d098 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,40 @@ All notable changes to the Pika Claude Code plugin are documented here. Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). +## [1.3.0] — 2026-05-20 + +### Repositioned + +- **Pika Creative Suite** — README rewritten from "Pikafy your Claude" (Claude-Code-centric) to "Pika Creative Suite — Give any AI agent a face, a voice, and a full creative studio." Reflects the actual product surface: the same MCP, skills, and plugin work natively across Claude Code, Cursor, Codex, and any of 50+ skill-aware agents. The previous hero overstated Claude exclusivity and undersold the cross-agent reality. + +### Added — cross-agent distribution + +- **`.cursor-plugin/plugin.json`** — native Cursor plugin manifest mirroring the first-party shape used in [`cursor/plugins`](https://github.com/cursor/plugins) (`category`, `tags`, `skills: "./skills/"`). Lets Cursor pick up Pika via its own plugin format. +- **`.codex-plugin/plugin.json`** — native Codex plugin manifest with documented `interface` block (`displayName`, `defaultPrompt` ≤3, `capabilities`, `brandColor`, etc.). Lets Codex CLI pick up Pika via its own plugin format. +- **`marketplace.json` `skills:` array** — explicit `["./skills/", ...]` registry so cross-agent installers (`vercel-labs/skills`, etc.) don't have to walk the filesystem. Canonical string-array form matching [`anthropics/skills`](https://github.com/anthropics/skills/blob/main/.claude-plugin/marketplace.json) and the documented `plugin-manifest.ts` schema. + +### Changed + +- **MCP tool surface: 42 → 58 atomic primitives + 9 back-compat deprecation aliases** (compounded across pika-mcp-server back-end releases). Net 16 new canonical primitives — most prominently the Sora generative-edit suite collapsed into a single `sora_edit` tool with a `mode` discriminator; the Pika tool family renamed to `pika_scene` / `pika_addition` / `pika_swap` / `pika_effect`; `edit_audio_isolate` → `edit_audio_denoise`; `extract_audio` → `extract_audio_from_video`; Composio integration via `connect_auth` / `connect_discover` / `connect_call`; wave-2 atomics (`analyze_clip_highlights`, `scrape_social`, `scrape_ads`, `web_publish`); and `html_to_pdf`. All old names remain as deprecation aliases — non-breaking for existing skills and prompts. +- **`generate_image`** new fields — `reference_images: string[]` (multi-ref), `mask` (gpt-image-2 inpainting), `watermark` (seedream), `n: 1–10` (batch). Output now includes `urls: string[]`; the singular `reference_image` field remains as a deprecated alias. +- **`generate_video`** new per-provider knobs — kling: `quality_mode` / `image_tail` / `voice_ids` / `kling_model`; pika: `negative_prompt` / `seed` / `pika_model`; veo3: `resolution` / `veo3_model` / `negative_prompt` / `seed`; sora: `sora_model` / `size` / `character_id`; minimax: `minimax_model` / `last_frame_image` / `resolution` / `prompt_optimizer`. +- **Plugin/marketplace descriptions** retired the legacy "Pika-fy your Claude" tagline in favor of "Pika Creative Suite — give any AI agent a face, a voice, and a full creative studio" matching the README hero. +- **Capabilities surface** in the README documented as 11 tool families summing to 58 canonical primitives, with the prefix convention (`mcp__plugin_pika_pika__*` inside Claude Code, agent-defined elsewhere) called out so cross-agent users can name what they see. + +### Install paths (new section in README) + +Three independent surfaces, equal weight: + +1. **MCP** — drop `https://mcp.pika.me/api/mcp` into any MCP-aware client (per-client config shape documented for Claude Code, Cursor, Codex, Claude.ai connectors). +2. **Skills** — `npx skills add Pika-Labs/Pika-Plugins` writes the 5 curated `SKILL.md` files to whichever agent the [`vercel-labs/skills` CLI](https://github.com/vercel-labs/skills) detects on your machine. +3. **Claude plugin** — `claude plugin marketplace add Pika-Labs/Pika-Plugins` + `/plugin install pika@pika-plugins` for the Claude-native install with bundled MCP wiring. + +### Fixed + +- **README Cursor `mcp.json` snippet** previously included an unverified `"transport": "http"` field. Cursor's [official docs](https://cursor.com/docs/context/mcp) show the bare `url` form; removed the unverified transport hint. +- **README `npx skills` framing** previously implied multi-agent fan-out by default. Corrected to describe actual flag behavior — default writes to detected agents; `--agent ` targets one; `--all` or `--agent '*'` installs to every detected one. +- **License footer** previously said "Built on Anthropic Claude Code"; now says "Speaks the open Model Context Protocol; finishing pipeline built on ffmpeg and Playwright" — reflects that Pika works with any MCP-aware agent, not Claude Code exclusively. + ## [1.2.3] — 2026-05-14 ### Added diff --git a/README.md b/README.md index 07d2b19..e3e7097 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,14 @@ -

Pika-fy your Claude

+

Pika Creative Suite

- Give your Claude a face, name, voice, and personality — plus a full creative stack of image, video, audio, and editing tools. All in your terminal. + Give any AI agent a face, a voice, and a full creative studio.
+ Image, video, music, editing — one identity, one auth, one bill, across every agent you use.

- Plugin version + Version MCP server - Tools + Tools License

@@ -16,371 +17,186 @@ scraping page (capture_website)... writing 4-act script (Host A · Host B)... rendering 4 video acts × ~15s (native multi-shot)... - concatenating final clip... done. -View video: https://cdn.pika.art/agent//podcast-final.mp4 +View video: https://cdn.pika.art/agent/.../podcast-final.mp4 ``` -Until now, every Claude was just *Claude*. With the **Pika MCP + Plugin** it can be a person you design — a 3D avatar, a cloned voice, a long-term memory of who you are — driving Pika's complete creative stack: video, image, voice cloning, music generation, deterministic HTML→video rendering, automatic captions, and ffmpeg-based finishing. **AI-native by design — not a GUI wrapped in an API.** +## Three independent ways to install -## How Pika fits together +Pika ships as **three independent surfaces**. Pick one, mix two, or use all three — same Pika Agent identity, same auth, same credit pool across every install. -Pika has three layers — your **Agent** (persona), the **MCP server** (protocol), and the **Claude Code plugin** (curated skills). The plugin auto-registers the MCP via its bundled `.mcp.json` — you don't have to wire anything by hand. +| Surface | What it gives you | Install mechanism | Works with | +|---|---|---|---| +| **MCP** | 58 atomic creative tools over HTTP MCP with OAuth | Add `https://mcp.pika.me/api/mcp` to any MCP-aware client | Claude Code, Cursor, Codex, Claude Desktop, Claude.ai connectors, any custom MCP agent | +| **Skills** | 5 curated `/pika:*` workflows + MCP wiring | `npx skills add Pika-Labs/Pika-Plugins` | Any skill-aware agent — Claude Code, Cursor, Codex, OpenCode, Cline, plus 50+ more auto-detected by [`vercel-labs/skills`](https://github.com/vercel-labs/skills) | +| **Claude plugin** | Same 5 skills bundled as a Claude Code-native plugin | `claude plugin marketplace add Pika-Labs/Pika-Plugins` | Claude Code only (marketplace + `/plugin` commands) | -| Layer | What it is | Where it lives | -|---|---|---| -| **Pika Agent** | Your persona — name, face, voice, and persistent memory — applied to every tool call | [pika.me](https://pika.me/) · [iOS app](https://apps.apple.com/us/app/pika-ai-agent/id6758411447) | -| **Pika MCP** | Open-protocol server exposing 42 atomic creative tools (image, video, voice, music, edit) | `https://mcp.pika.me/api/mcp` | -| **Pika Plugin** | 5 curated `/pika:*` slash commands that orchestrate multi-step pipelines on top of the MCP | This repo | +These aren't tiers — they're orthogonal mechanisms. A Claude Code user can pick the plugin, the skills, or just the raw MCP. A Cursor user picks skills + MCP. A custom agent picks just MCP. -Same backend, same auth, same output. [MCP (Model Context Protocol)](https://modelcontextprotocol.io/) is Anthropic's open standard for connecting agents to external tools — Pika MCP works with any MCP-compatible client; see [Other Claude surfaces & MCP clients](#other-claude-surfaces--mcp-clients) for non-Claude-Code setups. +## Install -> Tool names are shown unprefixed throughout this README (e.g. `generate_video`, `clone_voice`). Inside Claude Code the actual MCP tool prefix is `mcp__plugin_pika_pika__*` — both the curated skills and the tool catalog work without you ever needing to type the prefix. +### 1. MCP — just the 58 atomic tools -## Quickstart +The lightest install. No skill files written to disk. OAuth handles auth automatically on first tool call. Each client expects a slightly different shape — pick the one for your tool: -Requires Claude Code ≥ v2.0.12 (when the `/plugin` marketplace commands first shipped). +**Claude Code / Claude Desktop** — `.mcp.json`: -### 1. Create your Pika Agent +```json +{ "mcpServers": { "pika": { "type": "http", "url": "https://mcp.pika.me/api/mcp" } } } +``` -If you don't already have one, create your Pika Agent at **[pika.me](https://pika.me/)** or via the **[iOS app](https://apps.apple.com/us/app/pika-ai-agent/id6758411447)**. Your Pika Agent carries your persona, voice, avatar, and persistent memory across every Pika tool call — without it, the plugin has no identity to drive. +CLI equivalent: `claude mcp add --transport http pika https://mcp.pika.me/api/mcp`. -### 2. Install the plugin +**Cursor** — `~/.cursor/mcp.json` (global) or `.cursor/mcp.json` (project). Cursor uses bare `url`, no `type` field: -Pick the surface you use: +```json +{ "mcpServers": { "pika": { "url": "https://mcp.pika.me/api/mcp" } } } +``` -#### Claude Code CLI (terminal) +Then `cursor-agent mcp login pika`. + +**Codex CLI**: + +```bash +codex mcp add pika --url https://mcp.pika.me/api/mcp +``` + +**Claude.ai connectors** — add the endpoint URL in Settings → Connectors. **Any other MCP client** — follow your client's docs for the config shape; the endpoint is always `https://mcp.pika.me/api/mcp`. + +### 2. Skills — 5 curated workflows + MCP wiring + +[`vercel-labs/skills`](https://github.com/vercel-labs/skills) detects your installed agents and writes each skill to the right path. Pass `--agent ` to target one agent, `--all` to install to every detected one. + +```bash +npx skills add Pika-Labs/Pika-Plugins +``` + +Then add the MCP block from §1 to your agent. The skills assume the MCP server is registered as `pika`. + +### 3. Claude plugin — marketplace install ```bash claude plugin marketplace add Pika-Labs/Pika-Plugins claude plugin install pika@pika-plugins ``` -#### Claude Code Desktop (macOS / Windows app) - -UI-driven, with one slash-command line for the one-time marketplace registration. In the **Code** tab: - -1. In the prompt box, type `/plugin marketplace add Pika-Labs/Pika-Plugins` and hit Enter. -2. Click the **+** button next to the prompt box → **Plugins** → **Add plugin** → find **pika** → **Install**. - -Step 1 goes away once Pika lands in Anthropic's [official marketplace](https://claude.ai/settings/plugins/submit) — until then, the Desktop UI's plugin browser only surfaces plugins from already-configured marketplaces ([tracked in claude-code#52147](https://github.com/anthropics/claude-code/issues/52147)). - -### 3. Restart Claude Code - -Full quit and reopen — `.mcp.json` only loads at startup, and `/reload-plugins` alone isn't enough. - -### 4. Authenticate - -Inside Claude Code: - -``` -> /mcp -``` - -Find `pika`, hit **Authenticate** — your browser opens to the Pika sign-in page, sign in with the same account as your Pika Agent, the token is cached locally, and Claude Code reconnects automatically. Done. (See [Authentication](#authentication) for headless / CI options.) - -### 5. Use it - -You don't need to type slash commands — Pika skills auto-fire on natural-language intent. Both forms below do the same thing: - -``` -> /pika:podcast https://pika.art -> make me a podcast about https://pika.art - -> /pika:explainer https://github.com/anthropics/claude-code -> walk me through this repo: https://github.com/anthropics/claude-code - -> generate a 5-second video of a red panda dancing in the rain -``` - -The agent reads your prompt and runs the matching skill (or falls back to atomic MCP tools). Spending is bounded by your Pika account credit balance — no separate per-call confirmation step. - -### Verify - -```bash -claude plugin list -# pika@pika-plugins Version: 1.2.3 Status: enabled -claude mcp list -# pika: https://mcp.pika.me/api/mcp (HTTP) - Connected -``` - -## Other Claude surfaces & MCP clients - -The Pika MCP server is a standard MCP endpoint — it works with any MCP-compatible client. The Claude Code plugin (covered above) is the curated experience; below is everything else. - -| Client | How to add Pika | -|---|---| -| **Claude Code** (CLI / Desktop) | See [Quickstart Step 2](#2-install-the-plugin) above — full plugin with curated `/pika:*` skills | -| **Claude.ai chat** (regular web app) | Open [claude.ai/settings/connectors](https://claude.ai/settings/connectors) → **Add custom connector** → enter `https://mcp.pika.me/api/mcp` as the MCP server URL → complete the OAuth sign-in. Then enable the connector via the **+** button in any chat. | -| **Claude Desktop chat** (the Chat tab, not the Code tab) | Edit `claude_desktop_config.json` and add Pika as a remote MCP server pointing at `https://mcp.pika.me/api/mcp`. Restart Claude Desktop. | -| **Cursor / Codex / any MCP client** | Add `https://mcp.pika.me/api/mcp` as an HTTP MCP server in your client's MCP config; sign in with the same account as your Pika Agent. | - -On non-Claude-Code surfaces you get the **42 atomic tools** (image, video, voice, music, edit, identity) but **not** the curated `/pika:*` slash commands — those are Claude Code-specific. Same backend, same Pika Agent, same auth. - -## Launch-spotlight skills - -Curated skills designed to take you from a single prompt to a finished, shareable video. Five ship today (Podcast/Interview, Explainer, UGC Ads, Baseball-Trend, Kiss Cam). All generation skills consume Pika credits (paid via your Pika account). - -> [!TIP] -> **Skills activate from natural language — the slash command is optional.** Saying _"make me a podcast about https://pika.art"_ or _"walk me through this repo: github.com/foo/bar"_ triggers the matching skill automatically. The `/pika:*` form is just an explicit shortcut. - -### Podcast / Interview Video — `/pika:podcast` - -Hand it a URL **or a free-form topic** — get back a finished **1-minute two-host conversational video**. 4 acts × ~15s each, native multi-shot dialogue, with the Matan-authenticity rules baked in: specific jokes tied to concrete details, "wait, actually..." pivots, mid-sentence interruptions, real reactions over generic praise. Optional voice cloning for Host A via `use_avatar`. ~25–30 min wall-clock. **Costs Pika credits.** - -**URL mode** — scrape and review a product page, GitHub repo, or blog post: - -``` -/pika:podcast https://pika.art -/pika:podcast https://github.com/anthropics/claude-code use_avatar -/pika:podcast # ← no args = print input menu -``` - -**Topic mode** — free-form brief; the skill writes the script from your prose: - -``` -/pika:podcast Two AI researchers debate whether AGI arrives before 2030 -/pika:podcast I and a Mars-obsessed tech CEO talk about colonization timelines -/pika:podcast interview with a seed-stage VC about what kills most startups -``` - -Triggers from natural language — _"make a podcast about [url-or-topic]"_, _"interview-style clip about X"_, _"two-host take on Y"_, _"I and [persona] talk about Z"_ — or call the slash command directly. Named real people get archetype portraits by default (no auto-deepfake); pass `host_b_img=` to override with a likeness you have rights to. - -### Explainer Video — `/pika:explainer` - -Hand it **any URL** — a GitHub repo, product page, docs site, blog post, launch announcement — get back a ~60–80s explainer at 1280×800. Drives a real browser through the URL along an element-targeted timeline, generates an avatar lipsync of the narration, and composites it all in a macOS Sonoma frame with a 246-pixel bottom-left circle avatar. **GitHub URLs** activate a repo-aware mode (README scan + live-demo detection); other URLs use a generic page-walkthrough flow. ~5–7 min wall-clock with default `pika` lipsync; ~10–25 min if you opt into `--lipsync-provider kling` for polished-presenter mode. **Costs Pika credits.** - -Triggers from natural language too — _"explain this URL"_, _"walk me through [url]"_, _"make a demo video of [product page]"_, _"explainer for [github/product/docs link]"_, _"Loom-style walkthrough of [url]"_ — or use the slash command: - -``` -/pika:explainer https://github.com/anthropics/claude-code -/pika:explainer https://github.com// --focus "architecture, demo" -/pika:explainer https://github.com// --avatar https://cdn.pika.art/<...>.png -/pika:explainer # ← no args = print URL menu -``` - -### UGC Ads — `/pika:ugc-ads` - -Hand it a product URL — get back a **15s creator-style multi-cut UGC ad** in 9:16 vertical: HOOK + 3 JUMP CUTs + OUTRO, POV first-person talking-head selfie, native lip-synced dialogue on every beat with a 5-act narrative arc (set → name → reveal → twist → punchline). The dialogue is the through-line; the screen close-up + finger-point lands on whichever JUMP CUT the *reveal* line falls on. Six category essences (HAUL / APP / FOOD / BEAUTY / FITNESS / TECH) auto-picked from the URL guide dialogue character per category. Built-in fallback Pixar-style avatar when no `avatar_url` supplied; auto-cartoonize-on-rejection via seedream when fal-queue moderation flags a photorealistic portrait; uses your Pika avatar + cloned voice silently when available. ~6–12 min wall-clock. **Costs Pika credits.** - -Triggers from natural language — _"make a UGC ad for [URL]"_, _"jump-cut product ad about [URL]"_, _"creator-style ad for X"_, _"talking-head TikTok ad about Y"_, _"haul-style ad"_, _"unboxing video about [URL]"_ — or use the slash command: - -``` -/pika:ugc-ads https://pika.art -/pika:ugc-ads https://maisonbrune.com avatar_url=https://cdn/face.png aspect_ratio=3:4 -/pika:ugc-ads https://oatly.com category=FOOD -/pika:ugc-ads https://glossier.com avatar_url=https://cdn/face.png provider=kling -/pika:ugc-ads # ← no args = print URL menu -``` - -### Baseball-Trend (ESPN behind-home-plate cutaway) — `/pika:baseball-trend` - -Hand it your **name + one reference photo** — get back a **15s ESPN-style broadcast cutaway** of you sitting behind home plate at a fake Yankees vs Red Sox ALCS Game 3 at Fenway Park, with two live MLB announcers naming you on air. Broadcast still (`gpt-image-2`) with a real ESPN-style scorebug + chyron baked into frame 0, then a 15s `kling-v3-omni` clip locked to that frame for pixel-static graphics across the full shot. Native two-announcer commentary, realistic telephoto broadcast feel, no scene cuts. ~3–5 min wall-clock. **Costs Pika credits.** - -Triggers from natural language — _"make me a behind-home-plate cutaway"_, _"fake MLB broadcast of me"_, _"AI ESPN baseball crowd shot"_, _"viral MLB broadcast trend with me"_ — or use the slash command: - -``` -/pika:baseball-trend "Jane Doe" https://cdn/face.png -/pika:baseball-trend "Jane Doe" /path/to/portrait.jpg -/pika:baseball-trend # ← no args = ask for name + photo -``` - -Engine is Kling-only — Seedance's output-side moderation rejects every broadcast cutaway because of the crowd faces. Recognizable celebrities are also gated (the trend illusion only works with a non-public-figure reference where the chyron name + face are coherent). - -### Kiss Cam (in-arena Jumbotron moment) — `/pika:kiss-cam` - -Hand it **two reference photos** — get back a **15s viral "Kiss Cam at MSG" moment**: a fan-filmed spectator-POV phone shot of the Madison Square Garden Jumbotron with the retro red kiss cam graphic (sparkly hearts, cursive script) + adjacent Knicks vs Bulls scoreboard, then 15 seconds of the two subjects sharing a sweet, natural kiss while an off-screen PA announcer and packed-arena crowd react. Spectator-POV still (`gpt-image-2`) with the entire kiss cam UI baked into frame 0, then `kling-v3-omni` locks that as the first frame so the scoreboard, hearts, and "Kiss Cam" script stay pixel-static across all 15s — only the two subjects inside the kiss cam panel animate. Any subject style works (photoreal humans, 3D toys, illustrated avatars) — the recipe preserves whatever style each reference uses. No names anywhere; no chyron. ~4–6 min wall-clock. **Costs Pika credits.** - -Triggers from natural language — _"make me a kiss cam moment"_, _"kiss cam version of these two"_, _"Jumbotron kiss cam trend"_, _"fake NBA kiss cam"_ — or use the slash command: - -``` -/pika:kiss-cam https://cdn/photo-a.png https://cdn/photo-b.png -/pika:kiss-cam /path/to/photo-a.jpg /path/to/photo-b.jpg -/pika:kiss-cam # ← no args = ask for both photos -``` - -Engine is gpt-image-2 + Kling-only, same reason as baseball-trend's Kling lock — Seedance's two-stage face-moderation gate rejects every in-arena reaction shot because of the crowd faces. - -## Authentication - -You need an authenticated MCP session before any Pika tool call works. The recommended path is one-time `/mcp` connect: - -``` -> /mcp -``` - -This opens the MCP manager UI. Find `pika`, hit **Authenticate** — your browser opens to the Pika sign-in page, sign in with the same account as your Pika Agent, the token is cached locally, and Claude Code reconnects automatically. After this, every Pika tool call works without re-prompting. +Full quit + reopen Claude Code, then run `/mcp` and authenticate `pika`. The plugin bundles the same 5 skills as §2 plus the MCP wiring — no separate `claude mcp add`.
-Other auth flows: auto-OAuth on first call · static token (headless / CI) · troubleshooting +Claude Code on the web (claude.ai/code) -### Auto-OAuth on first call +Add this to your repo's `.claude/settings.json`, commit, and push — cloud sessions auto-install at startup: -Skip `/mcp` and just call any Pika tool. The first call returns `401`, Claude Code auto-discovers the OAuth metadata, opens your browser, you sign in, and the original call retries automatically. - -``` -> /pika:podcast https://pika.art -[browser opens for OAuth] -[returns to terminal, call retries, video URL appears] +```json +{ + "extraKnownMarketplaces": { + "pika-plugins": { + "source": { "source": "github", "repo": "Pika-Labs/Pika-Plugins" } + } + }, + "enabledPlugins": { + "pika@pika-plugins": true + } +} ``` -### Static token (headless / CI / no browser) - -If you can't do an interactive browser flow, set a Pika token in your shell **before launching `claude`**: - -```bash -export MCP_AUTH_TOKEN="" -claude -``` - -Tokens come in two flavors — a **developer key** (`dk_*` prefix, long-lived; get one at [pika.me/dev](https://www.pika.me/dev/)) or an **agent key** (service-to-service for trusted automation). Don't hard-code `${MCP_AUTH_TOKEN}` into `.mcp.json` or any file you commit — keep it in your shell env. - -### Troubleshooting - -| Symptom | Fix | -|---|---| -| `401 Unauthorized` on every call | Token expired. `claude mcp remove pika` then re-run `/mcp` to re-auth. | -| Want to switch accounts | `claude mcp remove pika` → re-run `/mcp` and sign in with the other account. | -| Browser doesn't open during OAuth | Allow Claude Code to open default browser, or fall back to a static token. | -| `claude mcp list` shows `Disconnected` | Restart Claude Code (full quit). `.mcp.json` is only loaded at startup. | +`mcp.pika.me` isn't in the default Trusted allowlist — switch the environment's network access to **Full**, or use **Custom** with `mcp.pika.me` added. ([Anthropic network access docs](https://code.claude.com/docs/en/claude-code-on-the-web#network-access))
-## What you can do with Pika +## Authenticate -The plugin ships 5 curated slash commands; underneath, **42 atomic MCP tools** are at your agent's disposal. You describe the outcome in plain English — Pika picks the right tool. +One time per install. Inside your agent, run `/mcp`, find `pika`, hit **Authenticate**. Your browser opens to the Pika sign-in page, the token caches locally, the MCP reconnects. -### Generate video +
+Headless / CI / no browser -Text-to-video, image-to-video, multi-reference video, keyframe transitions, lipsync, and motion transfer — all under one schema. Pika auto-routes to the best model for each request; override via the `provider` field if you have a preference. +Get a developer key (`dk_*`) at [pika.me/dev](https://www.pika.me/dev/) and export it before launching your agent: -``` -> make a 5-second video of a red panda dancing in the rain -> animate this image -> take these 3 reference images and this audio, build me a 10-second clip -> sync this audio to this face -> apply the motion from this reference video onto this character image +```bash +export MCP_AUTH_TOKEN="dk_..." +claude # or cursor, codex, etc. ``` -`generate_video` · `generate_reference_video` · `generate_keyframes_video` · `generate_lipsync` · `generate_motion_control_video` +Don't hard-code the token into `.mcp.json` or any committed file — keep it in shell env or your secret store. Tokens also come in an agent-key flavor for service-to-service automation; same env var. -### Generate images +
-Text-to-image, image editing, 4K resolution, ultra-fast iteration. Same auto-routing logic as video. +
+Troubleshooting -``` -> generate a product photo of a coffee cup on white -> make a 4K vertical wallpaper based on this brief -> edit this image — add a sunset behind it -``` +| Symptom | Fix | +|---|---| +| `401 Unauthorized` on every call | Token expired. Re-run `/mcp` and re-authenticate, or refresh `MCP_AUTH_TOKEN`. | +| Want to switch accounts | Remove `pika` from your client's MCP list (`claude mcp remove pika`, edit `~/.cursor/mcp.json`, `codex mcp remove pika`, …) → re-add and re-authenticate. | +| Browser doesn't open during OAuth | Allow your agent to open default browser, or fall back to the headless token flow above. | +| `mcp list` shows `Disconnected` | Full quit and restart your agent — `.mcp.json` is only loaded at startup. | -`generate_image` +
-### Generate + clone voices +## Featured workflows -Text-to-speech in 100+ languages, voice cloning from a 30-second sample. Cloned `voice_id`s are reusable across `generate_speech` and any video tool that takes voice IDs. +Curated `/pika:*` skills (Surfaces §2 and §3) — one prompt to a finished, shareable video. All consume Pika credits. -``` -> read this script in a calm female voice -> clone my voice from this 30-second sample -> make a podcast where two AI hosts debate Bitcoin -``` +| Skill | Input | Output | Invoke | +|---|---|---|---| +| **[Podcast](./skills/podcast/SKILL.md)** | URL or free-form topic | 1-minute two-host conversational video, 4 acts × ~15s | `/pika:podcast` | +| **[Explainer](./skills/explainer/SKILL.md)** | Any URL (GitHub, product, docs) | 60–80s browser walkthrough with avatar lipsync | `/pika:explainer` | +| **[UGC Ads](./skills/ugc-ads/SKILL.md)** | Product URL | 15s creator-style multi-cut UGC ad, 9:16 | `/pika:ugc-ads` | +| **[Baseball-Trend](./skills/baseball-trend/SKILL.md)** | Name + photo | 15s ESPN behind-home-plate broadcast cutaway | `/pika:baseball-trend` | +| **[Kiss Cam](./skills/kiss-cam/SKILL.md)** | Two photos | 15s MSG Jumbotron Kiss Cam moment | `/pika:kiss-cam` | -`generate_speech` · `clone_voice` +Skills activate from natural language too — saying *"make a podcast about https://pika.art"* fires `/pika:podcast` automatically. -### Generate music +## Capabilities — 58 atomic tools -Original music generation, licensed-catalog search, and beat-synced video cuts. +Behind every curated skill is a flat tool surface (Surface §1) you can drive directly. Inside Claude Code the MCP tool prefix is `mcp__plugin_pika_pika__*`; other agents follow their own prefix convention. Counts are canonical primitives only — 9 deprecation aliases ship for back-compat but aren't counted. -``` -> compose a 60-second uplifting electronic track -> find royalty-free music about [topic] -> cut this video on the beat at 128 bpm -``` +| Family | What it covers | Count | +|---|---|---| +| **Generation** | Image, video, lipsync, music, speech, slide animation, motion-control, keyframes, reference video | 9 | +| **Generative video edit** | One multi-mode tool — cut, extend, and remix existing video | 1 | +| **Scene composition** | Multi-character / multi-object scene compose, generative video inpainting, region replace by mask or text, viral still-image effects | 4 | +| **Editing** | Concat, mix, trim, captions, PiP, animate-zoom, browser-frame, beat-sync, audio denoise, text overlay, add captions | 11 | +| **Capture** | Website screenshot / recording, frame extraction, audio extraction | 3 | +| **Analysis** | Media, brief, transcription, clip highlights | 4 | +| **Identity** | Avatar, voice, persona, memory append / search, sample | 10 | +| **Persistent refs** | Reusable character refs, element refs, cloned voices | 3 | +| **Connect** | Third-party app integrations via auth / discover / call (broad ecosystem) | 3 | +| **Scrape** | Ads, social | 2 | +| **Publish / search / async / utility** | Web publish, music search, skill search, task status/cancel, upload, HTML render, HTML→PDF | 8 | +| **Total** | | **58** | -`generate_music` · `search_music` · `edit_beat_sync` +Full schema → [`tools-manifest.json`](./tools-manifest.json). -### Edit + finish +## Requirements -Pure-ffmpeg deterministic ops, ~30s each, stitched together by the agent. Concat, audio mix/trim, captions in 4 styles (`tiktok` · `hormozi` · `classic` · `karaoke`, 100+ languages), text overlays, picture-in-picture (rect or circular), animated zoom, macOS-frame wrap for screen recordings, frame extraction. - -`edit_concat` · `edit_audio_mix` · `edit_audio_trim` · `edit_text_overlay` · `edit_pip` · `edit_trim` · `edit_animate_zoom` · `edit_browser_frame` · `add_captions` · `extract_frame` - -### Render HTML → video (HyperFrames) - -Claude writes HTML, HyperFrames renders deterministically — same input produces byte-identical output. Outputs MP4, WebM, or MOV with transparency. - -``` -> make me a 30-second animated slide deck about my product launch -> render this HTML composition as a video -``` - -`generate_slide_animation` · `render_html_animation` - -### Analyze + transcribe - -Describe media, extract structured briefs from mixed sources, transcribe audio or video, and capture live websites with timed scroll/click actions. - -``` -> describe this video -> extract a structured product brief from these 3 sources -> transcribe this audio -> screencap this URL with timed scrolling -``` - -`analyze_media` · `analyze_brief` · `transcribe_audio` · `capture_website` - -### Identity + memory - -Your Pika Agent's persona, voice, avatar, and a persistent memory store — auto-injected as defaults on every Pika tool call so you never have to repeat yourself. - -`identity_whoami` · `identity_persona_read` · `identity_avatar_url` · `identity_voice_id` · `identity_voice_info` · `identity_set_avatar` · `identity_set_voice` · `identity_memory_search` · `identity_memory_append` - -### Full schema - -→ [`tools-manifest.json`](./tools-manifest.json) — all 42 tools with complete input/output schemas, ready for raw-MCP / OpenAPI consumers. +- A Pika account ([sign up at pika.me](https://pika.me)) — carries your persona, voice, avatar, and memory +- One of: an MCP-compatible client (any agent), a skill-aware agent ([50+ supported](https://github.com/vercel-labs/skills)), or Claude Code ≥ v2.0.12 (for the plugin path) ## FAQ **How does pricing work?** -All generation skills consume **Pika credits** from your Pika account. Free credits ship with every account; top up at [pika.me](https://pika.me/). Atomic-tool calls (e.g. `generate_video`) and curated skills (`/pika:podcast`, `/pika:explainer`, `/pika:ugc-ads`) both draw from the same balance. - -**Can I use Pika MCP without Claude Code?** -Yes — the MCP server at `https://mcp.pika.me/api/mcp` is a standard HTTP MCP endpoint and works with Claude Desktop, Cursor, Codex, or any MCP-compatible client. The curated `/pika:*` slash commands are Claude Code-specific, but the 42 atomic tools are universal. See [Other Claude surfaces & MCP clients](#other-claude-surfaces--mcp-clients). +All generation consumes **Pika credits** from your Pika account. Free credits ship with every account; top up at [pika.me](https://pika.me). Atomic-tool calls and curated `/pika:*` skills draw from the same balance. **Is my voice clone, avatar, and memory private?** -Yes. Your Pika Agent's persona, cloned voice, avatar, and memory are scoped to your Pika account and only accessible to your authenticated MCP sessions. They are not used to train shared models. Manage or delete them at [pika.me](https://pika.me/). +Yes. Persona, cloned voice, avatar, and memory are scoped to your Pika account and accessible only to your authenticated MCP sessions. They are not used to train shared models. Manage or delete at [pika.me](https://pika.me). -**Can I bring my own model API keys?** -No — Pika manages provider routing internally so you don't have to juggle API keys, rate limits, or billing across multiple model vendors. One Pika account, one billing surface, every model. +**Can I bring my own provider API keys?** +No — Pika manages provider routing internally so you don't juggle API keys, rate limits, or billing across vendors. One Pika account, one billing surface, every model. -**What's the difference between this and the Pika web app?** -The web app is a hosted creative environment with a UI. The MCP + Plugin is **AI-native** — designed to be driven by an agent in plain English, with no UI. Same backend, same Pika Agent, same output. Use the web app for hands-on direction; use the MCP + Plugin to let an agent compose multi-tool pipelines for you. +**Issues / questions →** [`Pika-Labs/Pika-Plugins/issues`](https://github.com/Pika-Labs/Pika-Plugins/issues) -## Related projects +## Links -| Repo | What it is | Use when | -|---|---|---| -| **[Pika-Labs/Pika-Skills](https://github.com/Pika-Labs/Pika-Skills)** | Open-source `SKILL.md` modules powered by the Pika Developer API. No MCP, no plugin — drop a folder into your agent workspace, set `PIKA_DEV_KEY`, and go. | You want a single-purpose skill (e.g. video meeting agent) without installing the full plugin, or you're on an agent harness without MCP support. | -| **This repo** ([`Pika-Labs/Pika-Plugins`](https://github.com/Pika-Labs/Pika-Plugins)) | Full Claude Code plugin + remote MCP server with 42 atomic tools and curated `/pika:*` slash commands. | You want the complete creative stack inside Claude Code with one install. | - -## Manage your install - -```bash -claude plugin update pika -claude plugin disable pika -claude plugin uninstall pika -claude plugin marketplace remove pika-plugins -``` - -## Acknowledgments - -Built on [Anthropic Claude Code](https://www.anthropic.com/) and the open [Model Context Protocol](https://modelcontextprotocol.io/), with [ffmpeg](https://ffmpeg.org/) and [Playwright](https://playwright.dev/) for finishing and capture. - -## Contributing - -Issues + PRs welcome at [`Pika-Labs/Pika-Plugins`](https://github.com/Pika-Labs/Pika-Plugins/issues). +- [Changelog](./CHANGELOG.md) — release history +- [Tool schema](./tools-manifest.json) — all 58 atomic tools with full param surfaces +- [Pika MCP endpoint](https://mcp.pika.me/api/mcp) — raw HTTP MCP +- [Pika Developer Portal](https://www.pika.me/dev/) — keys and SDK references +- [Security policy](./SECURITY.md) +- Open-source skill modules → [`Pika-Labs/Pika-Skills`](https://github.com/Pika-Labs/Pika-Skills) +- Pika consumer products — [pika.me](https://pika.me), [iOS app](https://apps.apple.com/us/app/pika-ai-agent/id6758411447) ## License -See [LICENSE](./LICENSE). +Apache 2.0 — see [LICENSE](./LICENSE). Speaks the open [Model Context Protocol](https://modelcontextprotocol.io/); finishing pipeline built on [ffmpeg](https://ffmpeg.org/) and [Playwright](https://playwright.dev/). diff --git a/tools-manifest.json b/tools-manifest.json index ccdae16..7663d99 100644 --- a/tools-manifest.json +++ b/tools-manifest.json @@ -1,7 +1,7 @@ [ { "name": "add_captions", - "description": "Auto-transcribe a video's audio (Whisper → Deepgram → Gemini waterfall, word-level timings) and burn styled captions onto the video. Four styles: `tiktok` (word-by-word purple highlight, Bebas Neue, all caps), `hormozi` (bold centered 1-3 words, yellow highlight), `classic` (bottom subtitle bar, semi-transparent), `karaoke` (word-by-word progressive color fill). CJK languages (zh/ja/ko) auto-detected and rendered with Noto CJK fonts bundled in the worker image.\n\nReturns the result inline when complete (typically 30s–5min). Progress updates are sent as notifications during execution. If the server budget expires before completion, falls back to `{ task_id, status }` — then call `task_status(task_id)` in a tight loop (no Bash, no sleep) until done.", + "description": "Auto-transcribe a video's audio (Whisper → Deepgram → Gemini waterfall, word-level timings) OR burn caller-provided captions in one pass. Manual mode accepts either plain `subtitle_text` or timestamped `subtitles[]` and skips transcription. Four styles: `tiktok` (word-by-word purple highlight, Bebas Neue, all caps), `hormozi` (bold centered 1-3 words, yellow highlight), `classic` (bottom subtitle bar, semi-transparent), `karaoke` (word-by-word progressive color fill). CJK languages (zh/ja/ko) auto-detected and rendered with Noto CJK fonts bundled in the worker image. Return `transcript` is the provider transcript in auto mode; in manual mode it is normalized visible text with control characters stripped, whitespace collapsed, and segment texts joined by spaces.\n\nReturns the result inline when complete (typically 30s–5min). Progress updates are sent as notifications during execution. If the server budget expires before completion, falls back to `{ task_id, status }` — then call `task_status(task_id)` in a tight loop (no Bash, no sleep) until done.", "inputSchema": { "type": "object", "properties": { @@ -9,39 +9,207 @@ "type": "string", "format": "uri", "pattern": "^https:\\/\\/.*", - "description": "Source video URL (must be https://). Audio extracted server-side." + "description": "Source video URL (must be https://). Audio extracted server-side in auto mode." }, "style": { "default": "classic", - "description": "Caption visual style. tiktok / hormozi / karaoke = word-level highlight; classic = bottom subtitle bar.", + "description": "Caption preset name. Built-ins: tiktok, hormozi, classic, karaoke (+ neon-pop demonstrator). Each declares default position, font, colors, animation. Designer-extendable via YAMLs in skills-worker/src/pika_mcp_skills/add_captions/presets/. Default: classic.", + "type": "string" + }, + "position": { + "description": "Caption vertical position; overrides preset default.", "type": "string", "enum": [ - "tiktok", - "hormozi", - "classic", - "karaoke" + "top", + "middle", + "bottom" + ] + }, + "font": { + "description": "Bundled font. CJK content always uses noto-cjk regardless.", + "type": "string", + "enum": [ + "bebas-neue", + "inter", + "noto-cjk" + ] + }, + "font_color": { + "description": "Main text color. Hex (#RRGGBB) or named: white|black|gray|red|orange|yellow|green|cyan|blue|purple|pink|magenta.", + "type": "string" + }, + "highlight_color": { + "description": "Word-highlight color (word-swap / karaoke styles only). Hex or named.", + "type": "string" + }, + "outline_color": { + "description": "Text outline color. Hex or named.", + "type": "string" + }, + "font_size": { + "description": "Explicit pixel font size. Mutually exclusive with font_scale.", + "type": "integer", + "minimum": 12, + "maximum": 200 + }, + "font_scale": { + "description": "Font size multiplier of preset auto-base. S=0.75x, M=1.0x, L=1.25x, XL=1.5x. Mutually exclusive with font_size.", + "type": "string", + "enum": [ + "S", + "M", + "L", + "XL" ] }, "language": { "description": "Optional BCP-47 language hint (e.g. 'en', 'zh'). Auto-detect if omitted.", "type": "string" }, - "font_size": { - "description": "Optional font size override. Style-specific default applied if omitted.", - "type": "integer", - "minimum": 12, - "maximum": 200 + "caption_mode": { + "description": "Caption source. Omit for automatic behavior: auto when no manual input is provided, manual when subtitle_text or subtitles is provided. auto transcribes audio; manual skips transcription and burns caller-provided text.", + "type": "string", + "enum": [ + "auto", + "manual" + ] + }, + "subtitle_text": { + "description": "Plain script text for manual mode. The worker splits it into caption groups and spreads timing across the detected video duration; very dense text may be rejected after media probing.", + "type": "string", + "minLength": 1, + "maxLength": 20000 + }, + "subtitles": { + "description": "Timestamped manual subtitles. Segments must be sorted, non-overlapping, and worker-validated against the video duration plus 0.25s tolerance after media probing.", + "minItems": 1, + "maxItems": 500, + "type": "array", + "items": { + "type": "object", + "properties": { + "start_s": { + "description": "Subtitle start time in seconds.", + "type": "number", + "minimum": 0 + }, + "end_s": { + "description": "Subtitle end time in seconds; must be greater than start_s.", + "type": "number", + "minimum": 0 + }, + "text": { + "type": "string", + "minLength": 1, + "maxLength": 500, + "description": "Subtitle text for this time range." + } + }, + "required": [ + "start_s", + "end_s", + "text" + ] + } } }, "required": [ "video_url" ], - "$schema": "http://json-schema.org/draft-07/schema#" + "$schema": "http://json-schema.org/draft-07/schema#", + "allOf": [ + { + "not": { + "allOf": [ + { + "required": [ + "subtitle_text" + ] + }, + { + "required": [ + "subtitles" + ] + } + ] + } + }, + { + "not": { + "allOf": [ + { + "required": [ + "font_size" + ] + }, + { + "required": [ + "font_scale" + ] + } + ] + } + }, + { + "if": { + "properties": { + "caption_mode": { + "const": "auto" + } + }, + "required": [ + "caption_mode" + ] + }, + "then": { + "not": { + "anyOf": [ + { + "required": [ + "subtitle_text" + ] + }, + { + "required": [ + "subtitles" + ] + } + ] + } + } + }, + { + "if": { + "properties": { + "caption_mode": { + "const": "manual" + } + }, + "required": [ + "caption_mode" + ] + }, + "then": { + "anyOf": [ + { + "required": [ + "subtitle_text" + ] + }, + { + "required": [ + "subtitles" + ] + } + ] + } + } + ] } }, { "name": "analyze_brief", - "description": "Extract a structured product brief from multiple sources: web pages, GitHub repos, PDFs, or raw text/chat history. Combines all sources and uses Gemini to output a normalised JSON brief (product name, tagline, features, pain points, tone, etc.) — ready for video script generation.\n\nReturns the result inline when complete (typically 30s–5min). Progress updates are sent as notifications during execution. If the server budget expires before completion, falls back to `{ task_id, status }` — then call `task_status(task_id)` in a tight loop (no Bash, no sleep) until done.", + "description": "Extract a structured product brief (default) OR a free-form prose summary from up to 5 sources: web pages, GitHub repos, PDFs, or raw text. The format field switches output shape:\n- `brief` (default): Gemini returns a normalised JSON brief — product name, tagline, features, pain points, tone, etc. Ready for video-script generation.\n- `summary` (AGNT-68 #21): Gemini returns 2-5 paragraphs of prose capturing each source's gist + cross-source notable points. Use for non-product content (research, news, docs) where the rigid brief shape doesn't fit.\n\nReturns the result inline when complete (typically 30s–5min). Progress updates are sent as notifications during execution. If the server budget expires before completion, falls back to `{ task_id, status }` — then call `task_status(task_id)` in a tight loop (no Bash, no sleep) until done.", "inputSchema": { "type": "object", "properties": { @@ -82,6 +250,15 @@ "description": "Optional extra context: target audience, video purpose, what to focus on.", "type": "string", "maxLength": 2000 + }, + "format": { + "default": "brief", + "description": "Output shape. `brief` (default) returns structured JSON product brief; `summary` returns free-form prose (2-5 paragraphs). Both share the same source-fetching pipeline (AGNT-68 #21).", + "type": "string", + "enum": [ + "brief", + "summary" + ] } }, "required": [ @@ -90,15 +267,171 @@ "$schema": "http://json-schema.org/draft-07/schema#" } }, + { + "name": "analyze_clip_highlights", + "description": "Find the most viral-worthy clip ranges in a video transcript. Returns scored start/end timestamps + hook + reason for each clip. Pure atomic primitive — single LLM call, no media output. Caller chains: transcribe_audio → analyze_clip_highlights → edit_trim (and optionally add_captions). Pass EITHER `transcript_words` (word-level timestamps from transcribe_audio) OR `transcript_text` (pre-formatted with `[XmYs]` timestamps), not both. Optional face-detection metadata (`first_face_time_s`, `no_face_intervals`) constrains clips so they don't start during slides/title cards.", + "inputSchema": { + "type": "object", + "properties": { + "transcript_words": { + "description": "Word-level transcript with timestamps in seconds. Output of `transcribe_audio`. Mutually exclusive with `transcript_text`.", + "type": "array", + "items": { + "type": "object", + "properties": { + "text": { + "type": "string" + }, + "start_s": { + "type": "number", + "minimum": 0 + }, + "end_s": { + "type": "number", + "minimum": 0 + } + }, + "required": [ + "text", + "start_s", + "end_s" + ] + } + }, + "transcript_text": { + "description": "Pre-formatted transcript with `[XmYs]` timestamps (e.g. `[1m23s] hello world`). Mutually exclusive with `transcript_words`.", + "type": "string", + "minLength": 1, + "maxLength": 50000 + }, + "source_duration_s": { + "type": "number", + "exclusiveMinimum": 0, + "maximum": 7200, + "description": "Source video duration in seconds (max 2h)." + }, + "num_clips": { + "default": 3, + "description": "How many clips to return (1-20, default 3).", + "type": "integer", + "minimum": 1, + "maximum": 20 + }, + "clip_duration_s": { + "default": 30, + "description": "Target clip duration in seconds (10-120, default 30). Min/max are clamped server-side to ±15 of this target, bounded by [15, 90].", + "type": "integer", + "minimum": 10, + "maximum": 120 + }, + "first_face_time_s": { + "description": "Optional: time at which the speaker first appears on screen. Clips that would start before this are dropped (intro title cards).", + "type": "number", + "minimum": 0 + }, + "no_face_intervals": { + "description": "Optional: list of `[start_s, end_s]` intervals where the speaker is NOT visible (slides, title cards, b-roll). Clips starting inside these intervals are dropped.", + "maxItems": 100, + "type": "array", + "items": { + "type": "array", + "items": [ + { + "type": "number" + }, + { + "type": "number" + } + ] + } + } + }, + "required": [ + "source_duration_s" + ], + "$schema": "http://json-schema.org/draft-07/schema#" + }, + "outputSchema": { + "type": "object", + "properties": { + "clips": { + "type": "array", + "items": { + "type": "object", + "properties": { + "rank": { + "type": "integer", + "exclusiveMinimum": 0, + "maximum": 9007199254740991 + }, + "virality_score": { + "type": "number", + "minimum": 0, + "maximum": 10 + }, + "hook": { + "type": "string" + }, + "reason": { + "type": "string" + }, + "start_s": { + "type": "number", + "minimum": 0 + }, + "end_s": { + "type": "number", + "minimum": 0 + }, + "duration_s": { + "type": "number", + "exclusiveMinimum": 0 + } + }, + "required": [ + "rank", + "virality_score", + "hook", + "reason", + "start_s", + "end_s", + "duration_s" + ], + "additionalProperties": {} + } + }, + "source_duration_s": { + "type": "number", + "exclusiveMinimum": 0 + }, + "num_clips_requested": { + "type": "integer", + "exclusiveMinimum": 0, + "maximum": 9007199254740991 + }, + "llm_model": { + "type": "string" + } + }, + "required": [ + "clips", + "source_duration_s", + "num_clips_requested", + "llm_model" + ], + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": {} + } + }, { "name": "analyze_media", - "description": "Analyze an image or short video with Gemini vision model.", + "description": "Analyze an image, short video, OR audio clip with Gemini's multimodal model. The worker auto-routes based on the Content-Type the `media` URL responds with: image/*, video/*, audio/* (mp3/wav/m4a/aac/flac/ogg/opus/webm) all flow through the same inlineData → :generateContent path. Use for transcribing intent, mood/tone analysis, audio quality scoring, content moderation, etc. (AGNT-68 #20).", "inputSchema": { "type": "object", "properties": { "provider": { "default": "gemini", - "description": "Vision provider. Default: `gemini` (gemini-3-pro). No alternative providers wired today.", + "description": "Multimodal analysis provider. Default: `gemini` (gemini-3-flash). No alternative providers wired today.", "type": "string", "enum": [ "gemini" @@ -107,7 +440,7 @@ "media": { "type": "string", "format": "uri", - "description": "Image or video URL to analyze." + "description": "Image, video, OR audio URL to analyze. Content-Type drives routing — audio/* MIME types are now accepted in addition to image/* and video/*." }, "query": { "type": "string", @@ -253,54 +586,377 @@ }, { "name": "clone_voice", - "description": "Clone a custom voice from an audio/video file or an existing Kling video. Returns a voice_id you can bind to a Kling element via create_kling_element (element_voice_id). Audio must be 5-30s, single clean voice, no background noise.\n\nReturns the result inline when complete (typically 30s–5min). Progress updates are sent as notifications during execution. If the server budget expires before completion, falls back to `{ task_id, status }` — then call `task_status(task_id)` in a tight loop (no Bash, no sleep) until done.", + "description": "Dispatch on `action` to manage cloned voices:\n- `clone` (default): clone a custom voice from an audio/video file or an existing Kling video. Returns a voice_id you can bind to a Kling element via create_kling_element (element_voice_id). Audio must be 5-30s, single clean voice, no background noise.\n- `design` (AGNT-44 #B1): generate a brand-new voice from a text description via ElevenLabs `/v1/text-to-voice/create-previews`. No audio sample needed — just a prose description (e.g. 'warm female narrator with British accent'). Returns the generated voice_id + an optional preview sample URL.\n- `list` (AGNT-66 #14) + `provider`: list user's custom voices (provider=kling supported in v1). Returns `{voices[], count}`.\n- `get` (AGNT-66 #15) + provider + voice_id: fetch one voice's metadata.\n- `delete` (AGNT-66 #16) + provider + voice_id: delete a custom voice.\n\nMinimax voice CRUD is filed as a follow-up ticket; v1 ships kling for clone/list/get/delete and elevenlabs for design.\n\nReturns the result inline when complete (typically 30s–5min). Progress updates are sent as notifications during execution. If the server budget expires before completion, falls back to `{ task_id, status }` — then call `task_status(task_id)` in a tight loop (no Bash, no sleep) until done.", "inputSchema": { "type": "object", "properties": { - "voice_name": { + "action": { + "default": "clone", + "description": "Which voice operation to perform. Default `clone` preserves pre-Wave-1 behavior. `design` was added in AGNT-44 Tier-C #B1.", "type": "string", - "maxLength": 20, - "description": "Voice name (max 20 chars)." + "enum": [ + "clone", + "design", + "list", + "get", + "delete" + ] + }, + "provider": { + "description": "Required for action=list/get/delete (use `kling`). For action=design, callers may explicitly pass `elevenlabs` to make the routing explicit — design always routes there. action=clone always routes to kling regardless of this field. PR #206 minor: accepting `elevenlabs` so explicit design-route calls don't surface a confusing 'invalid enum value' error.", + "type": "string", + "enum": [ + "kling", + "elevenlabs" + ] + }, + "voice_name": { + "description": "Voice name (max 20 chars). Required when action=clone.", + "type": "string", + "maxLength": 20 }, "voice_url": { - "description": "Audio/video source URL (mp3/wav/mp4/mov). 5-30s, single clean voice. Mutually exclusive with video_id.", + "description": "Audio/video source URL (mp3/wav/mp4/mov). 5-30s, single clean voice. Mutually exclusive with video_id. Used by action=clone.", "type": "string", "format": "uri" }, "video_id": { - "description": "Existing Kling video ID to extract voice from. Must be a v2.6 sound=on video, avatar, or lipsync output. Mutually exclusive with voice_url.", + "description": "Existing Kling video ID to extract voice from. Must be a v2.6 sound=on video, avatar, or lipsync output. Mutually exclusive with voice_url. Used by action=clone.", "type": "string" + }, + "voice_description": { + "description": "Free-text description of the voice. Required when action=design. Example: 'warm female narrator with British accent, slow pacing'.", + "type": "string", + "minLength": 1 + }, + "preview_text": { + "description": "Optional 100-1000-char preview text for action=design. When omitted, ElevenLabs auto-generates a sample.", + "type": "string" + }, + "seed": { + "description": "Optional seed for reproducibility on action=design.", + "type": "integer", + "minimum": -9007199254740991, + "maximum": 9007199254740991 + }, + "voice_id": { + "description": "Required when action=get or action=delete. The voice id (returned by action=clone, action=design, or action=list).", + "type": "string" + }, + "page_num": { + "description": "Optional pagination on action=list (default 1).", + "type": "integer", + "minimum": 1, + "maximum": 9007199254740991 + }, + "page_size": { + "description": "Optional page size on action=list (default 30; cap 500).", + "type": "integer", + "minimum": 1, + "maximum": 500 } }, - "required": [ - "voice_name" - ], "$schema": "http://json-schema.org/draft-07/schema#" } }, { - "name": "create_kling_element", - "description": "Create a Kling subject (element) from image or video references. Returns an element_id you can pass to generate_reference_video as element_ids[] for character/style consistency in kling omni r2v.\n\nReturns the result inline when complete (typically 30s–5min). Progress updates are sent as notifications during execution. If the server budget expires before completion, falls back to `{ task_id, status }` — then call `task_status(task_id)` in a tight loop (no Bash, no sleep) until done.", + "name": "connect_auth", + "description": "Auth operations for Composio third-party tools. Use op=list_accounts to see which apps the user has authorized and which are allowlisted; use op=request_link to obtain an OAuth URL for an unauthorized toolkit. To execute a tool, call connect_discover first (to get the slug + schema), then connect_call.", "inputSchema": { "type": "object", "properties": { - "element_name": { + "op": { "type": "string", - "maxLength": 20, - "description": "Subject name (max 20 chars)." + "enum": [ + "list_accounts", + "request_link" + ], + "description": "Operation discriminator. `list_accounts` returns the caller's connected accounts (across all toolkits, or filtered by `toolkit`); `request_link` mints a fresh OAuth connect URL for the specified `toolkit` (which becomes required)." + }, + "toolkit": { + "description": "Composio toolkit slug (kebab-case, e.g. `gmail`, `slack`, `github`, `notion`). REQUIRED when `op=request_link`; for `op=list_accounts` it is optional — pass to filter results to a single toolkit, omit to list across all toolkits.", + "type": "string", + "pattern": "^[a-z0-9-]{1,64}$" + } + }, + "required": [ + "op" + ], + "$schema": "http://json-schema.org/draft-07/schema#" + }, + "outputSchema": { + "type": "object", + "properties": { + "op": { + "type": "string", + "enum": [ + "list_accounts", + "request_link" + ] + }, + "accounts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "toolkit_slug": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "ACTIVE", + "INITIATED", + "EXPIRED", + "INACTIVE" + ] + }, + "connected_at": { + "type": "string" + } + }, + "required": [ + "id", + "toolkit_slug", + "status" + ], + "additionalProperties": false + } + }, + "available_toolkits": { + "type": "array", + "items": { + "type": "string" + } + }, + "connect_url": { + "type": "string", + "format": "uri" + }, + "expires_at": { + "type": "string" + }, + "account_id": { + "type": "string" + } + }, + "required": [ + "op" + ], + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false + } + }, + { + "name": "connect_call", + "description": "Execute one Composio action. You MUST have called connect_discover first to obtain the exact action slug and the JSON Schema for args — do NOT guess. For write actions (slug containing SEND/CREATE/DELETE/POST/UPDATE/REMOVE/WRITE/INSERT/ADD/PATCH/REPLY/FORWARD/MERGE/ARCHIVE/SCHEDULE/ASSIGN/REVOKE/MOVE/DRAFT/CLEAR/RESET), the user must confirm; pass confirm: true after confirmation. On needs_oauth, call connect_auth({op:'request_link', toolkit}).", + "inputSchema": { + "type": "object", + "properties": { + "toolkit": { + "type": "string", + "pattern": "^[a-z0-9-]{1,64}$", + "description": "Composio toolkit slug (kebab-case, e.g. `gmail`, `slack`). Must be a toolkit the caller has connected — if not, the response is `{ok:false, error:{code:'needs_oauth', …}}` and the caller should invoke `connect_auth({op:'request_link', toolkit})` to mint a connect URL." + }, + "action": { + "type": "string", + "pattern": "^[A-Z0-9_]{1,128}$", + "description": "Composio action slug (SCREAMING_SNAKE_CASE, e.g. `GMAIL_SEND_EMAIL`, `SLACK_POST_MESSAGE`). Discover via `connect_discover({query})` — the returned `slug` field is exactly this value." + }, + "args": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": {}, + "description": "Action-specific arguments matching the `arguments_schema` returned by `connect_discover`. The schema is action-specific and validated server-side by Composio." + }, + "confirm": { + "default": false, + "description": "Destructive-action gate. For action slugs matching the destructive verb list (SEND / CREATE / DELETE / POST / UPDATE / REMOVE / WRITE / INSERT / ADD / PATCH / REPLY / FORWARD / MERGE / ARCHIVE / SCHEDULE / ASSIGN / REVOKE / MOVE / DRAFT / CLEAR / RESET), callers MUST pass `confirm: true` (after explicit user confirmation) or the call short-circuits with `{ok: false, error: {code: 'confirmation_required', ...}}` before any upstream call is made. No-op for read-only actions. The destructive-slug list is matched on the `action` slug verbatim — see `isDestructiveSlug` in `lib/composio-shim.ts` for the canonical regex.", + "type": "boolean" + } + }, + "required": [ + "toolkit", + "action", + "args" + ], + "$schema": "http://json-schema.org/draft-07/schema#" + }, + "outputSchema": { + "type": "object", + "properties": { + "ok": { + "type": "boolean" + }, + "data": {}, + "error": { + "type": "object", + "properties": { + "code": { + "type": "string", + "enum": [ + "feature_disabled", + "toolkit_not_allowed", + "unknown_tool", + "needs_oauth", + "confirmation_required", + "invalid_arguments", + "proxy_failure", + "upstream_failure", + "rate_limited", + "timeout", + "downstream_auth_failed", + "internal" + ] + }, + "message": { + "type": "string", + "maxLength": 500 + }, + "correlation_id": { + "type": "string" + }, + "toolkit_slug": { + "type": "string" + } + }, + "required": [ + "code", + "message" + ], + "additionalProperties": false + } + }, + "required": [ + "ok" + ], + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false + } + }, + { + "name": "connect_discover", + "description": "Search Composio's third-party tool catalog by use case ('send an email', 'create a Linear issue', 'schedule a meeting'). Returns up to 25 matching tools with their full JSON Schema inline — you can construct a connect_call invocation directly from this output without a separate inspect call. Use connect_discover BEFORE connect_call; do NOT guess slug names or argument shapes.", + "inputSchema": { + "type": "object", + "properties": { + "query": { + "type": "string", + "minLength": 1, + "maxLength": 500, + "description": "Free-text search across the Composio action catalog. Matches tool slugs, descriptions, and parameter names. Examples: `send email`, `create issue`, `search drive`. Result objects carry their full `arguments_schema` inline so a follow-up `inspect_tool` call is not needed." + }, + "limit": { + "default": 10, + "description": "Max number of matching actions to return (1-25). Default 10. Each result carries the full JSON Schema for its arguments and output, so a wider limit increases response payload size non-trivially — pick the smallest value that gives enough candidates for the caller to pick from.", + "type": "integer", + "minimum": 1, + "maximum": 25 + }, + "toolkit": { + "description": "Optional toolkit slug filter (kebab-case, e.g. `gmail`). When set, only actions from that toolkit match. Omit to search the entire Composio catalog (discovery is connection- independent — connection is only required at `connect_call` time, not for discovery).", + "type": "string", + "pattern": "^[a-z0-9-]{1,64}$" + } + }, + "required": [ + "query" + ], + "$schema": "http://json-schema.org/draft-07/schema#" + }, + "outputSchema": { + "type": "object", + "properties": { + "tools": { + "maxItems": 25, + "type": "array", + "items": { + "type": "object", + "properties": { + "slug": { + "type": "string" + }, + "toolkit_slug": { + "type": "string" + }, + "description": { + "type": "string", + "maxLength": 500 + }, + "write_class": { + "type": "boolean" + }, + "arguments_schema": {}, + "output_schema": {}, + "score": { + "type": "number", + "minimum": 0, + "maximum": 1 + } + }, + "required": [ + "slug", + "toolkit_slug", + "description", + "write_class", + "arguments_schema", + "score" + ], + "additionalProperties": false + } + }, + "next_step_hint": { + "type": "string" + } + }, + "required": [ + "tools", + "next_step_hint" + ], + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false + } + }, + { + "name": "create_kling_element", + "description": "Dispatch on `action` to manage Kling subjects (elements):\n- `create` (default): create an element from image/video references. Returns `{element_id, element_name, task_id}`. Use the element_id with generate_reference_video as element_ids[] for character/style consistency in kling omni r2v.\n- `list` (AGNT-65 #5): list user's Kling elements. Returns `{elements[], count}`. Supports `page_num`/`page_size`.\n- `get` (AGNT-65 #6) + element_id: fetch one element's metadata.\n- `delete` (AGNT-65 #7) + element_id: delete an element.\n- `presets` (AGNT-65 #8): list available tag preset IDs (o_101..o_108) with human-readable labels. Free, no network call.\n\nReturns the result inline when complete (typically 30s–5min). Progress updates are sent as notifications during execution. If the server budget expires before completion, falls back to `{ task_id, status }` — then call `task_status(task_id)` in a tight loop (no Bash, no sleep) until done.", + "inputSchema": { + "type": "object", + "properties": { + "action": { + "default": "create", + "description": "Which element operation to perform. Default `create` preserves pre-Wave-1 behavior.", + "type": "string", + "enum": [ + "create", + "list", + "get", + "delete", + "presets" + ] + }, + "element_name": { + "description": "Subject name (max 20 chars). Required when action=create.", + "type": "string", + "maxLength": 20 }, "element_description": { + "description": "Subject description (max 100 chars). Required when action=create.", "type": "string", - "maxLength": 100, - "description": "Subject description (max 100 chars)." + "maxLength": 100 }, "reference_type": { + "description": "Required when action=create. \"image_refer\": define from multi-angle photos (all styles). \"video_refer\": define from a short video clip (realistic human only, kling-v3+ models).", "type": "string", "enum": [ "image_refer", "video_refer" - ], - "description": "\"image_refer\": define from multi-angle photos (all styles). \"video_refer\": define from a short video clip (realistic human only, kling-v3+ models)." + ] }, "frontal_image": { "description": "Front-facing reference image URL. Required when reference_type=image_refer.", @@ -327,7 +983,7 @@ "type": "string" }, "tag_ids": { - "description": "Category tags: o_101=趣梗 o_102=人物 o_103=动物 o_104=道具 o_105=服饰 o_106=场景 o_107=特效 o_108=其他", + "description": "Category tags: o_101=趣梗 o_102=人物 o_103=动物 o_104=道具 o_105=服饰 o_106=场景 o_107=特效 o_108=其他. Call action=presets to fetch the list at runtime.", "type": "array", "items": { "type": "string", @@ -342,13 +998,65 @@ "o_108" ] } + }, + "element_id": { + "description": "Required when action=get or action=delete. The Kling element id (returned by action=create or action=list).", + "type": "string" + }, + "page_num": { + "description": "Optional pagination on action=list (Kling default 1).", + "type": "integer", + "minimum": 1, + "maximum": 9007199254740991 + }, + "page_size": { + "description": "Optional page size on action=list (Kling default 30; cap 500).", + "type": "integer", + "minimum": 1, + "maximum": 500 + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "create_sora_character", + "description": "Dispatch on `action` to manage sora persistent assets:\n- `create_character` (default): create a reusable character from a short reference video. Requires `name` + `video`. Returns `{character_id, name}`.\n- `get_character` (AGNT-67): fetch character metadata by `character_id`. Returns `{character_id, name, metadata}`.\n- `list_videos` (AGNT-67 #17): list the user's previously-generated sora videos. Returns `{videos[], count}`.\n- `download_video` (AGNT-67 #18): fetch a sora video by `video_id` and upload to the CDN. Returns `{url, video_id, bytes}`.\n- `delete_video` (AGNT-67 #19): delete a sora video by `video_id`. Returns `{video_id, deleted}`.\n\nCharacter-creation reference video must be 2-4 seconds long, 16:9 or 9:16 aspect ratio — sora upstream rejects off-aspect clips with a 400 carrying the rule verbatim.\n\nReturns the result inline when complete (typically 30s–5min). Progress updates are sent as notifications during execution. If the server budget expires before completion, falls back to `{ task_id, status }` — then call `task_status(task_id)` in a tight loop (no Bash, no sleep) until done.", + "inputSchema": { + "type": "object", + "properties": { + "action": { + "default": "create_character", + "description": "Which sora asset operation to perform. Default `create_character` preserves pre-Wave-1 behavior.", + "type": "string", + "enum": [ + "create_character", + "get_character", + "list_videos", + "download_video", + "delete_video" + ] + }, + "name": { + "description": "Display name for the character. Required when action=create_character.", + "type": "string", + "minLength": 1, + "maxLength": 80 + }, + "video": { + "description": "Reference video URL (mp4 / mov). 2-4 seconds, 16:9 or 9:16 aspect ratio. Required when action=create_character. The worker forwards this to sora's /v1/videos/characters endpoint as a multipart `video` upload.", + "type": "string", + "format": "uri" + }, + "character_id": { + "description": "Required when action=get_character.", + "type": "string" + }, + "video_id": { + "description": "Required when action=download_video or action=delete_video. The sora video id (returned by generate_video provider=sora).", + "type": "string" } }, - "required": [ - "element_name", - "element_description", - "reference_type" - ], "$schema": "http://json-schema.org/draft-07/schema#" } }, @@ -423,6 +1131,42 @@ "$schema": "http://json-schema.org/draft-07/schema#" } }, + { + "name": "edit_audio_denoise", + "description": "Remove background noise / music / ambient sound from an audio recording, isolating the vocals or speech. Powered by ElevenLabs `/v1/audio-isolation`. Atomic primitive: single ~5-30s multipart POST, no poll. Returns the cleaned audio URL on the CDN. Pair with `transcribe_audio` for cleaner ASR on noisy field recordings, or with `generate_lipsync` to get a clean voice track before driving a face.\n\nReturns the result inline when complete (typically 30s–5min). Progress updates are sent as notifications during execution. If the server budget expires before completion, falls back to `{ task_id, status }` — then call `task_status(task_id)` in a tight loop (no Bash, no sleep) until done.", + "inputSchema": { + "type": "object", + "properties": { + "audio_url": { + "type": "string", + "format": "uri", + "description": "URL of the audio file to clean (mp3/wav/m4a/etc.). The file may contain background music, noise, or non-speech audio; the denoise model removes it and returns just the vocals." + } + }, + "required": [ + "audio_url" + ], + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "edit_audio_isolate", + "description": "⚠ DEPRECATED — Renamed to `edit_audio_denoise`. Same parameters, same behavior. See `edit_audio_denoise` for full documentation. This alias will be removed in a future release.", + "inputSchema": { + "type": "object", + "properties": { + "audio_url": { + "type": "string", + "format": "uri", + "description": "URL of the audio file to clean (mp3/wav/m4a/etc.). The file may contain background music, noise, or non-speech audio; the denoise model removes it and returns just the vocals." + } + }, + "required": [ + "audio_url" + ], + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, { "name": "edit_audio_mix", "description": "Overlay an audio track (music, voiceover) onto a video. Original video audio is preserved; the new track is mixed at the specified volume.\n\nReturns the result inline when complete (typically 30s–5min). Progress updates are sent as notifications during execution. If the server budget expires before completion, falls back to `{ task_id, status }` — then call `task_status(task_id)` in a tight loop (no Bash, no sleep) until done.", @@ -840,9 +1584,63 @@ "$schema": "http://json-schema.org/draft-07/schema#" } }, + { + "name": "extract_audio", + "description": "⚠ DEPRECATED — Renamed to `extract_audio_from_video`. Same parameters, same behavior. See `extract_audio_from_video` for full documentation. This alias will be removed in a future release.", + "inputSchema": { + "type": "object", + "properties": { + "video_url": { + "type": "string", + "format": "uri", + "description": "URL of the source video" + }, + "format": { + "default": "mp3", + "description": "Output audio format. `mp3` (default) is compact and universally compatible; `wav` is sample-accurate PCM (larger file size) and what most downstream audio-analysis tools prefer.", + "type": "string", + "enum": [ + "mp3", + "wav" + ] + } + }, + "required": [ + "video_url" + ], + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "extract_audio_from_video", + "description": "Pull the audio track out of a video file as an mp3 (default, 192k libmp3lame) or wav (PCM s16le) file. Input video is unchanged. Returns the audio URL on the CDN. Composes with `edit_audio_trim` if you need to slice a sub-range out of the extracted audio.\n\nCommon upstream sources: video clips you want to feed into `transcribe_audio` directly (note: transcribe_audio accepts video URLs too and extracts internally — use extract_audio_from_video when you want the intermediate audio URL exposed for later steps).\n\nReturns the result inline when complete (typically 30s–5min). Progress updates are sent as notifications during execution. If the server budget expires before completion, falls back to `{ task_id, status }` — then call `task_status(task_id)` in a tight loop (no Bash, no sleep) until done.", + "inputSchema": { + "type": "object", + "properties": { + "video_url": { + "type": "string", + "format": "uri", + "description": "URL of the source video" + }, + "format": { + "default": "mp3", + "description": "Output audio format. `mp3` (default) is compact and universally compatible; `wav` is sample-accurate PCM (larger file size) and what most downstream audio-analysis tools prefer.", + "type": "string", + "enum": [ + "mp3", + "wav" + ] + } + }, + "required": [ + "video_url" + ], + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, { "name": "extract_frame", - "description": "Extract a single frame from a video as a PNG image. Uses fast input-side seek so extraction is near-instant even for long videos. The returned PNG URL can be used as reference_image in generate_image (e.g. capture_website → extract_frame → generate_image to generate a laptop mockup using the real website screenshot as reference).\n\nReturns the result inline when complete (typically 30s–5min). Progress updates are sent as notifications during execution. If the server budget expires before completion, falls back to `{ task_id, status }` — then call `task_status(task_id)` in a tight loop (no Bash, no sleep) until done.", + "description": "Extract one or more frames from a video as PNG image(s). Single-frame mode (default): pass `time_s` (or omit; defaults to 0) — returns `{url}`. Batch mode (AGNT-69 #22): pass exactly one of `count`, `interval_s`, or `at_times[]` (mutually exclusive with `time_s`) — returns `{urls: [...], url: urls[0]}` (the legacy `url` field is kept set to the first frame for back-compat with single-frame callers that handle both shapes).\n\nUses fast input-side seek so extraction is near-instant even for long videos.\n\nReturns the result inline when complete (typically 30s–5min). Progress updates are sent as notifications during execution. If the server budget expires before completion, falls back to `{ task_id, status }` — then call `task_status(task_id)` in a tight loop (no Bash, no sleep) until done.", "inputSchema": { "type": "object", "properties": { @@ -852,9 +1650,30 @@ "description": "URL of the video to extract a frame from" }, "time_s": { - "description": "Timestamp in seconds to extract (default 0 = first frame)", + "description": "Timestamp in seconds to extract (default 0 = first frame). Single-frame mode only — mutually exclusive with batch knobs.", "type": "number", "minimum": 0 + }, + "count": { + "description": "Batch: extract N frames evenly spaced across the video (skipping the first/last 5% so title/outro frames don't dominate). Requires the video duration to be probeable via ffprobe. 1-32. Mutually exclusive with time_s/interval_s/at_times.", + "type": "integer", + "minimum": 1, + "maximum": 32 + }, + "interval_s": { + "description": "Batch: extract a frame every N seconds starting at t=0 until either the video ends or the 32-frame cap is reached. Requires the video duration to be probeable via ffprobe. Mutually exclusive with time_s/count/at_times.", + "type": "number", + "exclusiveMinimum": 0 + }, + "at_times": { + "description": "Batch: explicit list of timestamps in seconds. 1-32 entries. Sorted + de-duplicated server-side. Mutually exclusive with time_s/count/interval_s.", + "minItems": 1, + "maxItems": 32, + "type": "array", + "items": { + "type": "number", + "minimum": 0 + } } }, "required": [ @@ -863,6 +1682,61 @@ "$schema": "http://json-schema.org/draft-07/schema#" } }, + { + "name": "generate_effect_video", + "description": "⚠ DEPRECATED — Renamed to `pika_effect`. Same parameters, same behavior. See `pika_effect` for full documentation. This alias will be removed in a future release.", + "inputSchema": { + "type": "object", + "properties": { + "image": { + "type": "string", + "format": "uri", + "description": "Source image URL the effect is applied to." + }, + "effect": { + "type": "string", + "enum": [ + "Cake-ify", + "Crumble", + "Crush", + "Decapitate", + "Deflate", + "Dissolve", + "Explode", + "Eye-pop", + "Inflate", + "Levitate", + "Melt", + "Peel", + "Poke", + "Squish", + "Ta-da", + "Tear" + ], + "description": "One of 16 named viral Pikaffects." + }, + "prompt": { + "description": "Optional prompt to guide the effect.", + "type": "string", + "maxLength": 500 + }, + "negative_prompt": { + "type": "string", + "maxLength": 500 + }, + "seed": { + "type": "integer", + "minimum": -9007199254740991, + "maximum": 9007199254740991 + } + }, + "required": [ + "image", + "effect" + ], + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, { "name": "generate_image", "description": "Generate an image. One tool, multiple providers via the `provider` enum. **Default: nano-banana-pro** (Gemini 3 Pro — best balance of quality + character/style consistency). Alternatives: gemini-flash-image (fastest, lower fidelity); seedream (cinematic + 2K/4K); gpt-image-2 (best for editing an existing image, supports `quality` + `output_format`). When the user expresses preference for speed, cost, image editing, or 4K resolution, surface the provider choice and let them override — otherwise stick with the default.\n\nReturns the result inline when complete (typically 30s–5min). Progress updates are sent as notifications during execution. If the server budget expires before completion, falls back to `{ task_id, status }` — then call `task_status(task_id)` in a tight loop (no Bash, no sleep) until done.", @@ -885,10 +1759,19 @@ "description": "Description of the image. Be specific about subject, style, lighting." }, "reference_image": { - "description": "Optional reference image URL for style / character consistency. On gpt-image-2 this routes through the /v1/images/edits endpoint (image-to-image editing).", + "description": "DEPRECATED — use `reference_images`. Single reference image URL for style / character consistency. When both are present, this is prepended to the head of `reference_images`.", "type": "string", "format": "uri" }, + "reference_images": { + "description": "Reference image URLs for style / character consistency (multi-ref). Per-provider caps: gemini up to 14, seedream up to 14, gpt-image-2 up to 16. Order matters — refs are sent in array order. On gpt-image-2 this routes through /v1/images/edits with one `image[]` multipart entry per ref.", + "maxItems": 16, + "type": "array", + "items": { + "type": "string", + "format": "uri" + } + }, "aspect_ratio": { "description": "Output aspect ratio (default 1:1).", "type": "string", @@ -901,7 +1784,7 @@ ] }, "resolution": { - "description": "Output resolution (default 1K). 4K supported on seedream only.", + "description": "Output resolution (default 1K). 4K supported on seedream and gemini (post-BACK-339 imageSize fix). gpt-image-2 native sizes are 1024x1024 / 1536x1024 / 1024x1536 / 1792x1024 / 1024x1792 only (all 1K-class) — passing resolution=2K or 4K on gpt-image-2 is rejected with a pointer to seedream (BACK-339 round-1+2 fixup; AGNT-149 widened the 16:9/9:16 native sizes).", "type": "string", "enum": [ "1K", @@ -910,12 +1793,13 @@ ] }, "quality": { - "description": "Image quality, gpt-image-2 only. `low` is ~10–20s; `medium`/`auto` are slower. `high` is intentionally NOT exposed — it exceeds the proxy 180s read timeout. Rejected on other providers.", + "description": "Image quality, gpt-image-2 only. `low` is ~10–20s; `medium`/`auto` are slower. `high` is the slowest tier — typically around two minutes. Rejected on other providers.", "type": "string", "enum": [ "auto", "low", - "medium" + "medium", + "high" ] }, "output_format": { @@ -926,6 +1810,21 @@ "jpeg", "webp" ] + }, + "mask": { + "description": "Alpha PNG URL — mask for inpainting. gpt-image-2 only (routes to /v1/images/edits). Transparent regions are repainted, opaque regions are kept. Mask dimensions must match the reference image; mismatches return a clean upstream 400. Rejected on other providers.", + "type": "string", + "format": "uri" + }, + "watermark": { + "description": "Toggle the seedream watermark. seedream only — defaults to false (no watermark). Mirrors the kling watermark precedent (BACK-278). Rejected on other providers.", + "type": "boolean" + }, + "n": { + "description": "Number of images to generate (default 1, max 10). Output schema gains `urls[]` regardless; `url` retained as `urls[0]` for back-compat. gpt-image-2 native `n`; seedream uses `sequential_image_generation`; gemini does NOT support n>1 for image gen and returns a clean InvalidInput.", + "type": "integer", + "minimum": 1, + "maximum": 10 } }, "required": [ @@ -1018,8 +1917,20 @@ "description": "Source audio URL to sync to." }, "prompt": { - "description": "Optional style/motion hint (parrot only).", + "description": "Optional style/motion hint. Parrot uses promptText; kling wires it through to the avatar payload for emotion / camera guidance (BACK-339 — was previously dropped).", "type": "string" + }, + "mode": { + "description": "Kling avatar quality tier (std default upstream, pro higher fidelity). Kling only.", + "type": "string", + "enum": [ + "std", + "pro" + ] + }, + "watermark": { + "description": "Burn kling's watermark into the output. Default `false` — clean output by default. Pass `true` to opt back into kling's account-tier-dependent watermark. Kling only.", + "type": "boolean" } }, "required": [ @@ -1067,7 +1978,7 @@ ] }, "model": { - "description": "Kling model id (kling only; default kling-v3).", + "description": "Kling model id (kling only; default kling-v3). kling-v2-6 is intentionally kept on motion-control (worker enforces the same two-value allow-list); the v2-6 deferral on `generate_video.kling_model` is t2v/i2v-specific.", "type": "string", "enum": [ "kling-v3", @@ -1081,6 +1992,33 @@ "std", "pro" ] + }, + "character_orientation": { + "description": "Kling motion-control character orientation source. `video` (default) uses the reference video's orientation; `image` uses the source image. Kling only. (BACK-339.)", + "type": "string", + "enum": [ + "video", + "image" + ] + }, + "keep_original_sound": { + "description": "Preserve the reference video's original audio in the output. Default `false` (BACK-339; was previously silently `yes`). Kling only.", + "type": "boolean" + }, + "seed": { + "description": "Reproducibility seed for pika animate. Pika only — kling motion-control rejects this. (BACK-339.)", + "type": "integer", + "minimum": -9007199254740991, + "maximum": 9007199254740991 + }, + "negative_prompt": { + "description": "What pika animate should AVOID generating. Pika only — kling motion-control rejects this. (BACK-339.)", + "type": "string", + "maxLength": 2500 + }, + "watermark": { + "description": "Burn kling's watermark into the output. Default `false` — clean output by default. Pass `true` to opt back into kling's account-tier-dependent watermark. Kling only.", + "type": "boolean" } }, "required": [ @@ -1092,26 +2030,85 @@ }, { "name": "generate_music", - "description": "Generate music with vocals via MiniMax music-2.5. Duration is determined by lyric length (typically 20-60s); pass multi-section [verse]/[chorus] lyrics to get longer tracks.", + "description": "Generate music or sound effects. Default kind=`music` + provider=`minimax-music` calls MiniMax music-2.5 (full song with vocals; duration determined by lyric length, 20-60s typical). Set `kind: sfx` (AGNT-44 #B2) + `provider: elevenlabs` to generate a short sound effect via ElevenLabs `/v1/sound-generation` (e.g. 'thunder', 'glass breaking', 0.5-30s, no lyrics). Set `provider: kling-audio` (AGNT-44 #A2/A3) to generate music/SFX/BGM via Kling — `mode: text_to_audio` from a prompt, or `mode: video_to_audio` cued to an existing video (provide `source_video_url` or `source_video_id`).", "inputSchema": { "type": "object", "properties": { "provider": { "default": "minimax-music", - "description": "Which music model. Default minimax-music (currently the only provider).", + "description": "Music/SFX provider. `minimax-music` (default) for full songs with vocals + lyrics. `elevenlabs` for sound effects (requires kind=sfx). `kling-audio` (AGNT-44 #A2/A3) for music/SFX/BGM from a prompt (mode=text_to_audio) or cued to a video (mode=video_to_audio).", "type": "string", "enum": [ - "minimax-music" + "minimax-music", + "elevenlabs", + "kling-audio" + ] + }, + "kind": { + "default": "music", + "description": "What to generate. `music` (default) — full song with vocals/instruments via MiniMax. `sfx` (AGNT-44 #B2) — short sound effect via ElevenLabs (no lyrics; provider must be elevenlabs). Ignored for kling-audio (Kling handles music/SFX/BGM via mode + per-mode prompt fields).", + "type": "string", + "enum": [ + "music", + "sfx" + ] + }, + "mode": { + "description": "AGNT-44 #A2/A3 — kling-audio only. `text_to_audio` (default): generate audio from a prompt. `video_to_audio`: generate audio cued to a source video (provide source_video_url or source_video_id).", + "type": "string", + "enum": [ + "text_to_audio", + "video_to_audio" ] }, "prompt": { "type": "string", "minLength": 1, - "description": "Style/genre/mood description." + "description": "Style/genre/mood description (kind=music) OR the sound effect to generate (kind=sfx; e.g. 'thunder cracking with rain', 'glass shattering on tile') OR the audio prompt for kling-audio text_to_audio." }, "lyrics": { - "description": "Song lyrics with optional [verse]/[chorus] section tags. Output length scales with lyric length; omit for a ~33s instrumental.", + "description": "Song lyrics with optional [verse]/[chorus] section tags. Output length scales with lyric length; omit for a ~33s instrumental. Ignored when kind=sfx or provider=kling-audio.", "type": "string" + }, + "duration_seconds": { + "description": "kind=sfx only: target duration in seconds (0.5-30). When omitted, ElevenLabs auto-picks.", + "type": "number", + "minimum": 0.5, + "maximum": 30 + }, + "prompt_influence": { + "description": "kind=sfx only: how strictly to follow the prompt (0-1, default 0.3). Higher = more literal interpretation.", + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "loop": { + "description": "kind=sfx only: when true, generate seamless looping audio.", + "type": "boolean" + }, + "source_video_url": { + "description": "kling-audio mode=video_to_audio: HTTPS URL of the source video (3-20s, mp4/mov). Mutually exclusive with source_video_id.", + "type": "string", + "format": "uri" + }, + "source_video_id": { + "description": "kling-audio mode=video_to_audio: Kling video id (last 30 days). Mutually exclusive with source_video_url.", + "type": "string", + "minLength": 1 + }, + "sound_effect_prompt": { + "description": "kling-audio mode=video_to_audio: sound-effect prompt cued to the video (max 200 chars).", + "type": "string", + "maxLength": 200 + }, + "bgm_prompt": { + "description": "kling-audio mode=video_to_audio: background-music prompt cued to the video (max 200 chars).", + "type": "string", + "maxLength": 200 + }, + "asmr_mode": { + "description": "kling-audio mode=video_to_audio: enable ASMR generation mode.", + "type": "boolean" } }, "required": [ @@ -1122,16 +2119,17 @@ }, { "name": "generate_reference_video", - "description": "Generate a video from multi-modal reference inputs (images, videos, audio) used as character / style / motion anchors — NOT as start frames. **Default: kling** (omni-video, sound-capable, up to 7 image / 3 video / 8 audio refs). Specialist: seedance — cinematic look, supports `fast` / `seed` / `resolution` / `auto_duration`, accepts up to 9 image / 3 video / 3 audio refs (combined ≤ 12).\n\nReference assets in prompt via <<>>/<<>> (kling) or @Image1/@Video1/@Audio1 (seedance).\n\nSound defaults to on; pass sound=false to suppress. For text- or single-image-driven video use `generate_video` instead.\n\nReturns the result inline when complete (typically 30s–5min). Progress updates are sent as notifications during execution. If the server budget expires before completion, falls back to `{ task_id, status }` — then call `task_status(task_id)` in a tight loop (no Bash, no sleep) until done.", + "description": "Generate a video from multi-modal reference inputs (images, videos, audio) used as character / style / motion anchors — NOT as start frames. **Default: kling** (omni-video, sound-capable, up to 7 image / 3 video / 8 audio refs). Specialist: seedance — cinematic look, supports `fast` / `seed` / `resolution` / `auto_duration`, accepts up to 9 image / 3 video / 3 audio refs (combined ≤ 12). Specialist: minimax — S2V-01 single-subject consistent-character mode (exactly 1 reference_image, no videos or audio). Subject must be a HUMAN face (animals/objects fail subject extraction).\n\nReference assets in prompt via <<>>/<<>> (kling) or @Image1/@Video1/@Audio1 (seedance).\n\nSound defaults to on; pass sound=false to suppress. For text- or single-image-driven video use `generate_video` instead.\n\nReturns the result inline when complete (typically 30s–5min). Progress updates are sent as notifications during execution. If the server budget expires before completion, falls back to `{ task_id, status }` — then call `task_status(task_id)` in a tight loop (no Bash, no sleep) until done.", "inputSchema": { "type": "object", "properties": { "provider": { - "description": "Which video model. **Default: kling** — fastest + cheapest, omni-video supports sound + up to 7/3/8 refs. seedance for cinematic look, fast tier, seed control, auto duration.", + "description": "Which video model. **Default: kling** — fastest + cheapest, omni-video supports sound + up to 7/3/8 refs. seedance for cinematic look, fast tier, seed control, auto duration. minimax for S2V-01 single-subject (exactly 1 reference_image). Subject must be a HUMAN face (animals/objects fail subject extraction).", "type": "string", "enum": [ "kling", - "seedance" + "seedance", + "minimax" ] }, "prompt": { @@ -1213,7 +2211,8 @@ ] }, "shots": { - "description": "Multi-shot narrative segments. kling only. Up to 6 shots, each with its own prompt + duration. Sum of `shot.duration` MUST equal the top-level `duration`.", + "description": "Multi-shot narrative segments. kling only. 1-6 shots, each with its own prompt + duration. Sum of `shot.duration` MUST equal the top-level `duration`.", + "minItems": 1, "maxItems": 6, "type": "array", "items": { @@ -1250,7 +2249,7 @@ "maxLength": 2500 }, "watermark": { - "description": "Burn kling's watermark into the output. Default unset = kling applies its own (account-tier-dependent). Pass `false` for clean brand content. Kling only.", + "description": "Burn kling's watermark into the output. Default `false` — clean output by default. Pass `true` to opt back into kling's account-tier-dependent watermark. Kling only.", "type": "boolean" }, "image_types": { @@ -1351,6 +2350,87 @@ "$schema": "http://json-schema.org/draft-07/schema#" } }, + { + "name": "generate_scene_video", + "description": "⚠ DEPRECATED — Renamed to `pika_scene`. Same parameters, same behavior. See `pika_scene` for full documentation. This alias will be removed in a future release.", + "inputSchema": { + "type": "object", + "properties": { + "ingredients": { + "minItems": 2, + "maxItems": 6, + "type": "array", + "items": { + "type": "string", + "format": "uri" + }, + "description": "2-6 ingredient image URLs. The model composites the objects/people from these images into a coherent scene driven by `prompt`." + }, + "prompt": { + "type": "string", + "minLength": 1, + "maxLength": 50000, + "description": "Scene description — what happens with the ingredients (camera, action, mood, environment)." + }, + "ingredients_mode": { + "description": "How faithful to the ingredients. `precise` (default) keeps each ingredient recognizable. `creative` lets the model interpret them loosely.", + "type": "string", + "enum": [ + "precise", + "creative" + ] + }, + "model": { + "description": "Pika model. 2.2 (default, best quality, supports duration / resolution); 2.1 (older); turbo (fastest, cheapest).", + "type": "string", + "enum": [ + "2.2", + "2.1", + "turbo" + ] + }, + "duration": { + "description": "Duration in seconds, model 2.2 only — 5 or 10.", + "type": "integer", + "minimum": -9007199254740991, + "maximum": 9007199254740991 + }, + "resolution": { + "description": "Output resolution, model 2.2 only. Default 720p.", + "type": "string", + "enum": [ + "720p", + "1080p" + ] + }, + "aspect_ratio": { + "description": "Output aspect ratio. Forwarded to pika-api as `aspectRatio`.", + "type": "string", + "enum": [ + "16:9", + "9:16", + "1:1" + ] + }, + "negative_prompt": { + "description": "Optional — describe what to avoid.", + "type": "string", + "maxLength": 500 + }, + "seed": { + "description": "Optional seed for reproducibility.", + "type": "integer", + "minimum": -9007199254740991, + "maximum": 9007199254740991 + } + }, + "required": [ + "ingredients", + "prompt" + ], + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, { "name": "generate_slide_animation", "description": "Generate an animated motion-graphics video from a text prompt. Claude writes the HTML composition (scene structure, typography, GSAP animations, shader transitions); the HyperFrames engine renders it deterministically to MP4. Use for: title cards, product launch teasers, animated logo reveals, explainer slides, text-on-screen intros, designed motion graphics, and any 'slide animation' / 'animated text' / 'animated slides' request. NOT for real-footage video (use `generate_video`), still-image-to-video transitions (use `generate_keyframes_video`), or assembling existing clips (use `edit_concat`). Default returns the HTML CDN URL only (~30s); set `record_video=true` to also render an MP4 via deterministic per-frame seek (~30–90s typical, longer for dense shader work).\n\nReturns the result inline when complete (typically 30s–5min). Progress updates are sent as notifications during execution. If the server budget expires before completion, falls back to `{ task_id, status }` — then call `task_status(task_id)` in a tight loop (no Bash, no sleep) until done.", @@ -1359,7 +2439,7 @@ "properties": { "prompt": { "type": "string", - "maxLength": 1000, + "maxLength": 50000, "description": "Describe the slide deck — style, content, mood, audience. Example: \"A dark energetic product launch for a fitness app. Bold typography, neon accents.\"" }, "brief": { @@ -1440,44 +2520,180 @@ }, { "name": "generate_speech", - "description": "Generate speech from text. Default: minimax-tts (fast). elevenlabs: premium, more voice options.", + "description": "Generate speech from text (default mode=text_to_speech), transform audio to a different voice (mode=speech_to_speech, AGNT-44 #B3), or dub a video into another language (mode=dub, AGNT-44 #B4). Default provider: minimax-tts (fast). elevenlabs: premium, more voice options + the only provider for speech_to_speech / dub. kling-tts (AGNT-44 #A4): Kling voice catalogue; runs in the worker envelope.\n\n**Typed result (sync paths only):** `text_to_speech` and `speech_to_speech` modes return `structuredContent` with measured `duration_seconds`, `word_count`, `char_count`, `pace_wps`, `pace_cps`. Pass `expected_duration_s` to also receive `drift_seconds` + `drift_pct`. Worker-backed paths (`mode=dub`, `provider=kling-tts`) return via `task_status` with the original opaque envelope; v2 typed coverage tracked.", "inputSchema": { "type": "object", "properties": { "provider": { "default": "minimax-tts", - "description": "minimax-tts or elevenlabs. Default minimax-tts.", + "description": "TTS provider. Default minimax-tts; elevenlabs / kling-tts alternatives. speech_to_speech + dub modes require provider=elevenlabs.", "type": "string", "enum": [ "minimax-tts", - "elevenlabs" + "elevenlabs", + "kling-tts" + ] + }, + "mode": { + "description": "What to generate. `text_to_speech` (default) — synthesize speech from text. `speech_to_speech` (AGNT-44 #B3) — transform a source audio recording to a target voice (elevenlabs only; requires voice_id + source_audio_url). `dub` (AGNT-44 #B4) — translate and dub a video into another language (elevenlabs only; requires source_video_url + target_language).", + "type": "string", + "enum": [ + "text_to_speech", + "speech_to_speech", + "dub" ] }, "text": { + "description": "Text to speak. Required for mode=text_to_speech (default); ignored for speech_to_speech / dub. Max 10000 chars.", "type": "string", - "minLength": 1, - "maxLength": 10000, - "description": "Text to speak. Max 10000 chars." + "maxLength": 10000 }, "voice_id": { - "description": "Provider-specific voice ID.", + "description": "Provider-specific voice ID. For mode=speech_to_speech the target voice (required).", "type": "string" }, "language": { "default": "en", "description": "BCP-47 language tag (e.g. 'en', 'zh', 'es').", "type": "string" + }, + "voice_language": { + "description": "kling-tts only: kling-specific voice language code (overrides voice's default language; see kling docs).", + "type": "string" + }, + "speed": { + "description": "kling-tts only: playback speed multiplier (kling defaults).", + "type": "number" + }, + "source_audio_url": { + "description": "mode=speech_to_speech only: HTTPS URL of the source audio (mp3/wav/m4a, ≤50 MB). Worker fetches and uploads as multipart to ElevenLabs STS.", + "type": "string", + "format": "uri" + }, + "remove_background_noise": { + "description": "mode=speech_to_speech only: when true, strip background noise from the input before voice conversion.", + "type": "boolean" + }, + "source_video_url": { + "description": "mode=dub only: HTTPS URL of the source video (mp4/mov). Passed to ElevenLabs as source_url (upstream pulls it).", + "type": "string", + "format": "uri" + }, + "target_language": { + "description": "mode=dub only: ISO-639 target language code (e.g. 'es', 'fr', 'ja', 'de'). Required for dub.", + "type": "string" + }, + "source_language": { + "description": "mode=dub only: ISO-639 source language code, or 'auto' (default) to let ElevenLabs detect.", + "type": "string" + }, + "num_speakers": { + "description": "mode=dub only: number of speakers in the source (0 = auto-detect, default).", + "type": "integer", + "minimum": 0, + "maximum": 20 + }, + "expected_duration_s": { + "description": "Optional — caller's predicted audio duration in seconds. When provided, the response also includes `drift_seconds` (signed actual - expected) and `drift_pct` (fraction). Skills with no schedule can omit. AGNT-175.", + "type": "number", + "minimum": 0 + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" + }, + "outputSchema": { + "type": "object", + "properties": { + "audio_url": { + "type": "string" + }, + "duration_seconds": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + }, + "model_used": { + "type": "string" + }, + "voice_id": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "mode": { + "type": "string", + "enum": [ + "text_to_speech", + "speech_to_speech", + "dub" + ] + }, + "word_count": { + "anyOf": [ + { + "type": "integer", + "minimum": 0, + "maximum": 9007199254740991 + }, + { + "type": "null" + } + ] + }, + "char_count": { + "type": "integer", + "minimum": 0, + "maximum": 9007199254740991 + }, + "pace_wps": { + "anyOf": [ + { + "type": "number", + "minimum": 0 + }, + { + "type": "null" + } + ] + }, + "pace_cps": { + "anyOf": [ + { + "type": "number", + "minimum": 0 + }, + { + "type": "null" + } + ] + }, + "drift_seconds": { + "type": "number" + }, + "drift_pct": { + "type": "number" } }, "required": [ - "text" + "audio_url", + "duration_seconds", + "model_used", + "voice_id", + "provider" ], - "$schema": "http://json-schema.org/draft-07/schema#" + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": {} } }, { "name": "generate_video", - "description": "Generate a video from a text prompt or a single image. One tool, multiple providers via the `provider` enum. **Default: kling** — fastest + cheapest, supports ambient sound/music. Prefer kling unless the caller's request has a concrete reason that maps to a specialist.\n\nFor reference-based generation (multi-ref images / videos / audio as character or style anchors) use `generate_reference_video` instead.\n\nSpecialist alternatives: veo3 — use when the clip needs synthesized natural-language dialogue or voice-over (higher cost). sora — up to 20s, premium quality. seedance — cinematic look, supports `end_image` / `fast` / `seed` / `resolution`. minimax — Hailuo, image_to_video only. pika — parrot i2v.\n\nSound defaults to on for sound-capable providers (kling / veo3 / sora / seedance); pass sound=false to suppress. Passing sound=true on pika or minimax is rejected.\n\nTwo modes: text_to_video (default), image_to_video (requires `image`).\n\nReturns the result inline when complete (typically 30s–5min). Progress updates are sent as notifications during execution. If the server budget expires before completion, falls back to `{ task_id, status }` — then call `task_status(task_id)` in a tight loop (no Bash, no sleep) until done.", + "description": "Generate a video from a text prompt or a single image. One tool, multiple providers via the `provider` enum. **Default: kling** — fastest + cheapest, supports ambient sound/music. Prefer kling unless the caller's request has a concrete reason that maps to a specialist.\n\nFor reference-based generation (multi-ref images / videos / audio as character or style anchors) use `generate_reference_video` instead.\n\nSpecialist alternatives: veo3 — use when the clip needs synthesized natural-language dialogue or voice-over (higher cost). sora — up to 20s, premium quality. seedance — cinematic look, supports `end_image` / `fast` / `seed` / `resolution`. minimax — Hailuo, image_to_video only. pika — fast t2v + i2v on 2.2 / 2.1 / turbo models, no sound.\n\nSound defaults to on for sound-capable providers (kling / veo3 / sora / seedance); pass sound=false to suppress. Passing sound=true on pika or minimax is rejected.\n\nThree modes: text_to_video (default), image_to_video (requires `image`), video_extend (AGNT-44 #A1 / BACK-397 — extend an existing Kling video by 4-5s; requires `source_video_id`, kling only).\n\nReturns the result inline when complete (typically 30s–5min). Progress updates are sent as notifications during execution. If the server budget expires before completion, falls back to `{ task_id, status }` — then call `task_status(task_id)` in a tight loop (no Bash, no sleep) until done.", "inputSchema": { "type": "object", "properties": { @@ -1494,17 +2710,23 @@ ] }, "mode": { - "description": "text_to_video (default): from prompt only. image_to_video: animate a source image as the first frame (requires `image`). minimax requires image_to_video. For reference-based generation (multi-ref images / videos / audio) use the sibling tool `generate_reference_video`.", + "description": "text_to_video (default): from prompt only. image_to_video: animate a source image as the first frame (requires `image`). minimax requires image_to_video. video_extend (AGNT-44 #A1 / BACK-397): extend an existing Kling video by 4-5 seconds (requires `source_video_id`; `prompt` optional; kling only). For reference-based generation (multi-ref images / videos / audio) use the sibling tool `generate_reference_video`.", "type": "string", "enum": [ "text_to_video", - "image_to_video" + "image_to_video", + "video_extend" ] }, "prompt": { + "description": "Description or motion direction for the video. Required for text_to_video / image_to_video; optional for video_extend (when omitted, kling continues the source video's existing motion).", "type": "string", - "minLength": 1, - "description": "Description or motion direction for the video." + "minLength": 1 + }, + "source_video_id": { + "description": "mode=video_extend only: Kling video id of the source clip to extend (must be ≤ 30 days old). Kling only — passing this on other providers is rejected.", + "type": "string", + "minLength": 1 }, "image": { "description": "Source image URL. Required when mode=image_to_video.", @@ -1512,7 +2734,7 @@ "format": "uri" }, "duration": { - "description": "Length in seconds (default 5; **sora defaults to 4** since 5 isn't in its accepted set). Per-provider valid values: kling 5 or 10 · pika 5 or 10 · veo3 5–8 · seedance 3–12 · minimax 6 · **sora 4, 8, or 12 (no other values accepted)**.", + "description": "Length in seconds (default 5; **sora defaults to 4** since 5 isn't in its accepted set; **veo3 defaults to 4** since 5 isn't in its accepted set). Per-provider valid values: kling 5 or 10 · pika 5 or 10 · veo3 4, 6, or 8 · seedance 4–15 · minimax 6 or 10 · **sora 4, 8, or 12 (no other values accepted)**.", "type": "integer", "minimum": 3, "maximum": 20 @@ -1540,7 +2762,7 @@ "format": "uri" }, "seed": { - "description": "Reproducibility seed. seedance only (echoed in result). Rejected on other providers.", + "description": "Reproducibility seed. Accepted on seedance / pika / veo3. Rejected on kling / sora / minimax with a clear error.", "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 @@ -1550,16 +2772,19 @@ "type": "boolean" }, "resolution": { - "description": "Output resolution. seedance only. Default 720p. 1080p requires `fast=false`. Other providers ignore this.", + "description": "Output resolution. Accepted on seedance (480p/720p/1080p), pika (720p/1080p), veo3 (720p/1080p), and minimax (512p/720p/768p/1080p — sent upstream uppercased). Other providers (kling, sora) reject this field with a clear error. seedance fast tier additionally rejects 1080p.", "type": "string", "enum": [ "480p", + "512p", "720p", + "768p", "1080p" ] }, "shots": { - "description": "Multi-shot narrative segments (kling t2v only; rejected on kling i2v). Up to 6 shots, each with its own prompt + duration. Sum of `shot.duration` MUST equal the top-level `duration`.", + "description": "Multi-shot narrative segments (kling t2v only; rejected on kling i2v). 1-6 shots, each with its own prompt + duration. Sum of `shot.duration` MUST equal the top-level `duration`.", + "minItems": 1, "maxItems": 6, "type": "array", "items": { @@ -1591,21 +2816,492 @@ ] }, "negative_prompt": { - "description": "What the model should AVOID generating. Common patterns to combine: general quality → 'blur, distortion, low quality'; clean look → 'watermarks, text overlay, logos'; character work → 'deformed anatomy, extra fingers'; single-shot → 'cuts, scene transitions'. Kling only — leave empty unless you have a specific artifact to suppress.", + "description": "What the model should AVOID generating. Accepted on kling / pika / veo3; rejected on sora / seedance / minimax with a clear error. Common patterns: general quality → 'blur, distortion, low quality'; clean look → 'watermarks, text overlay, logos'; character work → 'deformed anatomy, extra fingers'; single-shot → 'cuts, scene transitions'.", "type": "string", "maxLength": 2500 }, "watermark": { - "description": "Burn kling's watermark into the output. Default unset = kling applies its own (account-tier-dependent). Pass `false` for clean brand content. Kling only.", + "description": "Burn kling's watermark into the output. Default `false` — clean output by default. Pass `true` to opt back into kling's account-tier-dependent watermark. Kling only.", + "type": "boolean" + }, + "quality_mode": { + "description": "Kling quality tier (std = 720p; pro = 1080p; 4k). Kling only.", + "type": "string", + "enum": [ + "std", + "pro", + "4k" + ] + }, + "image_tail": { + "description": "Kling i2v end-frame URL — drives a start→end morph. Requires mode=image_to_video. Kling only.", + "type": "string", + "format": "uri" + }, + "voice_ids": { + "description": "Cloned voice IDs from `clone_voice` for sound generation. Up to 8 (kling upstream cap). Kling only.", + "minItems": 1, + "maxItems": 8, + "type": "array", + "items": { + "type": "string", + "minLength": 1 + } + }, + "kling_model": { + "description": "Kling t2v/i2v model variant. Currently kling-v3 only; kling-v2-6 deferred per plan D6. Kling only.", + "type": "string", + "enum": [ + "kling-v3" + ] + }, + "pika_model": { + "description": "Pika model version. 2.2 = best quality (default); 2.1 / turbo are legacy and ignore duration / resolution. Pika only.", + "type": "string", + "enum": [ + "2.2", + "2.1", + "turbo" + ] + }, + "veo3_model": { + "description": "Veo3 model variant. Default veo-3.0. `-fast` cuts latency + cost; 3.1 is the newer model. veo3 only.", + "type": "string", + "enum": [ + "veo-3.0", + "veo-3.0-fast", + "veo-3.1", + "veo-3.1-fast" + ] + }, + "sora_model": { + "description": "Sora model variant. Default sora-2; sora-2-pro is the higher-fidelity tier (~$1/clip). sora only.", + "type": "string", + "enum": [ + "sora-2", + "sora-2-pro" + ] + }, + "size": { + "description": "Sora output resolution grid. When omitted, falls back to the aspect_ratio-derived selection. sora only.", + "type": "string", + "enum": [ + "720x1280", + "1280x720", + "1024x1792", + "1792x1024" + ] + }, + "character_id": { + "description": "Sora character ID (from `create_sora_character` — separate atomic tool, future work). sora only.", + "type": "string", + "minLength": 1 + }, + "minimax_model": { + "description": "Minimax video model variant. Default MiniMax-Hailuo-2.3-Fast. I2V-01-Director adds camera-movement tokens. minimax only.", + "type": "string", + "enum": [ + "MiniMax-Hailuo-2.3", + "MiniMax-Hailuo-2.3-Fast", + "MiniMax-Hailuo-02", + "I2V-01-Director", + "I2V-01-live", + "I2V-01" + ] + }, + "last_frame_image": { + "description": "Minimax end-frame image URL (start→end morph). minimax only.", + "type": "string", + "format": "uri" + }, + "prompt_optimizer": { + "description": "Toggle minimax's server-side prompt rewrite. Default true. minimax only.", "type": "boolean" } }, + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "generate_video_addition", + "description": "⚠ DEPRECATED — Renamed to `pika_addition`. Same parameters, same behavior. See `pika_addition` for full documentation. This alias will be removed in a future release.", + "inputSchema": { + "type": "object", + "properties": { + "video": { + "type": "string", + "format": "uri", + "description": "Source video URL (mp4 / mov / webm) to add an element into." + }, + "prompt": { + "type": "string", + "minLength": 1, + "maxLength": 50000, + "description": "What to add, e.g. 'a small dog walking across the foreground'." + }, + "object_image": { + "type": "string", + "format": "uri", + "description": "Required reference image of the object to composite in. Despite the canonical pika-video CLI documenting this as optional, pika-api/generate/pikadditions returns 422 'Unprocessable entity' without it (verified 2026-05-10, BACK-345). For prompt-only object generation use `pika_swap` with `region_text` instead." + }, + "negative_prompt": { + "type": "string", + "maxLength": 500 + }, + "seed": { + "type": "integer", + "minimum": -9007199254740991, + "maximum": 9007199254740991 + } + }, "required": [ + "video", + "prompt", + "object_image" + ], + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "generate_video_sora_edit", + "description": "⚠ DEPRECATED — Use `sora_edit({mode: \"edit\"})` instead. Same parameters, same behavior. This alias is kept for one release.", + "inputSchema": { + "type": "object", + "properties": { + "source_video_id": { + "type": "string", + "minLength": 1, + "description": "Sora upstream task id (e.g. `video_abc...`) to re-prompt." + }, + "prompt": { + "type": "string", + "minLength": 1, + "maxLength": 1500, + "description": "New prompt describing the edits." + }, + "seconds": { + "description": "Optional output duration. Sora only accepts 4 / 8 / 12. Defaults to whatever the upstream's billing model picks.", + "type": "string", + "enum": [ + "4", + "8", + "12" + ] + } + }, + "required": [ + "source_video_id", "prompt" ], "$schema": "http://json-schema.org/draft-07/schema#" } }, + { + "name": "generate_video_sora_extension", + "description": "⚠ DEPRECATED — Use `sora_edit({mode: \"extension\"})` instead. Same parameters, same behavior. This alias is kept for one release.", + "inputSchema": { + "type": "object", + "properties": { + "source_video_id": { + "type": "string", + "minLength": 1, + "description": "Sora upstream task id of the video to extend." + }, + "prompt": { + "type": "string", + "minLength": 1, + "maxLength": 1500, + "description": "Prompt for the extension segment." + }, + "seconds": { + "description": "Extension duration (default `4`). Sora only accepts 4 / 8 / 12.", + "type": "string", + "enum": [ + "4", + "8", + "12" + ] + } + }, + "required": [ + "source_video_id", + "prompt" + ], + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "generate_video_sora_remix", + "description": "⚠ DEPRECATED — Use `sora_edit({mode: \"remix\"})` instead. Same parameters, same behavior. This alias is kept for one release.", + "inputSchema": { + "type": "object", + "properties": { + "source_video_id": { + "type": "string", + "minLength": 1, + "description": "Sora upstream task id of the video to remix." + }, + "prompt": { + "type": "string", + "minLength": 1, + "maxLength": 1500, + "description": "New prompt driving the remix." + } + }, + "required": [ + "source_video_id", + "prompt" + ], + "$schema": "http://json-schema.org/draft-07/schema#" + } + }, + { + "name": "generate_video_swap", + "description": "⚠ DEPRECATED — Renamed to `pika_swap`. Same parameters, same behavior. See `pika_swap` for full documentation. This alias will be removed in a future release.", + "inputSchema": { + "type": "object", + "properties": { + "video": { + "type": "string", + "format": "uri", + "description": "Source video URL." + }, + "prompt": { + "type": "string", + "minLength": 1, + "maxLength": 50000, + "description": "What to replace the region with." + }, + "mask": { + "description": "Mask image URL (white = replace, black = keep). Mutually exclusive with `region_text`.", + "type": "string", + "format": "uri" + }, + "region_text": { + "description": "Free-text description of the region to replace, e.g. 'the person wearing red'. 1-500 chars after trim (whitespace-only rejected). Mutually exclusive with `mask`. At least one of `mask` or `region_text` is required.", + "type": "string", + "minLength": 1, + "maxLength": 500 + }, + "replacement_image": { + "description": "Optional reference image of the replacement subject.", + "type": "string", + "format": "uri" + }, + "negative_prompt": { + "type": "string", + "maxLength": 500 + }, + "seed": { + "type": "integer", + "minimum": -9007199254740991, + "maximum": 9007199254740991 + } + }, + "required": [ + "video", + "prompt" + ], + "$schema": "http://json-schema.org/draft-07/schema#", + "oneOf": [ + { + "required": [ + "mask" + ] + }, + { + "required": [ + "region_text" + ] + } + ] + } + }, + { + "name": "html_to_pdf", + "description": "Render an HTML document (or array of body fragments) to PDF, PNG, or JPG via a persistent server-side Chromium subprocess. Single-html mode is preferred (native @page support). body_pages mode renders pages in parallel and merges via PyPDF — no cross-page CSS counters / scripts / shared state. Assets are server-fetched and served to Chromium via route interception (deny-by-default). Async by default; sync mode requires preflight (html ≤100KB, single page, ≤10 assets, no external @import).\n\nReturns the result inline when complete (typically 30s–5min). Progress updates are sent as notifications during execution. If the server budget expires before completion, falls back to `{ task_id, status }` — then call `task_status(task_id)` in a tight loop (no Bash, no sleep) until done.", + "inputSchema": { + "type": "object", + "properties": { + "html": { + "description": "Complete HTML document as a string. Mutually exclusive with body_pages. All external assets (fonts, images, stylesheets) referenced via https:// are pre-fetched and inlined before Chromium renders — no live network access occurs during the render. Data URIs are served as-is. JavaScript is disabled in the render context. Max 10 MB.", + "type": "string", + "minLength": 1, + "maxLength": 10485760 + }, + "body_pages": { + "description": "Array of per-page HTML body fragments (1–50). Each fragment is wrapped in a full HTML document using shared_head, rendered by its own Chromium subprocess, and merged into a single PDF via PyPDF. Pages are rendered in parallel. No cross-page CSS counters, scripts, or shared DOM state. Requires shared_head. Mutually exclusive with html.", + "minItems": 1, + "maxItems": 50, + "type": "array", + "items": { + "type": "string", + "minLength": 1 + } + }, + "shared_head": { + "description": "HTML content injected into every body_pages page (e.g.