{"id":"e740a769-0184-4af6-b11c-c181f962d11a","entityType":"agent","slug":"clawhub-gxcun17-skywork-ppt","name":"Skywork PPT","canonicalUrl":"https://www.xpersona.co/agent/clawhub-gxcun17-skywork-ppt","canonicalPath":"/agent/clawhub-gxcun17-skywork-ppt","generatedAt":"2026-10-09T14:24:31.848Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T03:14:26.946Z","emptyReason":null},"description":"Skywork PPT (skywork) - Use when the user wants to work with PowerPoint presentations. Triggers: (1) Generate a new PPT from a topic — 'generate a PPT', 'cre...","descriptionLabel":"Source description","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 6.8K downloads reported by the source. Last updated 10/9/2026.","installCommand":"clawhub skill install s174hwb34r6ncgdm62n09a9tbd83hn5x:skywork-ppt","sourceUrl":"https://clawhub.ai/gxcun17/skywork-ppt","homepage":"https://clawhub.ai/gxcun17/skills/skywork-ppt","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/gxcun17/skywork-ppt","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/gxcun17/skills/skywork-ppt","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":71,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"Skywork PPT technical dossier on Xpersona with agent coverage, OPENCLEW support, and live trust metadata."},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-09T03:14:26.946Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T03:14:26.946Z","emptyReason":null},"stars":null,"forks":null,"downloads":6796,"packageName":null,"latestVersion":"1.0.9","tractionLabel":"6.8K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T03:14:26.946Z","emptyReason":null},"lastUpdatedAt":"2026-10-09T03:14:26.946Z","lastCrawledAt":"2026-10-09T03:14:26.946Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-10T03:14:26.946Z","lastVerifiedAt":null,"highlights":[{"version":"1.0.9","createdAt":"2026-04-23T12:59:48.398Z","changelog":"**Added support for converting NotebookLM-exported files to editable PPTX.** - New capability: Convert .pptx or .pdf exported from NotebookLM to fully editable PPTX format (Layer 5). - Added script: scripts/run_editable_convert.py to handle the conversion process. - Added workflow guide: workflow_convert_editable.md. - Updated skill description and workflow to include the new conversion feature.","fileCount":17,"zipByteSize":38593},{"version":"1.0.8","createdAt":"2026-04-10T13:37:21.791Z","changelog":"skywork-ppt 1.0.8 - Improved description for broader language/cross-lingual trigger support; trigger phrases now consolidated and clearer. - API key configuration instructions clarified (skill requires SKYWORK_API_KEY configured before use). - No logic or functional changes; documentation and trigger keyword improvements only. - No file changes detected in this release.","fileCount":14,"zipByteSize":32344},{"version":"1.0.7","createdAt":"2026-04-10T02:27:06.396Z","changelog":"No functional changes in this version. - Documentation and formatting updates only. - No changes to code, features, or workflows. - All usage and behavior remain the same.","fileCount":14,"zipByteSize":32320},{"version":"1.0.6","createdAt":"2026-04-09T12:08:18.926Z","changelog":"skywork-ppt 1.0.6 - Added \"Skywork PPT (skywork)\" to the skill description for clarity. - No functional or behavioral changes; documentation only. - All workflows, capabilities, and usage remain unchanged.","fileCount":14,"zipByteSize":32372},{"version":"1.0.5","createdAt":"2026-04-02T02:54:33.845Z","changelog":"Version 1.0.5 of skywork-ppt skill - Added a clear Privacy & Remote Calls notice highlighting which operations send data remotely versus local-only operations. - Noted that Layer 1, 2, and 4 upload files and user queries to the Skywork service; Layer 3 is strictly local. - Explained periodic backend status polling behavior during generation/edit processes. - No code changes; documentation improved for transparency and user guidance.","fileCount":14,"zipByteSize":32365},{"version":"1.0.4","createdAt":"2026-04-01T13:45:53.155Z","changelog":"Version 1.0.4 - Switched authentication from token-based login to explicit SKYWORK_API_KEY config; updated prerequisites and error handling accordingly. - Added instructions to obtain and configure the API key (see new references/apikey-fetch.md). - Updated description and triggers to clarify multilingual support for generation, editing, and local file operations. - Added scripts/constant.py and removed scripts/config.py to support the API key flow. - Metadata now specifies SKYWORK_API_KEY as required environment variable.","fileCount":14,"zipByteSize":32031},{"version":"1.0.3","createdAt":"2026-03-19T13:32:44.209Z","changelog":"- Removed environment variable and config requirements from metadata. - Now only requires the presence of a Python 3 binary (>=3.8) for operation. - All functional capabilities and documentation remain unchanged.","fileCount":13,"zipByteSize":33713},{"version":"1.0.2","createdAt":"2026-03-19T03:03:47.929Z","changelog":"Skywork-ppt 1.0.2 - Added skill metadata section specifying required environment variables, binaries, and config files. - Declared primary environment variable (`SKYBOT_TOKEN`) in metadata. - No functional or workflow changes to the skill logic.","fileCount":13,"zipByteSize":33786}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s174hwb34r6ncgdm62n09a9tbd83hn5x:skywork-ppt","setupComplexity":"low","setupSteps":["Install using `clawhub skill install s174hwb34r6ncgdm62n09a9tbd83hn5x:skywork-ppt` in an isolated environment before connecting it to live workloads.","No published capability contract is available yet, so validate auth and request/response behavior manually.","Review the upstream CLAWHUB listing at https://clawhub.ai/gxcun17/skywork-ppt before using production credentials."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-gxcun17-skywork-ppt/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-gxcun17-skywork-ppt/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-gxcun17-skywork-ppt/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-gxcun17-skywork-ppt/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-gxcun17-skywork-ppt/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-gxcun17-skywork-ppt/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-09T14:24:31.844Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-gxcun17-skywork-ppt/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-gxcun17-skywork-ppt/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-gxcun17-skywork-ppt/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-gxcun17-skywork-ppt/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T03:14:26.946Z","emptyReason":null},"readme":"Skill: Skywork PPT\n\nOwner: gxcun17\n\nSummary: Skywork PPT (skywork) - Use when the user wants to work with PowerPoint presentations. Triggers: (1) Generate a new PPT from a topic — 'generate a PPT', 'cre...\n\nTags: latest:1.0.9\n\nVersion history:\n\nv1.0.9 | 2026-04-23T12:59:48.398Z | user\n\n**Added support for converting NotebookLM-exported files to editable PPTX.**\n\n- New capability: Convert .pptx or .pdf exported from NotebookLM to fully editable PPTX format (Layer 5).\n- Added script: scripts/run_editable_convert.py to handle the conversion process.\n- Added workflow guide: workflow_convert_editable.md.\n- Updated skill description and workflow to include the new conversion feature.\n\nv1.0.8 | 2026-04-10T13:37:21.791Z | user\n\nskywork-ppt 1.0.8\n\n- Improved description for broader language/cross-lingual trigger support; trigger phrases now consolidated and clearer.\n- API key configuration instructions clarified (skill requires SKYWORK_API_KEY configured before use).\n- No logic or functional changes; documentation and trigger keyword improvements only.\n- No file changes detected in this release.\n\nv1.0.7 | 2026-04-10T02:27:06.396Z | user\n\nNo functional changes in this version.\n\n- Documentation and formatting updates only.\n- No changes to code, features, or workflows.\n- All usage and behavior remain the same.\n\nv1.0.6 | 2026-04-09T12:08:18.926Z | user\n\nskywork-ppt 1.0.6\n\n- Added \"Skywork PPT (skywork)\" to the skill description for clarity.\n- No functional or behavioral changes; documentation only.\n- All workflows, capabilities, and usage remain unchanged.\n\nv1.0.5 | 2026-04-02T02:54:33.845Z | user\n\nVersion 1.0.5 of skywork-ppt skill\n\n- Added a clear Privacy & Remote Calls notice highlighting which operations send data remotely versus local-only operations.\n- Noted that Layer 1, 2, and 4 upload files and user queries to the Skywork service; Layer 3 is strictly local.\n- Explained periodic backend status polling behavior during generation/edit processes.\n- No code changes; documentation improved for transparency and user guidance.\n\nv1.0.4 | 2026-04-01T13:45:53.155Z | user\n\nVersion 1.0.4\n\n- Switched authentication from token-based login to explicit SKYWORK_API_KEY config; updated prerequisites and error handling accordingly.\n- Added instructions to obtain and configure the API key (see new references/apikey-fetch.md).\n- Updated description and triggers to clarify multilingual support for generation, editing, and local file operations.\n- Added scripts/constant.py and removed scripts/config.py to support the API key flow.\n- Metadata now specifies SKYWORK_API_KEY as required environment variable.\n\nv1.0.3 | 2026-03-19T13:32:44.209Z | user\n\n- Removed environment variable and config requirements from metadata.\n- Now only requires the presence of a Python 3 binary (>=3.8) for operation.\n- All functional capabilities and documentation remain unchanged.\n\nv1.0.2 | 2026-03-19T03:03:47.929Z | user\n\nSkywork-ppt 1.0.2\n\n- Added skill metadata section specifying required environment variables, binaries, and config files.\n- Declared primary environment variable (`SKYBOT_TOKEN`) in metadata.\n- No functional or workflow changes to the skill logic.\n\nv1.0.1 | 2026-03-17T10:55:02.689Z | user\n\nskywork-ppt v1.0.1\n\n- Minor improvements and optimizations.\n- No changes to functionality or user experience.\n\nv1.0.0 | 2026-03-16T11:38:41.344Z | user\n\nSkywork-ppt 1.0.0 — Initial Release\n\n- Enables AI-powered PowerPoint (.pptx) generation, style template imitation, editing, and local slide operations via simple commands.\n- Supports four main workflows: new PPT creation, template-based generation, file editing, and local file manipulation.\n- Provides detailed routing instructions based on user intent and clear authentication requirements.\n- Includes mandatory environment checks for Python 3.8+ and automatic dependency installation.\n- Guides error handling for insufficient account benefit situations.\n\nArchive index:\n\nArchive v1.0.9: 17 files, 38593 bytes\n\nFiles: references/apikey-fetch.md (2693b), scripts/constant.py (81b), scripts/local_pptx_ops.py (13562b), scripts/parse_file.py (6798b), scripts/run_editable_convert.py (9270b), scripts/run_ppt_write.py (15459b), scripts/skywork_auth.py (284b), scripts/upload_files.py (4900b), scripts/web_search.py (2493b), skill-card.md (2381b), SKILL.md (10486b), workflow_convert_editable.md (4013b), workflow_edit.md (4275b), workflow_generate.md (9584b), workflow_imitate.md (7973b), workflow_local.md (3981b), _meta.json (130b)\n\nFile v1.0.9:SKILL.md\n\n---\nname: Skywork-ppt\ndescription: \"Skywork PPT (skywork) - Use when the user wants to work with PowerPoint presentations. Triggers: (1) Generate a new PPT from a topic — 'generate a PPT', 'create a presentation about X', 'make slides', '帮我做个PPT', '生成演示文稿', 'PPTを作って', 'スライドを作って', 'PPT 만들어줘', '슬라이드 만들어줘'; (2) Imitate an existing .pptx style/template — 'use this template', 'imitate this PPT/style', '用这个模板', '仿照这个PPT', 'このテンプレートを使って', '이 템플릿 써줘'; (3) Edit existing PPT via natural language — 'modify slide N', 'change background', 'add a slide', 'make it more beautiful', '修改第N页', '更换背景', '新增一页', '美化一下', 'N枚目を修正', '背景を変えて', 'きれいにして', 'N번 슬라이드 수정', '배경 바꿔줘'; (4) Convert NotebookLM-exported pptx/pdf into editable pptx — 'make this notebooklm ppt editable', 'convert notebooklm export to editable pptx', '把这个notebooklm导出的pptx改成可编辑pptx', '把这个pdf转成可编辑pptx'; (5) Local .pptx file ops — 'delete slide N', 'reorder slides', 'merge pptx', 'extract slides', 'how many slides', '删除第N页', '调整顺序', '合并PPT', '提取幻灯片', 'スライドを削除/並べ替え/結合/抽出', '슬라이드 삭제/순서 변경/합치기/추출'.\"\nmetadata:\n  openclaw:\n    requires:\n      bins:\n        - python3\n      env:\n        - SKYWORK_API_KEY\n    primaryEnv: SKYWORK_API_KEY\n---\n\n# PPT Write Skill\n\nFive capabilities: **generate**, **template imitation**, **edit existing PPT**, **convert NotebookLM export to editable PPTX**, and **local file operations**.\n\n---\n\n## Prerequisites\n\n### API Key Configuration (Required First)\nThis skill requires a **SKYWORK_API_KEY** to be configured before use.\n\nIf you don't have an API key yet, please visit:\n**https://skywork.ai**\n\nFor detailed setup instructions, see:\n[references/apikey-fetch.md](references/apikey-fetch.md)\n\n---\n\n## Privacy & Remote Calls (Read Before Use)\n\n- **Remote upload & processing**: Layers 1/2/4/5 upload local files and send the full, verbatim user query to the Skywork service. Avoid sensitive or confidential content unless you trust the remote service and its data handling policies.\n- **Polling behavior**: The generation/edit workflows include periodic status polling (about every 5 seconds) while waiting for backend jobs. This is expected.\n\n---\n\n## Routing — Identify the user's intent first\n\n| User intent | Which path |\n|-------------|------------|\n| Generate a new PPT from a topic, set of requirements or reference files | **Layer 1** — Generate |\n| Use an existing .pptx as a layout/style template to create a new presentation | **Layer 2** — Imitate |\n| Edit an existing PPT: modify slides, add slides, change style, split/merge | **Layer 4** — Edit |\n| Convert a NotebookLM-exported `.pptx` or `.pdf` into an editable `.pptx` | **Layer 5** — Convert to editable PPTX |\n| Delete / reorder / extract / merge slides in a local file (no backend) | **Layer 3** — Local ops |\n\n---\n\n## Environment check (always run this first)\n\n**This skill requires Python 3 (>=3.8). Run the following before any script to locate a valid Python binary and install dependencies.**\n\n```bash\nPYTHON_CMD=\"\"\nfor cmd in python3 python python3.13 python3.12 python3.11 python3.10 python3.9 python3.8; do\n  if command -v \"$cmd\" &>/dev/null && \"$cmd\" -c \"import sys; exit(0 if sys.version_info >= (3,8) else 1)\" 2>/dev/null; then\n    PYTHON_CMD=\"$cmd\"\n    break\n  fi\ndone\n\nif [ -z \"$PYTHON_CMD\" ]; then\n  echo \"ERROR: Python 3.8+ not found.\"\n  echo \"Install on macOS: brew install python3  or visit https://www.python.org/downloads/\"\n  exit 1\nfi\n\necho \"Found Python: $PYTHON_CMD ($($PYTHON_CMD --version))\"\n\n$PYTHON_CMD -m pip install -q --break-system-packages python-pptx\necho \"Dependencies ready.\"\n```\n\n> After this check, replace `python` with the discovered `$PYTHON_CMD` (e.g. `python3`) in all subsequent commands.\n\n---\n\n## Layer 1 — Generate PPT\n\n### Steps\n0. **REQUIRED FIRST STEP** — Read [workflow_generate.md](workflow_generate.md) NOW, before taking any other action. After reading, output exactly: `✅ workflow_generate.md loaded.` — then proceed.\n1. **Environment check** — run the check above to get `$PYTHON_CMD`.\n2. **Upload reference files** (if the user provides local files as content source) — parse the file using tool in script/parse_file.py and pass the result to `--files`. See the `--files` note below.\n3. **Web search** (required if no relevant content is already in the conversation) — call web_search tool in script to search the topic and distill results into a `reference-file` file of ≤ 2000 words.\n4. **Run the script**:\n   > **Important**: set exec tool `yieldMs` to `600000` (10 minutes).\n5. **Deliver** — provide the absolute `.pptx` path and the download URL.\n\n---\n\n## Layer 2 — Imitate PPT (template-based generation)\n\n### Steps\n0. **REQUIRED FIRST STEP** - Read [workflow_imitate.md](workflow_imitate.md) immidiately before any action you do!!!\n1. **Environment check** — run the check above to get `$PYTHON_CMD`.\n2. **Locate the template** — extract the absolute path of the local `.pptx` from the user's message; ask the user if it's unclear.\n3. **Upload the template** — upload it and extract `TEMPLATE_URL` from the output.\n4. **Upload reference files** (if the user provides additional local files as content source) — parse the file using tool in script/parse_file.py and pass the result to `--files`. See the `--files` \n5. **Web search** (required if no relevant content is already in the conversation) — call web_search tool in script to search the new topic and distill results into a `reference-file` file of ≤ 2000 words.\n6. **Run the script**:\n   > **Important**: set exec tool `yieldMs` to `600000` (10 minutes).\n7. **Deliver** — provide the absolute `.pptx` path, the download URL, and the template filename used.\n\n---\n\n## Layer 4 — Edit PPT (AI-powered modification)\n\nUse this layer when the user wants to modify an existing PPT using natural language. Requires an OSS/CDN URL of the PPTX (from a previous generation or upload).\n\n### Steps\n0. **Detailed workflow** - Read [workflow_edit.md](workflow_edit.md) immediately before any action you do!!!\n1. **Environment check** — run the check above to get `$PYTHON_CMD`.\n2. **Get PPTX URL** — from the user's message or upload a local file first.\n3. **Run the script** with `--pptx-url`:\n   ```bash\n   $PYTHON_CMD scripts/run_ppt_write.py \"edit instruction\" \\\n     --language Chinese \\\n     --pptx-url \"https://cdn.example.com/file.pptx\" \\\n     -o /absolute/path/output.pptx\n   ```\n   > **Important**: set exec tool `yieldMs` to `600000` (10 minutes).\n4. **Deliver** — provide download link, local path, and summary of changes.\n\n---\n\n## Layer 5 — Convert NotebookLM Export to Editable PPTX\n\nUse this layer when the user provides a local `.pptx` or `.pdf` exported from NotebookLM and wants an editable `.pptx`.\n\n### Steps\n0. **Detailed workflow** - Read [workflow_convert_editable.md](workflow_convert_editable.md) immediately before any action you do!!!\n1. **Environment check** — run the check above to get `$PYTHON_CMD`.\n2. **Locate the source file** — extract the absolute path of the local `.pptx` or `.pdf`; ask the user if the path is unclear.\n3. **Upload the source file** — upload it and extract `SOURCE_URL` from the output.\n4. **Run the script**:\n   ```bash\n   $PYTHON_CMD scripts/run_editable_convert.py \\\n     --file-url \"https://cdn.example.com/source.pptx\" \\\n     --file-type \"pptx\" \\\n     -o /absolute/path/output_editable.pptx\n   ```\n   > **Important**: set exec tool `yieldMs` to `600000` (10 minutes).\n5. **Deliver** — provide download link, local path, and the original filename used as the source.\n\n---\n\n## Layer 3 — PPT File operations\n\n```bash\n# Inspect slide count and titles\n$PYTHON_CMD scripts/local_pptx_ops.py info --file my.pptx\n\n# Delete slides (1-based index; supports ranges like 3,5,7-9; omit -o to overwrite in place)\n$PYTHON_CMD scripts/local_pptx_ops.py delete --file my.pptx --slides 3,5,7-9 -o trimmed.pptx\n\n# Reorder slides (must list every slide, no omissions)\n$PYTHON_CMD scripts/local_pptx_ops.py reorder --file my.pptx --order 2,1,4,3,5\n\n# Extract a subset of slides into a new file\n$PYTHON_CMD scripts/local_pptx_ops.py extract --file my.pptx --slides 1-3 -o subset.pptx\n\n# Merge multiple files\n$PYTHON_CMD scripts/local_pptx_ops.py merge --files a.pptx b.pptx -o merged.pptx\n```\n\nRead [workflow_local.md](workflow_local.md) immidiately before any action you do!!!\n\n---\n\n## Error Handling\n\n- **Insufficient benefit**: When calling scripts (generate, imitate, edit, or convert to editable), the script or log may show a message like `Insufficient benefit. Please upgrade your account at {url}`, meaning the user's benefit level does not meet the requirement for this skill.\n\n### How to reply when benefit is insufficient\n\nWhen you detect the above, **reply in the user's current language** — do not echo the English message. Use this pattern:\n\n- Convey: \"Sorry, PPT generation failed. This skill requires upgrading your Skywork membership to use.\" then a single call-to-action link.\n- **Format**: One short sentence in the user's language + a link like `[Upgrade now →](url)` or the equivalent in their language .\n- **URL**: Extract the upgrade URL from the log/script output (e.g. the `at https://...` part).\n\n> Note: Only suggest upgrading when the error is **Insufficient benefit**. For auth errors like `NO_TOKEN` / `INVALID_TOKEN` / `401` / “invalid API key”, keep the error code / raw message and guide users to update `SKYWORK_API_KEY`. **Do not** suggest upgrading membership.\n\n---\n\n## Dependencies\n\n- **Python 3.8+** (required) — `python3` / `python` must be on PATH\n- Layer 3 local ops: `pip install python-pptx --break-system-packages`\n\n(The environment check step installs all required dependencies automatically.)\n\n---\n\n## Which layer to trigger?\n\n| Scenario | Use |\n|----------|-----|\n| Generate a PPT from a topic or existing reference files | Layer 1 |\n| Imitate the layout/style of an existing .pptx | Layer 2 |\n| Edit/modify an existing PPT via natural language | Layer 4 |\n| Convert NotebookLM-exported `.pptx` / `.pdf` into editable `.pptx` | Layer 5 |\n| Delete / reorder / extract / merge local .pptx files (no backend) | Layer 3 |\n\nFile v1.0.9:_meta.json\n\n{\n  \"ownerId\": \"kn70ct0m3p4538a9t49cjcwern82ky02\",\n  \"slug\": \"skywork-ppt\",\n  \"version\": \"1.0.9\",\n  \"publishedAt\": 1776949188398\n}\n\nFile v1.0.9:references/apikey-fetch.md\n\n# Skywork API Key Setup Guide\n\n## SKYWORK_API_KEY Not Configured\n\nWhen the `SKYWORK_API_KEY` environment variable is not set, follow these steps:\n\n### 1. Get API Key\n\nVisit the Skywork website and sign in to your account:\n\n**https://skywork.ai**\n\n- Log in with your Skywork account\n- Open account / Settings / API Key (**https://skywork.ai/?openApiKeySetting=1**)\n- Create or copy your **API key**\n\nIf your organization uses a separate console or test environment, use the URL and credentials your team provides.\n\n### 2. Configure OpenClaw\n\nEdit the OpenClaw configuration file: `~/.openclaw/openclaw.json`\n\nIn current OpenClaw, Skywork skills store the key under `skills.entries.<Skill Name>.apiKey` (not under `env`).\nOpenClaw will inject this value into the skill's `SKYWORK_API_KEY` environment when `primaryEnv` matches.\nAdd or merge the following structure (adjust the skill name to match the installed skill):\n\n```json\n{\n  \"skills\": {\n    \"entries\": {\n      \"Skywork-ppt\": {\n        \"enabled\": true,\n        \"apiKey\": \"your_actual_skywork_api_key_here\"\n      }\n    }\n  }\n}\n```\n\nReplace `\"your_actual_skywork_api_key_here\"` with your real key.\n\nFor multiple Skywork skills, repeat the same `apiKey` field on each skill entry.\n\n### 3. Configure Claude Code\n\nIf you are using Claude Code, use one of these lightweight options:\n\n**Option A — shell environment**\n\nExport the API key before running the skill:\n\n```bash\nexport SKYWORK_API_KEY=\"your_actual_skywork_api_key_here\"\n```\n\nTo persist it across sessions, add the same line to `~/.zshrc` or `~/.bashrc`, then reload the shell.\n\n**Option B — Claude Code settings**\n\nAdd the variable to `~/.claude/settings.json`:\n\n```json\n{\n  \"env\": {\n    \"SKYWORK_API_KEY\": \"your_actual_skywork_api_key_here\"\n  }\n}\n```\n\nUse the method that best matches how you run Claude Code.\n\n### 4. Verify Configuration\n\n```bash\n# Check that the environment variable is available\necho \"$SKYWORK_API_KEY\"\n```\n\nFor OpenClaw, you can also validate the config file:\n\n```bash\ncat ~/.openclaw/openclaw.json | python3 -m json.tool\n```\n\n### 5. Restart OpenClaw\n\n```bash\nopenclaw gateway restart\n```\n\n## Troubleshooting\n\n- Ensure `~/.openclaw/openclaw.json` exists and is valid JSON\n- Ensure `SKYWORK_API_KEY` is available in Claude Code through your shell or `~/.claude/settings.json`\n- Confirm the API key is active and not expired\n- Check Skywork account status, membership, or quota if requests fail with auth or benefit errors\n- Restart OpenClaw after configuration changes\n\n**Recommended**: Use the setup method that matches your runtime. OpenClaw should use the OpenClaw config file; Claude Code can use either the shell environment or `~/.claude/settings.json`.\n\nFile v1.0.9:skill-card.md\n\n## Description:\n\nSkywork PPT helps agents generate new PowerPoint presentations, imitate an existing presentation style, edit decks through natural-language requests, convert NotebookLM exports to editable PPTX files, and run local PPTX operations.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[gxcun17](https://clawhub.ai/user/gxcun17)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers and external users use this skill to create, transform, and inspect PowerPoint presentations from topics, templates, existing decks, NotebookLM exports, and local PPTX files.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Skywork-backed workflows may send selected prompts and files to Skywork or cloud storage.\n\nMitigation: Use only with content approved for that service, and avoid confidential decks unless organizational policy permits it.\n\nRisk: The skill requires a Skywork API key for remote workflows.\n\nMitigation: Store the key in a protected secret store, use a revocable key, and avoid printing it in logs.\n\nRisk: Local slide-editing operations can modify presentation files.\n\nMitigation: Use explicit output paths or keep backups before running operations that may overwrite local decks.\n\nRisk: The security verdict is suspicious because the skill uploads local documents and can modify files without strong safeguards.\n\nMitigation: Review the skill before deployment and run dependencies in a virtual environment.\n\n## Reference(s):\n\n- [Skywork API key setup](references/apikey-fetch.md)\n- [Skywork AI](https://skywork.ai)\n- [ClawHub skill page](https://clawhub.ai/gxcun17/skills/skywork-ppt)\n\n## Skill Output:\n\n**Output Type(s):** [text, markdown, code, shell commands, configuration, files, guidance]\n\n**Output Format:** [Markdown guidance with shell commands and generated or modified PPTX files]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Requires Python 3 and SKYWORK_API_KEY for Skywork-backed workflows; local PPTX operations use python-pptx.]\n\n## Skill Version(s):\n\n1.0.9 (source: server release evidence)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nFile v1.0.9:workflow_convert_editable.md\n\n# Convert NotebookLM Export to Editable PPTX Workflow\n\nUse this workflow when the user provides a local `.pptx` or `.pdf` file and wants to convert a NotebookLM-exported deck into an editable `.pptx`.\n\nFollow these steps in order: identify the source file → upload it → run the conversion script in background → **read the log every 5 seconds and report progress** → deliver.\n\n---\n\n## 1. Confirm the source file\n\nThe user must provide a local `.pptx` or `.pdf` file.\n\n- If the file path is ambiguous, ask the user for the full absolute path.\n- If the file extension is not `.pptx` or `.pdf`, stop and explain that this workflow only supports those two input types.\n\n---\n\n## 2. Upload the source file to OSS\n\n```bash\n$PYTHON_CMD scripts/upload_files.py \"/absolute/path/to/source.pptx\"\n```\n\nor\n\n```bash\n$PYTHON_CMD scripts/upload_files.py \"/absolute/path/to/source.pdf\"\n```\n\n- Extract the OSS URL from the `[OK] ... -> https://...` output line.\n- Call this value `SOURCE_URL`.\n\n---\n\n## 3. Run the conversion script\n\nRun in the **background**, then read the progress log file every 5 seconds until done.\n\n### 3a. Choose a log path and start in background\n\n```bash\nPPT_LOG=/tmp/ppt_editable_$(date +%s).log\n\n$PYTHON_CMD scripts/run_editable_convert.py \\\n  --file-url \"SOURCE_URL\" \\\n  --file-type \"pptx\" \\\n  --log_path \"$PPT_LOG\" \\\n  -o /absolute/path/to/output_editable.pptx \\\n  > /dev/null 2>&1 &\n\necho \"Log: $PPT_LOG\"\n```\n\nor for pdf:\n\n```bash\n$PYTHON_CMD scripts/run_editable_convert.py \\\n  --file-url \"SOURCE_URL\" \\\n  --file-type \"pdf\" \\\n  --log_path \"$PPT_LOG\" \\\n  -o /absolute/path/to/output_editable.pptx \\\n  > /dev/null 2>&1 &\n```\n\n- **`--file-url`** (required): OSS URL of the uploaded source file.\n- **`--file-type`** (recommended): explicitly pass `pptx` or `pdf`.\n- **`--log_path`** (required): pass the pre-chosen path.\n- **`-o`** (required): absolute output path for the converted `.pptx`.\n\n### 3b. Monitor progress （REQUIRED）\n\n> **STRICT RULES — no exceptions:**\n> 1. **Read the log exactly every 5 seconds.** Do NOT extend the interval, do NOT skip reads.\n> 2. **Before every read, check if the process is still alive.** If alive → only read log, NEVER restart.\n\n**Every 5 seconds, run this exact sequence:**\n\n```bash\n# Step 1: extract PID from log\nPPT_PID=$(grep '^\\[PID\\]' \"$PPT_LOG\" | tail -1 | awk '{print $2}')\n# Step 2: check if process is alive\nkill -0 \"$PPT_PID\" 2>/dev/null && PPT_ALIVE=true || PPT_ALIVE=false\n# Step 3: read the log regardless\ntail -20 \"$PPT_LOG\"\n```\n\n- If process is **RUNNING** → report status to user, wait 5s, repeat. Do NOT touch the script.\n- If process is **not running** AND log ends with `[DONE]` or `[ERROR]` → stop polling, proceed to deliver/handle error.\n- If process is **not running** AND no `[DONE]`/`[ERROR]` in log → the script crashed; report error to user, ask whether to retry.\n\nEach line is plain text:\n- `[PID] <pid>` — process ID written at startup\n- `[START]` — job started\n- `[PHASE] <message>` — in progress\n- `[PROGRESS] <message>` — heartbeat progress update\n- `[DONE] saved=<path> download_url=<url>` — finished\n- `[ERROR] <message>` — failed\n\n**After each read, report status to the user:**\n\n```text\n[Main stage] | [current action]\nExample: Converting HTML | Converting batch 2/4\n```\n\nProgress phases:\n\n| Message contains | Main stage |\n|-----------------|------------|\n| \"Capturing screenshots\" / \"Screenshots captured\" | Capturing screenshots |\n| \"Uploading screenshot\" / \"Screenshot upload complete\" | Uploading screenshots |\n| \"Building nano HTML\" / \"Nano HTML ready\" | Building nano HTML |\n| \"Converting HTML\" / \"Converted batch\" | Converting HTML |\n| \"Exporting editable PPTX\" / \"Export complete\" | Exporting PPTX |\n\n**Stop polling** as soon as you see `[DONE]` or `[ERROR]`.\n\n---\n\n## 4. Deliver\n\nProvide all of the following:\n1. Download link (`download_url` from the completion event)\n2. Local `.pptx` absolute path\n3. The original filename used as the source\n\n### Failure\n\nBriefly explain the error.\n\nFile v1.0.9:workflow_edit.md\n\n# PPT Edit Workflow\n\nEdit an existing PPT via natural language: modify individual slides, add new slides, change the overall style, split or merge slides.\n\nFollow these steps in order: get pptx_url → confirm intent → run script (background) → **read log every 5s and report progress** (required) → deliver. **Never go silent — always report status as you poll the log.**\n\n---\n\n## 1. Get the PPTX URL\n\nThe user must supply a publicly accessible OSS/CDN URL of the existing PPTX to edit.\n\n- If the user provides a **local file path** instead of a URL, upload it first:\n  ```bash\n  $PYTHON_CMD scripts/upload_files.py \"/absolute/path/to/file.pptx\"\n  ```\n  Extract the URL from the `[OK] ... -> https://...` output line.\n\n- If the URL is already provided (e.g. from a previous generation's `Download URL:` output), use it directly.\n\n---\n\n## 2. Confirm edit intent\n\nUnderstand what the user wants to change. Supported operations include:\n\n| Operation | Example user intent |\n|-----------|---------------------|\n| Modify a slide | \"change page 4 background to black, text to white\" |\n| Add a new slide | \"insert a new slide after page 3 about X\" |\n| Change overall style | \"make all slides use a dark theme\" |\n| Split a slide | \"split page 5 into two slides\" |\n| Merge slides | \"merge pages 2 and 3 into one slide\" |\n\nPass the user's original instruction verbatim as `query`. Do not paraphrase — the backend interprets it directly.\n\n---\n\n## 3. Run the script\n\nRun in the **background**, then read the progress log file every 5 seconds until done.\n\n### 3a. Choose a log path and start in background\n```bash\nPPT_LOG=/tmp/ppt_$(date +%s).log\n\n$PYTHON_CMD scripts/run_ppt_write.py \"user's edit instruction\" \\\n  --language Chinese \\\n  --pptx-url \"https://cdn.example.com/path/to/file.pptx\" \\\n  --log_path \"$PPT_LOG\" \\\n  -o /absolute/path/to/output.pptx \\\n  > /dev/null 2>&1 &\n\necho \"Log: $PPT_LOG\"\n```\n\n- **`--log_path`** (required): Pass the pre-chosen path. The script writes all progress here.\n- **`--pptx-url`** (required): OSS URL of the PPTX to edit. This triggers edit mode.\n- **`--language`** (required): Detect from user input — `Chinese` or `English`.\n- **`-o`** (required): Absolute output path for the edited PPTX.\n\n### 3b. Monitor progress （REQUIRED）\n\n> **STRICT RULES — no exceptions:**\n> 1. **Read the log exactly every 5 seconds.** Do NOT extend the interval, do NOT skip reads.\n> 2. **Before every read, check if the process is still alive.** If alive → only read log, NEVER restart.\n\n**Every 5 seconds, run this exact sequence:**\n```bash\n# Step 1: extract PID from log\nPPT_PID=$(grep '^\\[PID\\]' \"$PPT_LOG\" | tail -1 | awk '{print $2}')\n# Step 2: check if process is alive\nkill -0 \"$PPT_PID\" 2>/dev/null && PPT_ALIVE=true || PPT_ALIVE=false\n# Step 3: read the log regardless\ntail -20 \"$PPT_LOG\"\n```\n- If process is **RUNNING** → report status to user, wait 5s, repeat. Do NOT touch the script.\n- If process is **not running** AND log ends with `[DONE]` or `[ERROR]` → stop polling, proceed to deliver/handle error.\n- If process is **not running** AND no `[DONE]`/`[ERROR]` in log → the script crashed; report error to user, ask whether to retry. **Both conditions must hold: PID gone AND no terminal log line. NEVER retry without explicit user confirmation.**\n\nEach line is plain text: \n- `[PID] <pid>` — process ID written at startup\n- `[START]` — job started\n- `[PHASE] <message>` — in progress\n- `[DONE] saved=<path> download_url=<url>` — finished\n- `[ERROR] <message>` — failed\n\n**After each read, report status to the user:**\n```\n[Main stage] | [current action] \nExample: Generating slides | Working on page 3 \n```\n\nProgress phases:\n\n| Message contains | Main stage |\n|-----------------|------------|\n| \"Parsing existing PPTX\" | Parsing original PPTX |\n| \"update plan\" | Planning updates |\n| \"updated slides\" / \"Slide N updated\" | Generating updated slides |\n| \"Exporting\" / \"Export complete\" | Exporting PPTX |\n\n**Stop polling** as soon as you see `[DONE]` or `[ERROR]`.\n\n---\n\n## 4. Deliver\n\nProvide all of the following:\n1. Download link (`download_url` from the completion event)\n2. Local `.pptx` absolute path\n3. Brief summary of what was changed (which pages, what modifications)\n\n### Failure\n\nBriefly explain the error.\n\nFile v1.0.9:workflow_generate.md\n\n# PPT Generate Workflow\n\nFollow these steps in order: confirm inputs → run script (streaming) → **output progress at every phase** (required) → save file → deliver. **Never go silent for an extended period — always stream progress as it arrives.**\n\n---\n\n## 1. Parse reference files (optional — only if the user provides local files)\n\nIf the user provides local files (PDF, DOCX, PPTX, images, etc.) as content source for the PPT, parse each file with the document parse service. This uploads the file, extracts its content, and returns metadata (file_id, file_url).\n\nRun `parse_file.py` once per filet, his may cost a few minutes to finish completely::\n\n```bash\n$PYTHON_CMD scripts/parse_file.py /path/to/file1.pdf\n$PYTHON_CMD scripts/parse_file.py /path/to/file2.docx\n```\n- **exec tool `yieldMs`**: Must be set to `600000` (10 minutes) when invoking the exec tool.\n\nEach call prints a `PARSED_FILE:` line on success:\n```\nPARSED_FILE: {\"filename\": \"file1.pdf\", \"url\": \"https://...\", \"file_id\": \"123456789\"}\n```\n\nCollect every `PARSED_FILE:` result and assemble them into a JSON array as `DOC_FILES_JSON`:\n```json\n[\n  {\"filename\":\"file1.pdf\",\"url\":\"https://...\",\"file_id\":\"123456789\",\"file_type\":\"pdf\"},\n  {\"filename\":\"file2.docx\",\"url\":\"https://...\",\"file_id\":\"987654321\",\"file_type\":\"docx\"}\n]\n```\n\nPass this array to `--files` in Step 3. If no local files are provided, skip this step entirely.\n\n---\n\n## 2. Web search (required if no relevant content is already in the conversation)\n\nSkip this step if the user has already provided sufficient reference material or reference files.\nOtherwise, run up to 3 targeted searches on the topic, make sure your query contains the date if you need to search the latest information:\n\n### Run searches\n\n```bash\n$PYTHON_CMD scripts/web_search.py \"query1\" \"query2\" \"query3\"\n```\n\n- Break the topic into 1–3 focused queries (e.g. for \"Beijing travel guide\": \"Beijing top attractions\", \"Beijing food recommendations\", \"Beijing transportation tips\").\n- **If the topic involves current events, trends, statistics, or anything time-sensitive**, append the current year (e.g. `2026`) or a date range to each query to ensure results are up to date. Example: `\"AI agent market trends 2026\"` instead of `\"AI agent market trends\"`.\n- Deduplicate and distill all results into a `reference` text to enrich the PPT content.\n\n### Synthesize search results\n\n**If reference files were parsed in Step 1**, use their `parsed_content` as the primary source and supplement with search results. The parsed content contains the full document text — extract and preserve all detail, do not compress it into a short summary.\n\nProduce a detailed **reference report**. **Target 800–2000 words — do not stop early.** Write as much specific detail as the sources provide:\n\n```\n## Key Findings\n3–5 sentences covering the main conclusions, background, and why it matters.\n\n## Key Data & Facts\n- List every specific number, percentage, date, and metric found. Do not skip data.\n- Format: \"Exact figure — what it measures (source)\"\n- Aim for at least 5 data points if the source contains them.\n\n## Topic Breakdown\nOrganize by sub-topic. For each sub-topic write 3–5 specific bullet points.\nDo not use vague phrases like \"it is important\" — state the actual fact.\nPreserve names of people, companies, products, places, and dates exactly as found.\n\n## Cases & Examples (if available)\nConcrete examples, case studies, or use cases with specific details and outcomes.\n\n## Summary\n3–5 bullet points capturing the core message the PPT must convey.\n```\n\n**Hard constraints**:\n- Only include information that **explicitly appears** in the sources. Do not invent or infer.\n- Numbers, percentages, and proper nouns must be quoted exactly — do not paraphrase or round.\n- **Never produce fewer than 500 words** unless the source material is genuinely sparse.\n- If a section has no relevant information, omit that section entirely.\n- **Note the publication date of each source.** Always include the current date context in the summary where relevant.\n\nAfter writing the reference report, save it to a local temp file to avoid shell encoding issues:\n```bash\ncat > /tmp/ppt_reference.md << 'REFERENCE_EOF'\n<paste the full reference report here>\nREFERENCE_EOF\n```\nUse this file path as `--reference-file` in Step 3.\n\n---\n\n## 2. Confirm inputs\n\n- **query** (required): Faithfully reproduce the user's full request — include every instruction the user mentioned. Cover the following if the user specified them; do not add anything they didn't mention:\n  - Slide count (if the user set a limit, it must be included — never drop it)\n  - Topic / content direction\n  - Style preference (e.g. business, academic, playful, minimalist)\n  - Audience / purpose (e.g. \"exec briefing for the CXO\", \"science explainer for kids\")\n  - Structure preference (e.g. \"data-heavy\", \"one case study per slide\")\n  - Other constraints (tone, things to avoid, required talking points, etc.)\n\n  **Rule**: Do not fabricate requirements the user never mentioned, and do not omit anything they explicitly said. If the user gives only a title, the query is exactly that title — don't add qualifiers.\n\n  **Examples**:\n\n  | User input | Correct query |\n  |------------|---------------|\n  | Make me a PPT about Beijing travel | `Beijing Travel Guide PPT` |\n  | 8-page English slides on AI Agent, clean business style, targeting investors | `8-page English slides on AI Agent, clean business style, targeting investors` |\n  | PPT for our Q1 sales summary, 10 slides, with data charts, formal style | `Q1 Sales Summary PPT, 10 slides, data charts, formal business style` |\n  | A fun solar system PPT for elementary school kids, 6 pages | `Solar System explainer PPT for elementary school kids, fun and engaging style, 6 slides` |\n\n- **language** (required): Detect from the user's input language — if the user writes in Chinese pass `Chinese`; English → `English`; etc. Never default to a fixed value.\n- **--reference-file** (optional): Pass the path to the temp file written at the end of Step 2 (e.g. `/tmp/ppt_reference.md`). Omit if no search was performed.\n- **--files** (optional): Pass the JSON array assembled from the `PARSED_FILE:` lines in Step 1. Omit if no files were provided. Format: `[{\"file_name\":\"...\",\"url\":\"...\",\"file_id\":\"...\", \"file_type\": \"pdf\"},...]`\n\n---\n\n## 3. Run the script\n\nPPT generation takes ~10 minutes. Choose a log path first, pass it to the script, then read it every 5 seconds.\n\n### 3a. Choose a log path and start in background\n```bash\nPPT_LOG=/tmp/ppt_$(date +%s).log\n\n$PYTHON_CMD scripts/run_ppt_write.py \"user query\" \\\n  --language English \\\n  --reference-file /tmp/ppt_reference.md \\\n  --files '[{\"file_name\":\"report.pdf\",\"url\":\"https://...\", \"file_id\":\"1212121\", \"file_type\":\"pdf\"}]' \\\n  --log_path \"$PPT_LOG\" \\\n  -o /absolute/path/to/output.pptx \\\n  > /dev/null 2>&1 &\n\necho \"Log: $PPT_LOG\"\n```\n\n- **`--log_path`** (required): Pass the pre-chosen path. The script writes all progress here.\n- **`-o`** (required): Use an absolute path.\n- **`--files`**: JSON array from `DOC_FILES_JSON:` lines **verbatim**. Omit if no reference files.\n\n### 3b. Monitor progress （REQUIRED）\n\n> **STRICT RULES — no exceptions:**\n> 1. **Read the log exactly every 5 seconds.** Do NOT extend the interval, do NOT skip reads.\n> 2. **Before every read, check if the process is still alive.** If alive → only read log, NEVER restart.\n\n**Every 5 seconds, run this exact sequence:**\n```bash\n# Step 1: extract PID from log\nPPT_PID=$(grep '^\\[PID\\]' \"$PPT_LOG\" | tail -1 | awk '{print $2}')\n# Step 2: check if process is alive\nkill -0 \"$PPT_PID\" 2>/dev/null && PPT_ALIVE=true || PPT_ALIVE=false\n# Step 3: read the log regardless\ntail -20 \"$PPT_LOG\"\n```\n- If process is **RUNNING** → report status to user, wait 5s, repeat. Do NOT touch the script.\n- If process is **not running** AND log ends with `[DONE]` or `[ERROR]` → stop polling, proceed to deliver/handle error.\n- If process is **not running** AND no `[DONE]`/`[ERROR]` in log → the script crashed; report error to user, ask whether to retry. **Both conditions must hold: PID gone AND no terminal log line. NEVER retry without explicit user confirmation.**\n\nEach line is plain text:\n- `[PID] <pid>` — process ID written at startup\n- `[START]` — job started\n- `[PHASE] <message>` — stage transition (outline, slides, export, etc.)\n- `[PING] <progress>% | <stage>` — heartbeat every few seconds with current progress and stage label\n- `[OUTLINE]` — outline content (appears once after outline_done)\n- `[DONE] saved=<path> download_url=<url>` — finished\n- `[ERROR] <message>` — failed\n\n**After each read, report status to the user:**\n```\n[Main stage] | [current action]\nExample: Generating slides | Working on page 3 \n```\n\nMap phase messages to main stages:\n\n| Message contains | Main stage |\n|-----------------|------------|\n| \"outline\" | Generating outline |\n| \"slide\" / \"page\" / \"content\" | Generating slides |\n| \"image\" / \"HTML\" | Rendering images |\n| \"Export\" / \"export\" | Exporting PPTX |\n| \"Parsing existing PPTX\" | Parsing original PPTX |\n| \"update plan\" | Planning updates |\n| \"template\" | Processing template |\n\n**Stop polling** as soon as you see `[DONE]` or `[ERROR]`.\n\n---\n\n## 4. Deliver\n\n### Success\n\nProvide all of the following:\n1. Download link\n2. Local `.pptx` absolute path\n3. Presentation title\n4. Brief description of each slide's content\n\n### Failure\n\nBriefly explain the error. \n\n## Technical Notes\n- **Timeout**: PPT generation takes ~10 minutes, set sufficient timeout\n\nFile v1.0.9:workflow_imitate.md\n\n# PPT Imitation Workflow\n\nThe user provides an existing PPTX file as a layout/style reference. Generate a new presentation on a different topic that follows the same visual structure.\n\nFollow these steps in order: identify intent → locate template → web search → upload template → run script (streaming) → **output progress at every phase** (required) → save file → deliver. **Never go silent for an extended period — always stream progress as it arrives.**\n\n---\n\n## 0. Confirm imitation intent\n\nUse this workflow (instead of the standard generate flow) when **both** of the following are true:\n\n- The user mentions a template, style reference, or an existing file — e.g. \"use this template\", \"match the style of this PPT\", \"imitate this layout\" — **or** provides a `.pptx` file path or filename.\n- The user has a new generation request (topic, content, slide count, etc.).\n\nIf the user provides a template but no new topic, **ask what they want to create** before proceeding.\n\n---\n\n## 1. Locate the local template file\n\nExtract the local PPTX path from the user's message. It may appear as:\n\n- An absolute path: `/Users/xxx/templates/style.pptx`\n- A relative path or filename: `my_template.pptx` (ask the user to confirm the exact full path before using it)\n- An attachment uploaded in the conversation (the platform will provide a local temp path)\n\n**If the path is ambiguous, ask the user for the full absolute path.**\n\n---\n\n## 2. Parse reference files (optional — only if the user provides local files as content source)\n\nIf the user provides additional local files (PDF, DOCX, PPTX, images, etc.) to use as content source — separate from the template — parse each file with the document parse service.\n\nRun `parse_file.py` once per file, this may cost a few minutes to finish completely:\n\n```bash\n$PYTHON_CMD scripts/parse_file.py /path/to/file1.pdf\n$PYTHON_CMD scripts/parse_file.py /path/to/file2.docx\n```\n- **exec tool `yieldMs`**: Must be set to `600000` (10 minutes) when invoking the exec tool.\n\nEach call prints a `PARSED_FILE:` line on success:\n```\nPARSED_FILE: {\"filename\": \"file1.pdf\", \"url\": \"https://...\", \"file_id\": \"123456789\"}\n```\n\nCollect every `PARSED_FILE:` result and assemble them into a JSON array as `DOC_FILES_JSON`:\n```json\n[\n  {\"filename\":\"file1.pdf\",\"url\":\"https://...\",\"file_id\":\"123456789\",\"file_type\":\"pdf\"},\n  {\"filename\":\"file2.docx\",\"url\":\"https://...\",\"file_id\":\"987654321\",\"file_type\":\"docx\"}\n]\n```\n\nPass this array to `--files` in Step 6. If no additional content files are provided, skip this step entirely.\n\n---\n\n## 3. Web search (required if no relevant content is already in the conversation)\n\nSkip if the user has already provided sufficient reference material or reference files.\nOtherwise, run up to 3 targeted searches on the **new PPT topic**:\n\n```bash\n$PYTHON_CMD scripts/web_search.py \"query1\" \"query2\" \"query3\"\n```\n\nProduce a detailed reference report following the same format and constraints as the generate workflow (target 800–2000 words, preserve all specific details, never fewer than 500 words).\n\nAfter writing the reference report, save it to a local temp file:\n```bash\ncat > /tmp/ppt_reference.md << 'REFERENCE_EOF'\n<paste the full reference report here>\nREFERENCE_EOF\n```\nUse this file path as `--reference-file` in Step 6.\n\n---\n\n## 4. Upload the template to OSS\n\n```bash\n$PYTHON_CMD scripts/upload_files.py \"/absolute/path/to/template.pptx\"\n```\n\n- Script output format: `[OK] /path/to/file.pptx -> https://cdn.xxx/skills/upload/yyyy-mm-dd/uuid_filename.pptx`\n- Extract the OSS URL from the output and call it `TEMPLATE_URL`.\n- If the upload fails, inform the user and stop.\n\n---\n\n## 5. Confirm generation parameters\n\n- **query** (required): Faithfully reproduce the user's full request — include every instruction (slide count, style, audience, etc.). Do not fabricate or omit anything.\n- **language** (required): Language for the slides, e.g. `Chinese`, `English`.\n- **language** (required): Detect from the user's input language — if the user writes in Chinese pass `Chinese`; English → `English`; etc. Never default to a fixed value.\n- **template_urls** (required): The OSS URL(s) from Step 4. Multiple URLs are supported (comma-separated) — the backend selects the best-matching layout from each. One URL is sufficient in most cases; pass multiple only if the user provided several template files.\n- **--reference-file** (optional): Path to the temp file written at the end of Step 3 (e.g. `/tmp/ppt_reference.md`). Omit if no search was performed.\n- **--files** (optional): Pass the JSON array assembled from the `PARSED_FILE:` lines in Step 2. Omit if no content files were provided. Format: `[{\"filename\":\"...\",\"url\":\"...\",\"file_id\":\"...\", \"file_type\": \"pdf\"},...]`\n\n---\n\n## 6. Run the script\n\nPPT generation takes ~10 minutes. Run it in the **background**, then read the progress log file every 5 seconds until done.\n\n### 6a. Choose a log path and start in background\n```bash\nPPT_LOG=/tmp/ppt_$(date +%s).log\n\n$PYTHON_CMD scripts/run_ppt_write.py \"user query\" \\\n  --language Chinese \\\n  --template_urls \"TEMPLATE_URL1,TEMPLATE_URL2\" \\\n  --reference-file /tmp/ppt_reference.md \\\n  --files '[{\"file_name\":\"report.pdf\",\"url\":\"https://...\", \"file_id\":\"1212121\", \"file_type\":\"pdf\"}]' \\\n  --log_path \"$PPT_LOG\" \\\n  -o /absolute/path/to/output.pptx \\\n  > /dev/null 2>&1 &\n\necho \"Log: $PPT_LOG\"\n```\n\n- **`--log_path`** (required): Pass the pre-chosen path. The script writes all progress here.\n- **`-o`** (required): Use an absolute path for reliable delivery.\n- **`--template_urls`**: Comma-separated OSS URLs of template files from Step 4.\n- **`--files`**: Pass the JSON array assembled from `PARSED_FILE:` lines **verbatim**. Omit if no reference files.\n\n### 6b. Monitor progress （REQUIRED）\n\n> **STRICT RULES — no exceptions:**\n> 1. **Read the log exactly every 5 seconds.** Do NOT extend the interval, do NOT skip reads.\n> 2. **Before every read, check if the process is still alive.** If alive → only read log, NEVER restart.\n\n**Every 5 seconds, run this exact sequence:**\n```bash\n# Step 1: extract PID from log\nPPT_PID=$(grep '^\\[PID\\]' \"$PPT_LOG\" | tail -1 | awk '{print $2}')\n# Step 2: check if process is alive\nkill -0 \"$PPT_PID\" 2>/dev/null && PPT_ALIVE=true || PPT_ALIVE=false\n# Step 3: read the log regardless\ntail -20 \"$PPT_LOG\"\n```\n- If process is **RUNNING** → report status to user, wait 5s, repeat. Do NOT touch the script.\n- If process is **not running** AND log ends with `[DONE]` or `[ERROR]` → stop polling, proceed to deliver/handle error.\n- If process is **not running** AND no `[DONE]`/`[ERROR]` in log → the script crashed; report error to user, ask whether to retry. **Both conditions must hold: PID gone AND no terminal log line. NEVER retry without explicit user confirmation.**\n\n\nEach line is plain text: \n- `[PID] <pid>` — process ID written at startup\n- `[START]` — job started\n- `[PHASE] <message>` — in progress\n- `[DONE] saved=<path> download_url=<url>` — finished\n- `[ERROR] <message>` — failed\n\n**After each read, report status to the user:**\n```\n[Main stage] | [current action] \nExample: Generating slides | Working on page 3 \n```\n\n**Stop polling** as soon as you see `[DONE]` or `[ERROR]`.\n\n\n## 7. Deliver\n\n### Success\n\nProvide all of the following:\n1. Download link\n2. Local `.pptx` absolute path\n3. Presentation title\n4. Brief description of each slide's content\n5. Template filename used (so the user can verify)\n\n### Failure\n\nBriefly explain the error.\n---\n\n## Appendix — Intent classification examples\n\n| User input | Use this workflow? |\n|------------|--------------------|\n| Make me a PPT about Beijing travel | ❌ Standard generate |\n| Use this template to make a PPT on AI trends — template at `/tmp/style.pptx` | ✅ Imitate |\n| Imitate the uploaded pptx style, 10-slide quarterly review | ✅ Imitate |\n| What style is this template? | ❌ Not a generation request — just answer the question |\n\nFile v1.0.9:workflow_local.md\n\n# Local PPTX Operations Workflow (Layer 3)\n\nNo backend or token needed — uses `python-pptx` to operate on local `.pptx` files directly.\n\n---\n\n## Install Dependencies\n\n```bash\npip install python-pptx\n```\n\n---\n\n## Trigger Keywords\n\nWhen the user expresses the following intents, use this workflow (instead of calling the backend API):\n\n| User Intent | Example Keywords |\n|----------|-----------|\n| View file info | View PPT page count, how many pages, pptx info |\n| Delete specific slides | Delete slide N, remove slide 3, delete slide 3, remove page 5 |\n| Reorder slides | Reorder PPT, rearrange slide order, reorder slides |\n| Extract slides | Extract slides 1-3, export certain slides, extract slides |\n| Merge files | Merge two PPTs, merge pptx, combine a and b |\n\n---\n\n## Unified Entry Point\n\nAll operations are done via `scripts/local_pptx_ops.py`:\n\n```bash\n$PYTHON_CMD scripts/local_pptx_ops.py <subcommand> [arguments]\n```\n\n---\n\n## Subcommand Details\n\n### info — View file info\n\n```bash\n$PYTHON_CMD scripts/local_pptx_ops.py info --file my.pptx\n```\n\nOutput: file path, total slides, dimensions, title of each slide.\n\n---\n\n### delete — Delete slides\n\n```bash\n# Delete slide 3\n$PYTHON_CMD scripts/local_pptx_ops.py delete --file my.pptx --slides 3\n\n# Delete slides 3, 5, 7-9, overwrite the original file\n$PYTHON_CMD scripts/local_pptx_ops.py delete --file my.pptx --slides 3,5,7-9\n\n# Save to a new file after deletion (don't overwrite the original)\n$PYTHON_CMD scripts/local_pptx_ops.py delete --file my.pptx --slides 3,5,7-9 -o trimmed.pptx\n```\n\n**Note**:\n- Page numbers are 1-based (slide 1 = 1)\n- Supports comma-separated and `-` ranges, e.g. `1,3,5-8,10`\n- If `-o` is not specified, the original file is overwritten\n\n---\n\n### reorder — Reorder slide order\n\n```bash\n# Move original slide 2 to position 1, slide 1 to position 2 (rest unchanged)\n$PYTHON_CMD scripts/local_pptx_ops.py reorder --file my.pptx --order 2,1,3,4,5\n\n# Save to a new file\n$PYTHON_CMD scripts/local_pptx_ops.py reorder --file my.pptx --order 2,1,3,4,5 -o reordered.pptx\n```\n\n**Note**: `--order` must include all page numbers — no omissions or duplicates.\n\n---\n\n### extract — Extract specific slides\n\n```bash\n# Extract slides 1 through 3\n$PYTHON_CMD scripts/local_pptx_ops.py extract --file my.pptx --slides 1-3 -o subset.pptx\n\n# Extract slides 1, 3, 5\n$PYTHON_CMD scripts/local_pptx_ops.py extract --file my.pptx --slides 1,3,5 -o subset.pptx\n```\n\nExtracted result is saved as a new file (original file is not modified).\n\n---\n\n### merge — Merge multiple files\n\n```bash\n# Merge two files\n$PYTHON_CMD scripts/local_pptx_ops.py merge --files a.pptx b.pptx -o merged.pptx\n\n# Merge three or more\n$PYTHON_CMD scripts/local_pptx_ops.py merge --files a.pptx b.pptx c.pptx -o merged.pptx\n```\n\n**Note**: The slide dimensions of the first file are used as the standard; shapes are preserved as much as possible during merging, but complex animations/video effects may be lost.\n\n---\n\n## Agent Decision Logic\n\nUser intent → Route selection:\n\n```\nUser says \"Generate a PPT about X\"\n  → Layer 1: scripts/run_ppt_write.py (call backend to generate)\n\nUser says \"Delete slide 3 from this PPT\" / \"Merge these two pptx\" / \"Extract the first 5 slides\"\n  → Layer 3: scripts/local_pptx_ops.py (local operation, no token needed)\n```\n\n---\n\n## FAQ\n\n**Q: Do page numbers change after deletion?**\nA: Yes. After deletion, page numbers are renumbered starting from 1. If you need to delete multiple slides, it's recommended to pass them all at once (`--slides 3,5,7`) rather than running multiple times.\n\n**Q: What if styles are wrong after merging?**\nA: Merging uses deep-copy of the shape tree; themes/masters come from the first file. If there are significant style differences, manual adjustments in PowerPoint are recommended.\n\n**Q: Does python-pptx support deleting slides?**\nA: Not natively. This tool operates on the underlying XML (`_sldIdLst`), consistent with common python-pptx community approaches.\n\nArchive v1.0.8: 14 files, 32344 bytes\n\nFiles: references/apikey-fetch.md (2693b), scripts/constant.py (81b), scripts/local_pptx_ops.py (13562b), scripts/parse_file.py (6798b), scripts/run_ppt_write.py (15459b), scripts/skywork_auth.py (284b), scripts/upload_files.py (4900b), scripts/web_search.py (2493b), SKILL.md (8974b), workflow_edit.md (4275b), workflow_generate.md (9584b), workflow_imitate.md (7973b), workflow_local.md (3981b), _meta.json (130b)\n\nFile v1.0.8:SKILL.md\n\n---\nname: Skywork-ppt\ndescription: Skywork PPT (skywork) - Use when the user wants to work with PowerPoint presentations. Triggers: (1) Generate a new PPT from a topic — 'generate a PPT', 'create a presentation about X', 'make slides', '帮我做个PPT', '生成演示文稿', 'PPTを作って', 'スライドを作って', 'PPT 만들어줘', '슬라이드 만들어줘'; (2) Imitate an existing .pptx style/template — 'use this template', 'imitate this PPT/style', '用这个模板', '仿照这个PPT', 'このテンプレートを使って', '이 템플릿 써줘'; (3) Edit existing PPT via natural language — 'modify slide N', 'change background', 'add a slide', 'make it more beautiful', '修改第N页', '更换背景', '新增一页', '美化一下', 'N枚目を修正', '背景を変えて', 'きれいにして', 'N번 슬라이드 수정', '배경 바꿔줘'; (4) Local .pptx file ops — 'delete slide N', 'reorder slides', 'merge pptx', 'extract slides', 'how many slides', '删除第N页', '调整顺序', '合并PPT', '提取幻灯片', 'スライドを削除/並べ替え/結合/抽出', '슬라이드 삭제/순서 변경/합치기/추출'.\nmetadata:\n  openclaw:\n    requires:\n      bins:\n        - python3\n      env:\n        - SKYWORK_API_KEY\n    primaryEnv: SKYWORK_API_KEY\n---\n\n# PPT Write Skill\n\nFour capabilities: **generate**, **template imitation**, **edit existing PPT**, and **local file operations**.\n\n---\n\n## Prerequisites\n\n### API Key Configuration (Required First)\nThis skill requires a **SKYWORK_API_KEY** to be configured before use.\n\nIf you don't have an API key yet, please visit:\n**https://skywork.ai**\n\nFor detailed setup instructions, see:\n[references/apikey-fetch.md](references/apikey-fetch.md)\n\n---\n\n## Privacy & Remote Calls (Read Before Use)\n\n- **Remote upload & processing**: Layers 1/2/4 upload local files and send the full, verbatim user query to the Skywork service. Avoid sensitive or confidential content unless you trust the remote service and its data handling policies.\n- **Polling behavior**: The generation/edit workflows include periodic status polling (about every 5 seconds) while waiting for backend jobs. This is expected.\n\n---\n\n## Routing — Identify the user's intent first\n\n| User intent | Which path |\n|-------------|------------|\n| Generate a new PPT from a topic, set of requirements or reference files | **Layer 1** — Generate |\n| Use an existing .pptx as a layout/style template to create a new presentation | **Layer 2** — Imitate |\n| Edit an existing PPT: modify slides, add slides, change style, split/merge | **Layer 4** — Edit |\n| Delete / reorder / extract / merge slides in a local file (no backend) | **Layer 3** — Local ops |\n\n---\n\n## Environment check (always run this first)\n\n**This skill requires Python 3 (>=3.8). Run the following before any script to locate a valid Python binary and install dependencies.**\n\n```bash\nPYTHON_CMD=\"\"\nfor cmd in python3 python python3.13 python3.12 python3.11 python3.10 python3.9 python3.8; do\n  if command -v \"$cmd\" &>/dev/null && \"$cmd\" -c \"import sys; exit(0 if sys.version_info >= (3,8) else 1)\" 2>/dev/null; then\n    PYTHON_CMD=\"$cmd\"\n    break\n  fi\ndone\n\nif [ -z \"$PYTHON_CMD\" ]; then\n  echo \"ERROR: Python 3.8+ not found.\"\n  echo \"Install on macOS: brew install python3  or visit https://www.python.org/downloads/\"\n  exit 1\nfi\n\necho \"Found Python: $PYTHON_CMD ($($PYTHON_CMD --version))\"\n\n$PYTHON_CMD -m pip install -q --break-system-packages python-pptx\necho \"Dependencies ready.\"\n```\n\n> After this check, replace `python` with the discovered `$PYTHON_CMD` (e.g. `python3`) in all subsequent commands.\n\n---\n\n## Layer 1 — Generate PPT\n\n### Steps\n0. **REQUIRED FIRST STEP** — Read [workflow_generate.md](workflow_generate.md) NOW, before taking any other action. After reading, output exactly: `✅ workflow_generate.md loaded.` — then proceed.\n1. **Environment check** — run the check above to get `$PYTHON_CMD`.\n2. **Upload reference files** (if the user provides local files as content source) — parse the file using tool in script/parse_file.py and pass the result to `--files`. See the `--files` note below.\n3. **Web search** (required if no relevant content is already in the conversation) — call web_search tool in script to search the topic and distill results into a `reference-file` file of ≤ 2000 words.\n4. **Run the script**:\n   > **Important**: set exec tool `yieldMs` to `600000` (10 minutes).\n5. **Deliver** — provide the absolute `.pptx` path and the download URL.\n\n---\n\n## Layer 2 — Imitate PPT (template-based generation)\n\n### Steps\n0. **REQUIRED FIRST STEP** - Read [workflow_imitate.md](workflow_imitate.md) immidiately before any action you do!!!\n1. **Environment check** — run the check above to get `$PYTHON_CMD`.\n2. **Locate the template** — extract the absolute path of the local `.pptx` from the user's message; ask the user if it's unclear.\n3. **Upload the template** — upload it and extract `TEMPLATE_URL` from the output.\n4. **Upload reference files** (if the user provides additional local files as content source) — parse the file using tool in script/parse_file.py and pass the result to `--files`. See the `--files` \n5. **Web search** (required if no relevant content is already in the conversation) — call web_search tool in script to search the new topic and distill results into a `reference-file` file of ≤ 2000 words.\n6. **Run the script**:\n   > **Important**: set exec tool `yieldMs` to `600000` (10 minutes).\n7. **Deliver** — provide the absolute `.pptx` path, the download URL, and the template filename used.\n\n---\n\n## Layer 4 — Edit PPT (AI-powered modification)\n\nUse this layer when the user wants to modify an existing PPT using natural language. Requires an OSS/CDN URL of the PPTX (from a previous generation or upload).\n\n### Steps\n0. **Detailed workflow** - Read [workflow_edit.md](workflow_edit.md) immediately before any action you do!!!\n1. **Environment check** — run the check above to get `$PYTHON_CMD`.\n2. **Get PPTX URL** — from the user's message or upload a local file first.\n3. **Run the script** with `--pptx-url`:\n   ```bash\n   $PYTHON_CMD scripts/run_ppt_write.py \"edit instruction\" \\\n     --language Chinese \\\n     --pptx-url \"https://cdn.example.com/file.pptx\" \\\n     -o /absolute/path/output.pptx\n   ```\n   > **Important**: set exec tool `yieldMs` to `600000` (10 minutes).\n4. **Deliver** — provide download link, local path, and summary of changes.\n\n---\n\n## Layer 3 — PPT File operations\n\n```bash\n# Inspect slide count and titles\n$PYTHON_CMD scripts/local_pptx_ops.py info --file my.pptx\n\n# Delete slides (1-based index; supports ranges like 3,5,7-9; omit -o to overwrite in place)\n$PYTHON_CMD scripts/local_pptx_ops.py delete --file my.pptx --slides 3,5,7-9 -o trimmed.pptx\n\n# Reorder slides (must list every slide, no omissions)\n$PYTHON_CMD scripts/local_pptx_ops.py reorder --file my.pptx --order 2,1,4,3,5\n\n# Extract a subset of slides into a new file\n$PYTHON_CMD scripts/local_pptx_ops.py extract --file my.pptx --slides 1-3 -o subset.pptx\n\n# Merge multiple files\n$PYTHON_CMD scripts/local_pptx_ops.py merge --files a.pptx b.pptx -o merged.pptx\n```\n\nRead [workflow_local.md](workflow_local.md) immidiately before any action you do!!!\n\n---\n\n## Error Handling\n\n- **Insufficient benefit**: When calling scripts (generate, imitate, or edit), the script or log may show a message like `Insufficient benefit. Please upgrade your account at {url}`, meaning the user's benefit level does not meet the requirement for this skill.\n\n### How to reply when benefit is insufficient\n\nWhen you detect the above, **reply in the user's current language** — do not echo the English message. Use this pattern:\n\n- Convey: \"Sorry, PPT generation failed. This skill requires upgrading your Skywork membership to use.\" then a single call-to-action link.\n- **Format**: One short sentence in the user's language + a link like `[Upgrade now →](url)` or the equivalent in their language .\n- **URL**: Extract the upgrade URL from the log/script output (e.g. the `at https://...` part).\n\n> Note: Only suggest upgrading when the error is **Insufficient benefit**. For auth errors like `NO_TOKEN` / `INVALID_TOKEN` / `401` / “invalid API key”, keep the error code / raw message and guide users to update `SKYWORK_API_KEY`. **Do not** suggest upgrading membership.\n\n---\n\n## Dependencies\n\n- **Python 3.8+** (required) — `python3` / `python` must be on PATH\n- Layer 3 local ops: `pip install python-pptx --break-system-packages`\n\n(The environment check step installs all required dependencies automatically.)\n\n---\n\n## Which layer to trigger?\n\n| Scenario | Use |\n|----------|-----|\n| Generate a PPT from a topic or existing reference files | Layer 1 |\n| Imitate the layout/style of an existing .pptx | Layer 2 |\n| Edit/modify an existing PPT via natural language | Layer 4 |\n| Delete / reorder / extract / merge local .pptx files (no backend) | Layer 3 |\n\nFile v1.0.8:_meta.json\n\n{\n  \"ownerId\": \"kn70ct0m3p4538a9t49cjcwern82ky02\",\n  \"slug\": \"skywork-ppt\",\n  \"version\": \"1.0.8\",\n  \"publishedAt\": 1775828241791\n}\n\nFile v1.0.8:references/apikey-fetch.md\n\n# Skywork API Key Setup Guide\n\n## SKYWORK_API_KEY Not Configured\n\nWhen the `SKYWORK_API_KEY` environment variable is not set, follow these steps:\n\n### 1. Get API Key\n\nVisit the Skywork website and sign in to your account:\n\n**https://skywork.ai**\n\n- Log in with your Skywork account\n- Open account / Settings / API Key (**https://skywork.ai/?openApiKeySetting=1**)\n- Create or copy your **API key**\n\nIf your organization uses a separate console or test environment, use the URL and credentials your team provides.\n\n### 2. Configure OpenClaw\n\nEdit the OpenClaw configuration file: `~/.openclaw/openclaw.json`\n\nIn current OpenClaw, Skywork skills store the key under `skills.entries.<Skill Name>.apiKey` (not under `env`).\nOpenClaw will inject this value into the skill's `SKYWORK_API_KEY` environment when `primaryEnv` matches.\nAdd or merge the following structure (adjust the skill name to match the installed skill):\n\n```json\n{\n  \"skills\": {\n    \"entries\": {\n      \"Skywork-ppt\": {\n        \"enabled\": true,\n        \"apiKey\": \"your_actual_skywork_api_key_here\"\n      }\n    }\n  }\n}\n```\n\nReplace `\"your_actual_skywork_api_key_here\"` with your real key.\n\nFor multiple Skywork skills, repeat the same `apiKey` field on each skill entry.\n\n### 3. Configure Claude Code\n\nIf you are using Claude Code, use one of these lightweight options:\n\n**Option A — shell environment**\n\nExport the API key before running the skill:\n\n```bash\nexport SKYWORK_API_KEY=\"your_actual_skywork_api_key_here\"\n```\n\nTo persist it across sessions, add the same line to `~/.zshrc` or `~/.bashrc`, then reload the shell.\n\n**Option B — Claude Code settings**\n\nAdd the variable to `~/.claude/settings.json`:\n\n```json\n{\n  \"env\": {\n    \"SKYWORK_API_KEY\": \"your_actual_skywork_api_key_here\"\n  }\n}\n```\n\nUse the method that best matches how you run Claude Code.\n\n### 4. Verify Configuration\n\n```bash\n# Check that the environment variable is available\necho \"$SKYWORK_API_KEY\"\n```\n\nFor OpenClaw, you can also validate the config file:\n\n```bash\ncat ~/.openclaw/openclaw.json | python3 -m json.tool\n```\n\n### 5. Restart OpenClaw\n\n```bash\nopenclaw gateway restart\n```\n\n## Troubleshooting\n\n- Ensure `~/.openclaw/openclaw.json` exists and is valid JSON\n- Ensure `SKYWORK_API_KEY` is available in Claude Code through your shell or `~/.claude/settings.json`\n- Confirm the API key is active and not expired\n- Check Skywork account status, membership, or quota if requests fail with auth or benefit errors\n- Restart OpenClaw after configuration changes\n\n**Recommended**: Use the setup method that matches your runtime. OpenClaw should use the OpenClaw config file; Claude Code can use either the shell environment or `~/.claude/settings.json`.\n\nFile v1.0.8:workflow_edit.md\n\n# PPT Edit Workflow\n\nEdit an existing PPT via natural language: modify individual slides, add new slides, change the overall style, split or merge slides.\n\nFollow these steps in order: get pptx_url → confirm intent → run script (background) → **read log every 5s and report progress** (required) → deliver. **Never go silent — always report status as you poll the log.**\n\n---\n\n## 1. Get the PPTX URL\n\nThe user must supply a publicly accessible OSS/CDN URL of the existing PPTX to edit.\n\n- If the user provides a **local file path** instead of a URL, upload it first:\n  ```bash\n  $PYTHON_CMD scripts/upload_files.py \"/absolute/path/to/file.pptx\"\n  ```\n  Extract the URL from the `[OK] ... -> https://...` output line.\n\n- If the URL is already provided (e.g. from a previous generation's `Download URL:` output), use it directly.\n\n---\n\n## 2. Confirm edit intent\n\nUnderstand what the user wants to change. Supported operations include:\n\n| Operation | Example user intent |\n|-----------|---------------------|\n| Modify a slide | \"change page 4 background to black, text to white\" |\n| Add a new slide | \"insert a new slide after page 3 about X\" |\n| Change overall style | \"make all slides use a dark theme\" |\n| Split a slide | \"split page 5 into two slides\" |\n| Merge slides | \"merge pages 2 and 3 into one slide\" |\n\nPass the user's original instruction verbatim as `query`. Do not paraphrase — the backend interprets it directly.\n\n---\n\n## 3. Run the script\n\nRun in the **background**, then read the progress log file every 5 seconds until done.\n\n### 3a. Choose a log path and start in background\n```bash\nPPT_LOG=/tmp/ppt_$(date +%s).log\n\n$PYTHON_CMD scripts/run_ppt_write.py \"user's edit instruction\" \\\n  --language Chinese \\\n  --pptx-url \"https://cdn.example.com/path/to/file.pptx\" \\\n  --log_path \"$PPT_LOG\" \\\n  -o /absolute/path/to/output.pptx \\\n  > /dev/null 2>&1 &\n\necho \"Log: $PPT_LOG\"\n```\n\n- **`--log_path`** (required): Pass the pre-chosen path. The script writes all progress here.\n- **`--pptx-url`** (required): OSS URL of the PPTX to edit. This triggers edit mode.\n- **`--language`** (required): Detect from user input — `Chinese` or `English`.\n- **`-o`** (required): Absolute output path for the edited PPTX.\n\n### 3b. Monitor progress （REQUIRED）\n\n> **STRICT RULES — no exceptions:**\n> 1. **Read the log exactly every 5 seconds.** Do NOT extend the interval, do NOT skip reads.\n> 2. **Before every read, check if the process is still alive.** If alive → only read log, NEVER restart.\n\n**Every 5 seconds, run this exact sequence:**\n```bash\n# Step 1: extract PID from log\nPPT_PID=$(grep '^\\[PID\\]' \"$PPT_LOG\" | tail -1 | awk '{print $2}')\n# Step 2: check if process is alive\nkill -0 \"$PPT_PID\" 2>/dev/null && PPT_ALIVE=true || PPT_ALIVE=false\n# Step 3: read the log regardless\ntail -20 \"$PPT_LOG\"\n```\n- If process is **RUNNING** → report status to user, wait 5s, repeat. Do NOT touch the script.\n- If process is **not running** AND log ends with `[DONE]` or `[ERROR]` → stop polling, proceed to deliver/handle error.\n- If process is **not running** AND no `[DONE]`/`[ERROR]` in log → the script crashed; report error to user, ask whether to retry. **Both conditions must hold: PID gone AND no terminal log line. NEVER retry without explicit user confirmation.**\n\nEach line is plain text: \n- `[PID] <pid>` — process ID written at startup\n- `[START]` — job started\n- `[PHASE] <message>` — in progress\n- `[DONE] saved=<path> download_url=<url>` — finished\n- `[ERROR] <message>` — failed\n\n**After each read, report status to the user:**\n```\n[Main stage] | [current action] \nExample: Generating slides | Working on page 3 \n```\n\nProgress phases:\n\n| Message contains | Main stage |\n|-----------------|------------|\n| \"Parsing existing PPTX\" | Parsing original PPTX |\n| \"update plan\" | Planning updates |\n| \"updated slides\" / \"Slide N updated\" | Generating updated slides |\n| \"Exporting\" / \"Export complete\" | Exporting PPTX |\n\n**Stop polling** as soon as you see `[DONE]` or `[ERROR]`.\n\n---\n\n## 4. Deliver\n\nProvide all of the following:\n1. Download link (`download_url` from the completion event)\n2. Local `.pptx` absolute path\n3. Brief summary of what was changed (which pages, what modifications)\n\n### Failure\n\nBriefly explain the error.\n\nFile v1.0.8:workflow_generate.md\n\n# PPT Generate Workflow\n\nFollow these steps in order: confirm inputs → run script (streaming) → **output progress at every phase** (required) → save file → deliver. **Never go silent for an extended period — always stream progress as it arrives.**\n\n---\n\n## 1. Parse reference files (optional — only if the user provides local files)\n\nIf the user provides local files (PDF, DOCX, PPTX, images, etc.) as content source for the PPT, parse each file with the document parse service. This uploads the file, extracts its content, and returns metadata (file_id, file_url).\n\nRun `parse_file.py` once per filet, his may cost a few minutes to finish completely::\n\n```bash\n$PYTHON_CMD scripts/parse_file.py /path/to/file1.pdf\n$PYTHON_CMD scripts/parse_file.py /path/to/file2.docx\n```\n- **exec tool `yieldMs`**: Must be set to `600000` (10 minutes) when invoking the exec tool.\n\nEach call prints a `PARSED_FILE:` line on success:\n```\nPARSED_FILE: {\"filename\": \"file1.pdf\", \"url\": \"https://...\", \"file_id\": \"123456789\"}\n```\n\nCollect every `PARSED_FILE:` result and assemble them into a JSON array as `DOC_FILES_JSON`:\n```json\n[\n  {\"filename\":\"file1.pdf\",\"url\":\"https://...\",\"file_id\":\"123456789\",\"file_type\":\"pdf\"},\n  {\"filename\":\"file2.docx\",\"url\":\"https://...\",\"file_id\":\"987654321\",\"file_type\":\"docx\"}\n]\n```\n\nPass this array to `--files` in Step 3. If no local files are provided, skip this step entirely.\n\n---\n\n## 2. Web search (required if no relevant content is already in the conversation)\n\nSkip this step if the user has already provided sufficient reference material or reference files.\nOtherwise, run up to 3 targeted searches on the topic, make sure your query contains the date if you need to search the latest information:\n\n### Run searches\n\n```bash\n$PYTHON_CMD scripts/web_search.py \"query1\" \"query2\" \"query3\"\n```\n\n- Break the topic into 1–3 focused queries (e.g. for \"Beijing travel guide\": \"Beijing top attractions\", \"Beijing food recommendations\", \"Beijing transportation tips\").\n- **If the topic involves current events, trends, statistics, or anything time-sensitive**, append the current year (e.g. `2026`) or a date range to each query to ensure results are up to date. Example: `\"AI agent market trends 2026\"` instead of `\"AI agent market trends\"`.\n- Deduplicate and distill all results into a `reference` text to enrich the PPT content.\n\n### Synthesize search results\n\n**If reference files were parsed in Step 1**, use their `parsed_content` as the primary source and supplement with search results. The parsed content contains the full document text — extract and preserve all detail, do not compress it into a short summary.\n\nProduce a detailed **reference report**. **Target 800–2000 words — do not stop early.** Write as much specific detail as the sources provide:\n\n```\n## Key Findings\n3–5 sentences covering the main conclusions, background, and why it matters.\n\n## Key Data & Facts\n- List every specific number, percentage, date, and metric found. Do not skip data.\n- Format: \"Exact figure — what it measures (source)\"\n- Aim for at least 5 data points if the source contains them.\n\n## Topic Breakdown\nOrganize by sub-topic. For each sub-topic write 3–5 specific bullet points.\nDo not use vague phrases like \"it is important\" — state the actual fact.\nPreserve names of people, companies, products, places, and dates exactly as found.\n\n## Cases & Examples (if available)\nConcrete examples, case studies, or use cases with specific details and outcomes.\n\n## Summary\n3–5 bullet points capturing the core message the PPT must convey.\n```\n\n**Hard constraints**:\n- Only include information that **explicitly appears** in the sources. Do not invent or infer.\n- Numbers, percentages, and proper nouns must be quoted exactly — do not paraphrase or round.\n- **Never produce fewer than 500 words** unless the source material is genuinely sparse.\n- If a section has no relevant information, omit that section entirely.\n- **Note the publication date of each source.** Always include the current date context in the summary where relevant.\n\nAfter writing the reference report, save it to a local temp file to avoid shell encoding issues:\n```bash\ncat > /tmp/ppt_reference.md << 'REFERENCE_EOF'\n<paste the full reference report here>\nREFERENCE_EOF\n```\nUse this file path as `--reference-file` in Step 3.\n\n---\n\n## 2. Confirm inputs\n\n- **query** (required): Faithfully reproduce the user's full request — include every instruction the user mentioned. Cover the following if the user specified them; do not add anything they didn't mention:\n  - Slide count (if the user set a limit, it must be included — never drop it)\n  - Topic / content direction\n  - Style preference (e.g. business, academic, playful, minimalist)\n  - Audience / purpose (e.g. \"exec briefing for the CXO\", \"science explainer for kids\")\n  - Structure preference (e.g. \"data-heavy\", \"one case study per slide\")\n  - Other constraints (tone, things to avoid, required talking points, etc.)\n\n  **Rule**: Do not fabricate requirements the user never mentioned, and do not omit anything they explicitly said. If the user gives only a title, the query is exactly that title — don't add qualifiers.\n\n  **Examples**:\n\n  | User input | Correct query |\n  |------------|---------------|\n  | Make me a PPT about Beijing travel | `Beijing Travel Guide PPT` |\n  | 8-page English slides on AI Agent, clean business style, targeting investors | `8-page English slides on AI Agent, clean business style, targeting investors` |\n  | PPT for our Q1 sales summary, 10 slides, with data charts, formal style | `Q1 Sales Summary PPT, 10 slides, data charts, formal business style` |\n  | A fun solar system PPT for elementary school kids, 6 pages | `Solar System explainer PPT for elementary school kids, fun and engaging style, 6 slides` |\n\n- **language** (required): Detect from the user's input language — if the user writes in Chinese pass `Chinese`; English → `English`; etc. Never default to a fixed value.\n- **--reference-file** (optional): Pass the path to the temp file written at the end of Step 2 (e.g. `/tmp/ppt_reference.md`). Omit if no search was performed.\n- **--files** (optional): Pass the JSON array assembled from the `PARSED_FILE:` lines in Step 1. Omit if no files were provided. Format: `[{\"file_name\":\"...\",\"url\":\"...\",\"file_id\":\"...\", \"file_type\": \"pdf\"},...]`\n\n---\n\n## 3. Run the script\n\nPPT generation takes ~10 minutes. Choose a log path first, pass it to the script, then read it every 5 seconds.\n\n### 3a. Choose a log path and start in background\n```bash\nPPT_LOG=/tmp/ppt_$(date +%s).log\n\n$PYTHON_CMD scripts/run_ppt_write.py \"user query\" \\\n  --language English \\\n  --reference-file /tmp/ppt_reference.md \\\n  --files '[{\"file_name\":\"report.pdf\",\"url\":\"https://...\", \"file_id\":\"1212121\", \"file_type\":\"pdf\"}]' \\\n  --log_path \"$PPT_LOG\" \\\n  -o /absolute/path/to/output.pptx \\\n  > /dev/null 2>&1 &\n\necho \"Log: $PPT_LOG\"\n```\n\n- **`--log_path`** (required): Pass the pre-chosen path. The script writes all progress here.\n- **`-o`** (required): Use an absolute path.\n- **`--files`**: JSON array from `DOC_FILES_JSON:` lines **verbatim**. Omit if no reference files.\n\n### 3b. Monitor progress （REQUIRED）\n\n> **STRICT RULES — no exceptions:**\n> 1. **Read the log exactly every 5 seconds.** Do NOT extend the interval, do NOT skip reads.\n> 2. **Before every read, check if the process is still alive.** If alive → only read log, NEVER restart.\n\n**Every 5 seconds, run this exact sequence:**\n```bash\n# Step 1: extract PID from log\nPPT_PID=$(grep '^\\[PID\\]' \"$PPT_LOG\" | tail -1 | awk '{print $2}')\n# Step 2: check if process is alive\nkill -0 \"$PPT_PID\" 2>/dev/null && PPT_ALIVE=true || PPT_ALIVE=false\n# Step 3: read the log regardless\ntail -20 \"$PPT_LOG\"\n```\n- If process is **RUNNING** → report status to user, wait 5s, repeat. Do NOT touch the script.\n- If process is **not running** AND log ends with `[DONE]` or `[ERROR]` → stop polling, proceed to deliver/handle error.\n- If process is **not running** AND no `[DONE]`/`[ERROR]` in log → the script crashed; report error to user, ask whether to retry. **Both conditions must hold: PID gone AND no terminal log line. NEVER retry without explicit user confirmation.**\n\nEach line is plain text:\n- `[PID] <pid>` — process ID written at startup\n- `[START]` — job started\n- `[PHASE] <message>` — stage transition (outline, slides, export, etc.)\n- `[PING] <progress>% | <stage>` — heartbeat every few seconds with current progress and stage label\n- `[OUTLINE]` — outline content (appears once after outline_done)\n- `[DONE] saved=<path> download_url=<url>` — finished\n- `[ERROR] <message>` — failed\n\n**After each read, report status to the user:**\n```\n[Main stage] | [current action]\nExample: Generating slides | Working on page 3 \n```\n\nMap phase messages to main stages:\n\n| Message contains | Main stage |\n|-----------------|------------|\n| \"outline\" | Generating outline |\n| \"slide\" / \"page\" / \"content\" | Generating slides |\n| \"image\" / \"HTML\" | Rendering images |\n| \"Export\" / \"export\" | Exporting PPTX |\n| \"Parsing existing PPTX\" | Parsing original PPTX |\n| \"update plan\" | Planning updates |\n| \"template\" | Processing template |\n\n**Stop polling** as soon as you see `[DONE]` or `[ERROR]`.\n\n---\n\n## 4. Deliver\n\n### Success\n\nProvide all of the following:\n1. Download link\n2. Local `.pptx` absolute path\n3. Presentation title\n4. Brief description of each slide's content\n\n### Failure\n\nBriefly explain the error. \n\n## Technical Notes\n- **Timeout**: PPT generation takes ~10 minutes, set sufficient timeout\n\nFile v1.0.8:workflow_imitate.md\n\n# PPT Imitation Workflow\n\nThe user provides an existing PPTX file as a layout/style reference. Generate a new presentation on a different topic that follows the same visual structure.\n\nFollow these steps in order: identify intent → locate template → web search → upload template → run script (streaming) → **output progress at every phase** (required) → save file → deliver. **Never go silent for an extended period — always stream progress as it arrives.**\n\n---\n\n## 0. Confirm imitation intent\n\nUse this workflow (instead of the standard generate flow) when **both** of the following are true:\n\n- The user mentions a template, style reference, or an existing file — e.g. \"use this template\", \"match the style of this PPT\", \"imitate this layout\" — **or** provides a `.pptx` file path or filename.\n- The user has a new generation request (topic, content, slide count, etc.).\n\nIf the user provides a template but no new topic, **ask what they want to create** before proceeding.\n\n---\n\n## 1. Locate the local template file\n\nExtract the local PPTX path from the user's message. It may appear as:\n\n- An absolute path: `/Users/xxx/templates/style.pptx`\n- A relative path or filename: `my_template.pptx` (ask the user to confirm the exact full path before using it)\n- An attachment uploaded in the conversation (the platform will provide a local temp path)\n\n**If the path is ambiguous, ask the user for the full absolute path.**\n\n---\n\n## 2. Parse reference files (optional — only if the user provides local files as content source)\n\nIf the user provides additional local files (PDF, DOCX, PPTX, images, etc.) to use as content source — separate from the template — parse each file with the document parse service.\n\nRun `parse_file.py` once per file, this may cost a few minutes to finish completely:\n\n```bash\n$PYTHON_CMD scripts/parse_file.py /path/to/file1.pdf\n$PYTHON_CMD scripts/parse_file.py /path/to/file2.docx\n```\n- **exec tool `yieldMs`**: Must be set to `600000` (10 minutes) when invoking the exec tool.\n\nEach call prints a `PARSED_FILE:` line on success:\n```\nPARSED_FILE: {\"filename\": \"file1.pdf\", \"url\": \"https://...\", \"file_id\": \"123456789\"}\n```\n\nCollect every `PARSED_FILE:` result and assemble them into a JSON array as `DOC_FILES_JSON`:\n```json\n[\n  {\"filename\":\"file1.pdf\",\"url\":\"https://...\",\"file_id\":\"123456789\",\"file_type\":\"pdf\"},\n  {\"filename\":\"file2.docx\",\"url\":\"https://...\",\"file_id\":\"987654321\",\"file_type\":\"docx\"}\n]\n```\n\nPass this array to `--files` in Step 6. If no additional content files are provided, skip this step entirely.\n\n---\n\n## 3. Web search (required if no relevant content is already in the conversation)\n\nSkip if the user has already provided sufficient reference material or reference files.\nOtherwise, run up to 3 targeted searches on the **new PPT topic**:\n\n```bash\n$PYTHON_CMD scripts/web_search.py \"query1\" \"query2\" \"query3\"\n```\n\nProduce a detailed reference report following the same format and constraints as the generate workflow (target 800–2000 words, preserve all specific details, never fewer than 500 words).\n\nAfter writing the reference report, save it to a local temp file:\n```bash\ncat > /tmp/ppt_reference.md << 'REFERENCE_EOF'\n<paste the full reference report here>\nREFERENCE_EOF\n```\nUse this file path as `--reference-file` in Step 6.\n\n---\n\n## 4. Upload the template to OSS\n\n```bash\n$PYTHON_CMD scripts/upload_files.py \"/absolute/path/to/template.pptx\"\n```\n\n- Script output format: `[OK] /path/to/file.pptx -> https://cdn.xxx/skills/upload/yyyy-mm-dd/uuid_filename.pptx`\n- Extract the OSS URL from the output and call it `TEMPLATE_URL`.\n- If the upload fails, inform the user and stop.\n\n---\n\n## 5. Confirm generation parameters\n\n- **query** (required): Faithfully reproduce the user's full request — include every instruction (slide count, style, audience, etc.). Do not fabricate or omit anything.\n- **language** (required): Language for the slides, e.g. `Chinese`, `English`.\n- **language** (required): Detect from the user's input language — if the user writes in Chinese pass `Chinese`; English → `English`; etc. Never default to a fixed value.\n- **template_urls** (required): The OSS URL(s) from Step 4. Multiple URLs are supported (comma-separated) — the backend selects the best-matching layout from each. One URL is sufficient in most cases; pass multiple only if the user provided several template files.\n- **--reference-file** (optional): Path to the temp file written at the end of Step 3 (e.g. `/tmp/ppt_reference.md`). Omit if no search was performed.\n- **--files** (optional): Pass the JSON array assembled from the `PARSED_FILE:` lines in Step 2. Omit if no content files were provided. Format: `[{\"filename\":\"...\",\"url\":\"...\",\"file_id\":\"...\", \"file_type\": \"pdf\"},...]`\n\n---\n\n## 6. Run the script\n\nPPT generation takes ~10 minutes. Run it in the **background**, then read the progress log file every 5 seconds until done.\n\n### 6a. Choose a log path and start in background\n```bash\nPPT_LOG=/tmp/ppt_$(date +%s).log\n\n$PYTHON_CMD scripts/run_ppt_write.py \"user query\" \\\n  --language Chinese \\\n  --template_urls \"TEMPLATE_URL1,TEMPLATE_URL2\" \\\n  --reference-file /tmp/ppt_reference.md \\\n  --files '[{\"file_name\":\"report.pdf\",\"url\":\"https://...\", \"file_id\":\"1212121\", \"file_type\":\"pdf\"}]' \\\n  --log_path \"$PPT_LOG\" \\\n  -o /absolute/path/to/output.pptx \\\n  > /dev/null 2>&1 &\n\necho \"Log: $PPT_LOG\"\n```\n\n- **`--log_path`** (required): Pass the pre-chosen path. The script writes all progress here.\n- **`-o`** (required): Use an absolute path for reliable delivery.\n- **`--template_urls`**: Comma-separated OSS URLs of template files from Step 4.\n- **`--files`**: Pass the JSON array assembled from `PARSED_FILE:` lines **verbatim**. Omit if no reference files.\n\n### 6b. Monitor progress （REQUIRED）\n\n> **STRICT RULES — no exceptions:**\n> 1. **Read the log exactly every 5 seconds.** Do NOT extend the interval, do NOT skip reads.\n> 2. **Before every read, check if the process is still alive.** If alive → only read log, NEVER restart.\n\n**Every 5 seconds, run this exact sequence:**\n```bash\n# Step 1: extract PID from log\nPPT_PID=$(grep '^\\[PID\\]' \"$PPT_LOG\" | tail -1 | awk '{print $2}')\n# Step 2: check if process is alive\nkill -0 \"$PPT_PID\" 2>/dev/null && PPT_ALIVE=true || PPT_ALIVE=false\n# Step 3: read the log regardless\ntail -20 \"$PPT_LOG\"\n```\n- If process is **RUNNING** → report status to user, wait 5s, repeat. Do NOT touch the script.\n- If process is **not running** AND log ends with `[DONE]` or `[ERROR]` → stop polling, proceed to deliver/handle error.\n- If process is **not running** AND no `[DONE]`/`[ERROR]` in log → the script crashed; report error to user, ask whether to retry. **Both conditions must hold: PID gone AND no terminal log line. NEVER retry without explicit user confirmation.**\n\n\nEach line is plain text: \n- `[PID] <pid>` — process ID written at startup\n- `[START]` — job started\n- `[PHASE] <message>` — in progress\n- `[DONE] saved=<path> download_url=<url>` — finished\n- `[ERROR] <message>` — failed\n\n**After each read, report status to the user:**\n```\n[Main stage] | [current action] \nExample: Generating slides | Working on page 3 \n```\n\n**Stop polling** as soon as you see `[DONE]` or `[ERROR]`.\n\n\n## 7. Deliver\n\n### Success\n\nProvide all of the following:\n1. Download link\n2. Local `.pptx` absolute path\n3. Presentation title\n4. Brief description of each slide's content\n5. Template filename used (so the user can verify)\n\n### Failure\n\nBriefly explain the error.\n---\n\n## Appendix — Intent classification examples\n\n| User input | Use this workflow? |\n|------------|--------------------|\n| Make me a PPT about Beijing travel | ❌ Standard generate |\n| Use this template to make a PPT on AI trends — template at `/tmp/style.pptx` | ✅ Imitate |\n| Imitate the uploaded pptx style, 10-slide quarterly review | ✅ Imitate |\n| What style is this template? | ❌ Not a generation request — just answer the question |\n\nFile v1.0.8:workflow_local.md\n\n# Local PPTX Operations Workflow (Layer 3)\n\nNo backend or token needed — uses `python-pptx` to operate on local `.pptx` files directly.\n\n---\n\n## Install Dependencies\n\n```bash\npip install python-pptx\n```\n\n---\n\n## Trigger Keywords\n\nWhen the user expresses the following intents, use this workflow (instead of calling the backend API):\n\n| User Intent | Example Keywords |\n|----------|-----------|\n| View file info | View PPT page count, how many pages, pptx info |\n| Delete specific slides | Delete slide N, remove slide 3, delete slide 3, remove page 5 |\n| Reorder slides | Reorder PPT, rearrange slide order, reorder slides |\n| Extract slides | Extract slides 1-3, export certain slides, extract slides |\n| Merge files | Merge two PPTs, merge pptx, combine a and b |\n\n---\n\n## Unified Entry Point\n\nAll operations are done via `scripts/local_pptx_ops.py`:\n\n```bash\n$PYTHON_CMD scripts/local_pptx_ops.py <subcommand> [arguments]\n```\n\n---\n\n## Subcommand Details\n\n### info — View file info\n\n```bash\n$PYTHON_CMD scripts/local_pptx_ops.py info --file my.pptx\n```\n\nOutput: file path, total slides, dimensions, title of each slide.\n\n---\n\n### delete — Delete slides\n\n```bash\n# Delete slide 3\n$PYTHON_CMD scripts/local_pptx_ops.py delete --file my.pptx --slides 3\n\n# Delete slides 3, 5, 7-9, overwrite the original file\n$PYTHON_CMD scripts/local_pptx_ops.py delete --file my.pptx --slides 3,5,7-9\n\n# Save to a new file after deletion (don't overwrite the original)\n$PYTHON_CMD scripts/local_pptx_ops.py delete --file my.pptx --slides 3,5,7-9 -o trimmed.pptx\n```\n\n**Note**:\n- Page numbers are 1-based (slide 1 = 1)\n- Supports comma-separated and `-` ranges, e.g. `1,3,5-8,10`\n- If `-o` is not specified, the original file is overwritten\n\n---\n\n### reorder — Reorder slide order\n\n```bash\n# Move original slide 2 to position 1, slide 1 to position 2 (rest unchanged)\n$PYTHON_CMD scripts/local_pptx_ops.py reorder --file my.pptx --order 2,1,3,4,5\n\n# Save to a new file\n$PYTHON_CMD scripts/local_pptx_ops.py reorder --file my.pptx --order 2,1,3,4,5 -o reordered.pptx\n```\n\n**Note**: `--order` must include all page numbers — no omissions or duplicates.\n\n---\n\n### extract — Extract specific slides\n\n```bash\n# Extract slides 1 through 3\n$PYTHON_CMD scripts/local_pptx_ops.py extract --file my.pptx --slides 1-3 -o subset.pptx\n\n# Extract slides 1, 3, 5\n$PYTHON_CMD scripts/local_pptx_ops.py extract --file my.pptx --slides 1,3,5 -o subset.pptx\n```\n\nExtracted result is saved as a new file (original file is not modified).\n\n---\n\n### merge — Merge multiple files\n\n```bash\n# Merge two files\n$PYTHON_CMD scripts/local_pptx_ops.py merge --files a.pptx b.pptx -o merged.pptx\n\n# Merge three or more\n$PYTHON_CMD scripts/local_pptx_ops.py merge --files a.pptx b.pptx c.pptx -o merged.pptx\n```\n\n**Note**: The slide dimensions of the first file are used as the standard; shapes are preserved as much as possible during merging, but complex animations/video effects may be lost.\n\n---\n\n## Agent Decision Logic\n\nUser intent → Route selection:\n\n```\nUser says \"Generate a PPT about X\"\n  → Layer 1: scripts/run_ppt_write.py (call backend to generate)\n\nUser says \"Delete slide 3 from this PPT\" / \"Merge these two pptx\" / \"Extract the first 5 slides\"\n  → Layer 3: scripts/local_pptx_ops.py (local operation, no token needed)\n```\n\n---\n\n## FAQ\n\n**Q: Do page numbers change after deletion?**\nA: Yes. After deletion, page numbers are renumbered starting from 1. If you need to delete multiple slides, it's recommended to pass them all at once (`--slides 3,5,7`) rather than running multiple times.\n\n**Q: What if styles are wrong after merging?**\nA: Merging uses deep-copy of the shape tree; themes/masters come from the first file. If there are significant style differences, manual adjustments in PowerPoint are recommended.\n\n**Q: Does python-pptx support deleting slides?**\nA: Not natively. This tool operates on the underlying XML (`_sldIdLst`), consistent with common python-pptx community approaches.\n\nArchive v1.0.7: 14 files, 32320 bytes\n\nFiles: references/apikey-fetch.md (1791b), scripts/constant.py (81b), scripts/local_pptx_ops.py (13562b), scripts/parse_file.py (6798b), scripts/run_ppt_write.py (15459b), scripts/skywork_auth.py (284b), scripts/upload_files.py (4900b), scripts/web_search.py (2493b), SKILL.md (9822b), workflow_edit.md (4275b), workflow_generate.md (9584b), workflow_imitate.md (7973b), workflow_local.md (3981b), _meta.json (130b)\n\nFile v1.0.7:SKILL.md\n\n---\nname: Skywork-ppt\ndescription: |\n  Skywork PPT (skywork) - Use this skill when the user wants to work with PowerPoint presentations. Triggers include:\n  - Generating a new PPT from a topic: 'generate a PPT' / '帮我做个PPT' / 'PPTを作って' / 'PPT 만들어줘', 'create a presentation about X' / '生成关于X的演示文稿' / 'Xについてのプレゼンを作って' / 'X에 대한 발표 자료 만들어줘', 'help me make slides' / '帮我做幻灯片' / 'スライドを作って' / '슬라이드 만들어줘'\n  - Imitating an existing .pptx style/template: 'use this template' / '用这个模板' / 'このテンプレートを使って' / '이 템플릿을 써줘', 'imitate this PPT' / '仿照这个PPT' / 'このPPTを真似して' / '이 PPT를 따라 해줘', 'imitate this style' / '仿照这个风格' / 'このスタイルを真似して' / '이 스타일을 따라 해줘'\n  - Editing an existing PPT via natural language: 'modify slide N' / '修改第N页' / 'N枚目のスライドを修正して' / 'N번 슬라이드 수정해줘', 'change the background' / '更换背景' / '背景を変えて' / '배경 바꿔줘', 'add a slide' / '新增一页幻灯片' / 'スライドを追加して' / '슬라이드 추가해줘', 'make it more beautiful' / '美化一下PPT' / 'もっときれいにして' / '더 예쁘게 다듬어줘', 'edit this PPT' / '改一下这个PPT' / 'このPPTを編集して' / '이 PPT 수정해줘'\n  - Local file operations on .pptx (no backend): 'delete slide N' / '删除第N页' / 'N枚目のスライドを削除して' / 'N번 슬라이드 삭제해줘', 'reorder slides' / '调整幻灯片顺序' / 'スライドを並べ替えて' / '슬라이드 순서 바꿔줘', 'merge pptx' / '合并PPT' / 'pptxを結合して' / 'pptx 합쳐줘', 'extract slides' / '提取幻灯片' / 'スライドを抽出して' / '슬라이드 추출해줘', 'how many slides' / '有多少页幻灯片' / 'スライドは何枚ある' / '슬라이드 몇 장이야'\nmetadata:\n  openclaw:\n    requires:\n      bins:\n        - python3\n      env:\n        - SKYWORK_API_KEY\n    primaryEnv: SKYWORK_API_KEY\n---\n\n# PPT Write Skill\n\nFour capabilities: **generate**, **template imitation**, **edit existing PPT**, and **local file operations**.\n\n---\n\n## Prerequisites\n\n### API Key Configuration (Required First)\nThis skill requires a **SKYWORK_API_KEY** to be configured in OpenClaw.\n\nIf you don't have an API key yet, please visit:\n**https://skywork.ai**\n\nFor detailed setup instructions, see:\n[references/apikey-fetch.md](references/apikey-fetch.md)\n\n---\n\n## Privacy & Remote Calls (Read Before Use)\n\n- **Remote upload & processing**: Layers 1/2/4 upload local files and send the full, verbatim user query to the Skywork service. Avoid sensitive or confidential content unless you trust the remote service and its data handling policies.\n- **Polling behavior**: The generation/edit workflows include periodic status polling (about every 5 seconds) while waiting for backend jobs. This is expected.\n\n---\n\n## Routing — Identify the user's intent first\n\n| User intent | Which path |\n|-------------|------------|\n| Generate a new PPT from a topic, set of requirements or reference files | **Layer 1** — Generate |\n| Use an existing .pptx as a layout/style template to create a new presentation | **Layer 2** — Imitate |\n| Edit an existing PPT: modify slides, add slides, change style, split/merge | **Layer 4** — Edit |\n| Delete / reorder / extract / merge slides in a local file (no backend) | **Layer 3** — Local ops |\n\n---\n\n## Environment check (always run this first)\n\n**This skill requires Python 3 (>=3.8). Run the following before any script to locate a valid Python binary and install dependencies.**\n\n```bash\nPYTHON_CMD=\"\"\nfor cmd in python3 python python3.13 python3.12 python3.11 python3.10 python3.9 python3.8; do\n  if command -v \"$cmd\" &>/dev/null && \"$cmd\" -c \"import sys; exit(0 if sys.version_info >= (3,8) else 1)\" 2>/dev/null; then\n    PYTHON_CMD=\"$cmd\"\n    break\n  fi\ndone\n\nif [ -z \"$PYTHON_CMD\" ]; then\n  echo \"ERROR: Python 3.8+ not found.\"\n  echo \"Install on macOS: brew install python3  or visit https://www.python.org/downloads/\"\n  exit 1\nfi\n\necho \"Found Python: $PYTHON_CMD ($($PYTHON_CMD --version))\"\n\n$PYTHON_CMD -m pip install -q --break-system-packages python-pptx\necho \"Dependencies ready.\"\n```\n\n> After this check, replace `python` with the discovered `$PYTHON_CMD` (e.g. `python3`) in all subsequent commands.\n\n---\n\n## Layer 1 — Generate PPT\n\n### Steps\n0. **REQUIRED FIRST STEP** — Read [workflow_generate.md](workflow_generate.md) NOW, before taking any other action. After reading, output exactly: `✅ workflow_generate.md loaded.` — then proceed.\n1. **Environment check** — run the check above to get `$PYTHON_CMD`.\n2. **Upload reference files** (if the user provides local files as content source) — parse the file using tool in script/parse_file.py and pass the result to `--files`. See the `--files` note below.\n3. **Web search** (required if no relevant content is already in the conversation) — call web_search tool in script to search the topic and distill results into a `reference-file` file of ≤ 2000 words.\n4. **Run the script**:\n   > **Important**: set exec tool `yieldMs` to `600000` (10 minutes).\n5. **Deliver** — provide the absolute `.pptx` path and the download URL.\n\n---\n\n## Layer 2 — Imitate PPT (template-based generation)\n\n### Steps\n0. **REQUIRED FIRST STEP** - Read [workflow_imitate.md](workflow_imitate.md) immidiately before any action you do!!!\n1. **Environment check** — run the check above to get `$PYTHON_CMD`.\n2. **Locate the template** — extract the absolute path of the local `.pptx` from the user's message; ask the user if it's unclear.\n3. **Upload the template** — upload it and extract `TEMPLATE_URL` from the output.\n4. **Upload reference files** (if the user provides additional local files as content source) — parse the file using tool in script/parse_file.py and pass the result to `--files`. See the `--files` \n5. **Web search** (required if no relevant content is already in the conversation) — call web_search tool in script to search the new topic and distill results into a `reference-file` file of ≤ 2000 words.\n6. **Run the script**:\n   > **Important**: set exec tool `yieldMs` to `600000` (10 minutes).\n7. **Deliver** — provide the absolute `.pptx` path, the download URL, and the template filename used.\n\n---\n\n## Layer 4 — Edit PPT (AI-powered modification)\n\nUse this layer when the user wants to modify an existing PPT using natural language. Requires an OSS/CDN URL of the PPTX (from a previous generation or upload).\n\n### Steps\n0. **Detailed workflow** - Read [workflow_edit.md](workflow_edit.md) immediately before any action you do!!!\n1. **Environment check** — run the check above to get `$PYTHON_CMD`.\n2. **Get PPTX URL** — from the user's message or upload a local file first.\n3. **Run the script** with `--pptx-url`:\n   ```bash\n   $PYTHON_CMD scripts/run_ppt_write.py \"edit instruction\" \\\n     --language Chinese \\\n     --pptx-url \"https://cdn.example.com/file.pptx\" \\\n     -o /absolute/path/output.pptx\n   ```\n   > **Important**: set exec tool `yieldMs` to `600000` (10 minutes).\n4. **Deliver** — provide download link, local path, and summary of changes.\n\n---\n\n## Layer 3 — PPT File operations\n\n```bash\n# Inspect slide count and titles\n$PYTHON_CMD scripts/local_pptx_ops.py info --file my.pptx\n\n# Delete slides (1-based index; supports ranges like 3,5,7-9; omit -o to overwrite in place)\n$PYTHON_CMD scripts/local_pptx_ops.py delete --file my.pptx --slides 3,5,7-9 -o trimmed.pptx\n\n# Reorder slides (must list every slide, no omissions)\n$PYTHON_CMD scripts/local_pptx_ops.py reorder --file my.pptx --order 2,1,4,3,5\n\n# Extract a subset of slides into a new file\n$PYTHON_CMD scripts/local_pptx_ops.py extract --file my.pptx --slides 1-3 -o subset.pptx\n\n# Merge multiple files\n$PYTHON_CMD scripts/local_pptx_ops.py merge --files a.pptx b.pptx -o merged.pptx\n```\n\nRead [workflow_local.md](workflow_local.md) immidiately before any action you do!!!\n\n---\n\n## Error Handling\n\n- **Insufficient benefit**: When calling scripts (generate, imitate, or edit), the script or log may show a message like `Insufficient benefit. Please upgrade your account at {url}`, meaning the user's benefit level does not meet the requirement for this skill.\n\n### How to reply when benefit is insufficient\n\nWhen you detect the above, **reply in the user's current language** — do not echo the English message. Use this pattern:\n\n- Convey: \"Sorry, PPT generation failed. This skill requires upgrading your Skywork membership to use.\" then a single call-to-action link.\n- **Format**: One short sentence in the user's language + a link like `[Upgrade now →](url)` or the equivalent in their language .\n- **URL**: Extract the upgrade URL from the log/script output (e.g. the `at https://...` part).\n\n> Note: Only suggest upgrading when the error is **Insufficient benefit**. For auth errors like `NO_TOKEN` / `INVALID_TOKEN` / `401` / “invalid API key”, keep the error code / raw message and guide users to update `SKYWORK_API_KEY`. **Do not** suggest upgrading membership.\n\n---\n\n## Dependencies\n\n- **Python 3.8+** (required) — `python3` / `python` must be on PATH\n- Layer 3 local ops: `pip install python-pptx --break-system-packages`\n\n(The environment check step installs all required dependencies automatically.)\n\n---\n\n## Which layer to trigger?\n\n| Scenario | Use |\n|----------|-----|\n| Generate a PPT from a topic or existing reference files | Layer 1 |\n| Imitate the layout/style of an existing .pptx | Layer 2 |\n| Edit/modify an existing PPT via natural language | Layer 4 |\n| Delete / reorder / extract / merge local .pptx files (no backend) | Layer 3 |\n\nFile v1.0.7:_meta.json\n\n{\n  \"ownerId\": \"kn70ct0m3p4538a9t49cjcwern82ky02\",\n  \"slug\": \"skywork-ppt\",\n  \"version\": \"1.0.7\",\n  \"publishedAt\": 1775788026396\n}\n\nFile v1.0.7:references/apikey-fetch.md\n\n# Skywork API Key Setup Guide (OpenClaw)\n\n## SKYWORK_API_KEY Not Configured\n\nWhen the `SKYWORK_API_KEY` environment variable is not set, follow these steps:\n\n### 1. Get API Key\n\nVisit the Skywork website and sign in to your account:\n\n**https://skywork.ai**\n\n- Log in with your Skywork account\n- Open account / Settings / API Key (**https://skywork.ai/?openApiKeySetting=1**)\n- Create or copy your **API key**\n\nIf your organization uses a separate console or test environment, use the URL and credentials your team provides.\n\n### 2. Configure OpenClaw\n\nEdit the OpenClaw configuration file: `~/.openclaw/openclaw.json`\n\nIn current OpenClaw, Skywork skills store the key under `skills.entries.<Skill Name>.apiKey` (not under `env`).\nOpenClaw will inject this value into the skill's `SKYWORK_API_KEY` environment when `primaryEnv` matches.\nAdd or merge the following structure (adjust the skill name to match the installed skill):\n\n```json\n{\n  \"skills\": {\n    \"entries\": {\n      \"Skywork-ppt\": {\n        \"enabled\": true,\n        \"apiKey\": \"your_actual_skywork_api_key_here\"\n      }\n    }\n  }\n}\n```\n\nReplace `\"your_actual_skywork_api_key_here\"` with your real key.\n\nFor multiple Skywork skills, repeat the same `apiKey` field on each skill entry.\n\n### 3. Verify Configuration\n\n```bash\n# Check JSON format\ncat ~/.openclaw/openclaw.json | python3 -m json.tool\n```\n\n### 4. Restart OpenClaw\n\n```bash\nopenclaw gateway restart\n```\n\n## Troubleshooting\n\n- Ensure `~/.openclaw/openclaw.json` exists and is valid JSON\n- Confirm the API key is active and not expired\n- Check Skywork account status, membership, or quota if requests fail with auth or benefit errors\n- Restart OpenClaw after configuration changes\n\n**Recommended**: Use the OpenClaw configuration file for centralized environment management.\n\nFile v1.0.7:workflow_edit.md\n\n# PPT Edit Workflow\n\nEdit an existing PPT via natural language: modify individual slides, add new slides, change the overall style, split or merge slides.\n\nFollow these steps in order: get pptx_url → confirm intent → run script (background) → **read log every 5s and report progress** (required) → deliver. **Never go silent — always report status as you poll the log.**\n\n---\n\n## 1. Get the PPTX URL\n\nThe user must supply a publicly accessible OSS/CDN URL of the existing PPTX to edit.\n\n- If the user provides a **local file path** instead of a URL, upload it first:\n  ```bash\n  $PYTHON_CMD scripts/upload_files.py \"/absolute/path/to/file.pptx\"\n  ```\n  Extract the URL from the `[OK] ... -> https://...` output line.\n\n- If the URL is already provided (e.g. from a previous generation's `Download URL:` output), use it directly.\n\n---\n\n## 2. Confirm edit intent\n\nUnderstand what the user wants to change. Supported operations include:\n\n| Operation | Example user intent |\n|-----------|---------------------|\n| Modify a slide | \"change page 4 background to black, text to white\" |\n| Add a new slide | \"insert a new slide after page 3 about X\" |\n| Change overall style | \"make all slides use a dark theme\" |\n| Split a slide | \"split page 5 into two slides\" |\n| Merge slides | \"merge pages 2 and 3 into one slide\" |\n\nPass the user's original instruction verbatim as `query`. Do not paraphrase — the backend interprets it directly.\n\n---\n\n## 3. Run the script\n\nRun in the **background**, then read the progress log file every 5 seconds until done.\n\n### 3a. Choose a log path and start in background\n```bash\nPPT_LOG=/tmp/ppt_$(date +%s).log\n\n$PYTHON_CMD scripts/run_ppt_write.py \"user's edit instruction\" \\\n  --language Chinese \\\n  --pptx-url \"https://cdn.example.com/path/to/file.pptx\" \\\n  --log_path \"$PPT_LOG\" \\\n  -o /absolute/path/to/output.pptx \\\n  > /dev/null 2>&1 &\n\necho \"Log: $PPT_LOG\"\n```\n\n- **`--log_path`** (required): Pass the pre-chosen path. The script writes all progress here.\n- **`--pptx-url`** (required): OSS URL of the PPTX to edit. This triggers edit mode.\n- **`--language`** (required): Detect from user input — `Chinese` or `English`.\n- **`-o`** (required): Absolute output path for the edited PPTX.\n\n### 3b. Monitor progress （REQUIRED）\n\n> **STRICT RULES — no exceptions:**\n> 1. **Read the log exactly every 5 seconds.** Do NOT extend the interval, do NOT skip reads.\n> 2. **Before every read, check if the process is still alive.** If alive → only read log, NEVER restart.\n\n**Every 5 seconds, run this exact sequence:**\n```bash\n# Step 1: extract PID from log\nPPT_PID=$(grep '^\\[PID\\]' \"$PPT_LOG\" | tail -1 | awk '{print $2}')\n# Step 2: check if process is alive\nkill -0 \"$PPT_PID\" 2>/dev/null && PPT_ALIVE=true || PPT_ALIVE=false\n# Step 3: read the log regardless\ntail -20 \"$PPT_LOG\"\n```\n- If process is **RUNNING** → report status to user, wait 5s, repeat. Do NOT touch the script.\n- If process is **not running** AND log ends with `[DONE]` or `[ERROR]` → stop polling, proceed to deliver/handle error.\n- If process is **not running** AND no `[DONE]`/`[ERROR]` in log → the script crashed; report error to user, ask whether to retry. **Both conditions must hold: PID gone AND no terminal log line. NEVER retry without explicit user confirmation.**\n\nEach line is plain text: \n- `[PID] <pid>` — process ID written at startup\n- `[START]` — job started\n- `[PHASE] <message>` — in progress\n- `[DONE] saved=<path> download_url=<url>` — finished\n- `[ERROR] <message>` — failed\n\n**After each read, report status to the user:**\n```\n[Main stage] | [current action] \nExample: Generating slides | Working on page 3 \n```\n\nProgress phases:\n\n| Message contains | Main stage |\n|-----------------|------------|\n| \"Parsing existing PPTX\" | Parsing original PPTX |\n| \"update plan\" | Planning updates |\n| \"updated slides\" / \"Slide N updated\" | Generating updated slides |\n| \"Exporting\" / \"Export complete\" | Exporting PPTX |\n\n**Stop polling** as soon as you see `[DONE]` or `[ERROR]`.\n\n---\n\n## 4. Deliver\n\nProvide all of the following:\n1. Download link (`download_url` from the completion event)\n2. Local `.pptx` absolute path\n3. Brief summary of what was changed (which pages, what modifications)\n\n### Failure\n\nBriefly explain the error.\n\nFile v1.0.7:workflow_generate.md\n\n# PPT Generate Workflow\n\nFollow these steps in order: confirm inputs → run script (streaming) → **output progress at every phase** (required) → save file → deliver. **Never go silent for an extended period — always stream progress as it arrives.**\n\n---\n\n## 1. Parse reference files (optional — only if the user provides local files)\n\nIf the user provides local files (PDF, DOCX, PPTX, images, etc.) as content source for the PPT, parse each file with the document parse service. This uploads the file, extracts its content, and returns metadata (file_id, file_url).\n\nRun `parse_file.py` once per filet, his may cost a few minutes to finish completely::\n\n```bash\n$PYTHON_CMD scripts/parse_file.py /path/to/file1.pdf\n$PYTHON_CMD scripts/parse_file.py /path/to/file2.docx\n```\n- **exec tool `yieldMs`**: Must be set to `600000` (10 minutes) when invoking the exec tool.\n\nEach call prints a `PARSED_FILE:` line on success:\n```\nPARSED_FILE: {\"filename\": \"file1.pdf\", \"url\": \"https://...\", \"file_id\": \"123456789\"}\n```\n\nCollect every `PARSED_FILE:` result and assemble them into a JSON array as `DOC_FILES_JSON`:\n```json\n[\n  {\"filename\":\"file1.pdf\",\"url\":\"https://...\",\"file_id\":\"123456789\",\"file_type\":\"pdf\"},\n  {\"filename\":\"file2.docx\",\"url\":\"https://...\",\"file_id\":\"987654321\",\"file_type\":\"docx\"}\n]\n```\n\nPass this array to `--files` in Step 3. If no local files are provided, skip this step entirely.\n\n---\n\n## 2. Web search (required if no relevant content is already in the conversation)\n\nSkip this step if the user has already provided sufficient reference material or reference files.\nOtherwise, run up to 3 targeted searches on the topic, make sure your query contains the date if you need to search the latest information:\n\n### Run searches\n\n```bash\n$PYTHON_CMD scripts/web_search.py \"query1\" \"query2\" \"query3\"\n```\n\n- Break the topic into 1–3 focused queries (e.g. for \"Beijing travel guide\": \"Beijing top attractions\", \"Beijing food recommendations\", \"Beijing transportation tips\").\n- **If the topic involves current events, trends, statistics, or anything time-sensitive**, append the current year (e.g. `2026`) or a date range to each query to ensure results are up to date. Example: `\"AI agent market trends 2026\"` instead of `\"AI agent market trends\"`.\n- Deduplicate and distill all results into a `reference` text to enrich the PPT content.\n\n### Synthesize search results\n\n**If reference files were parsed in Step 1**, use their `parsed_content` as the primary source and supplement with search results. The parsed content contains the full document text — extract and preserve all detail, do not compress it into a short summary.\n\nProduce a detailed **reference report**. **Target 800–2000 words — do not stop early.** Write as much specific detail as the sources provide:\n\n```\n## Key Findings\n3–5 sentences covering the main conclusions, background, and why it matters.\n\n## Key Data & Facts\n- List every specific number, percentage, date, and metric found. Do not skip data.\n- Format: \"Exact figure — what it measures (source)\"\n- Aim for at least 5 data points if the source contains them.\n\n## Topic Breakdown\nOrganize by sub-topic. For each sub-topic write 3–5 specific bullet points.\nDo not use vague phrases like \"it is important\" — state the actual fact.\nPreserve names of people, companies, products, places, and dates exactly as found.\n\n## Cases & Examples (if available)\nConcrete examples, case studies, or use cases with specific details and outcomes.\n\n## Summary\n3–5 bullet points capturing the core message the PPT must convey.\n```\n\n**Hard constraints**:\n- Only include information that **explicitly appears** in the sources. Do not invent or infer.\n- Numbers, percentages, and proper nouns must be quoted exactly — do not paraphrase or round.\n- **Never produce fewer than 500 words** unless the source material is genuinely sparse.\n- If a section has no relevant information, omit that section entirely.\n- **Note the publication date of each source.** Always include the current date context in the summary where relevant.\n\nAfter writing the reference report, save it to a local temp file to avoid shell encoding issues:\n```bash\ncat > /tmp/ppt_reference.md << 'REFERENCE_EOF'\n<paste the full reference report here>\nREFERENCE_EOF\n```\nUse this file path as `--reference-file` in Step 3.\n\n---\n\n## 2. Confirm inputs\n\n- **query** (required): Faithfully reproduce the user's full request — include every instruction the user mentioned. Cover the following if the user specified them; do not add anything they didn't mention:\n  - Slide count (if the user set a limit, it must be included — never drop it)\n  - Topic / content direction\n  - Style preference (e.g. business, academic, playful, minimalist)\n  - Audience / purpose (e.g. \"exec briefing for the CXO\", \"science explainer for kids\")\n  - Structure preference (e.g. \"data-heavy\", \"one case study per slide\")\n  - Other constraints (tone, things to avoid, required talking points, etc.)\n\n  **Rule**: Do not fabricate requirements the user never mentioned, and do not omit anything they explicitly said. If the user gives only a title, the query is exactly that title — don't add qualifiers.\n\n  **Examples**:\n\n  | User input | Correct query |\n  |------------|---------------|\n  | Make me a PPT about Beijing travel | `Beijing Travel Guide PPT` |\n  | 8-page English slides on AI Agent, clean business style, targeting investors | `8-page English slides on AI Agent, clean business style, targeting investors` |\n  | PPT for our Q1 sales summary, 10 slides, with data charts, formal style | `Q1 Sales Summary PPT, 10 slides, data charts, formal business style` |\n  | A fun solar system PPT for elementary school kids, 6 pages | `Solar System explainer PPT for elementary school kids, fun and engaging style, 6 slides` |\n\n- **language** (required): Detect from the user's input language — if the user writes in Chinese pass `Chinese`; English → `English`; etc. Never default to a fixed value.\n- **--reference-file** (optional): Pass the path to the temp file written at the end of Step 2 (e.g. `/tmp/ppt_reference.md`). Omit if no search was performed.\n- **--files** (optional): Pass the JSON array assembled from the `PARSED_FILE:` lines in Step 1. Omit if no files were provided. Format: `[{\"file_name\":\"...\",\"url\":\"...\",\"file_id\":\"...\", \"file_type\": \"pdf\"},...]`\n\n---\n\n## 3. Run the script\n\nPPT generation takes ~10 minutes. Choose a log path first, pass it to the script, then read it every 5 seconds.\n\n### 3a. Choose a log path and start in background\n```bash\nPPT_LOG=/tmp/ppt_$(date +%s).log\n\n$PYTHON_CMD scripts/run_ppt_write.py \"user query\" \\\n  --language English \\\n  --reference-file /tmp/ppt_reference.md \\\n  --files '[{\"file_name\":\"report.pdf\",\"url\":\"https://...\", \"file_id\":\"1212121\", \"file_type\":\"pdf\"}]' \\\n  --log_path \"$PPT_LOG\" \\\n  -o /absolute/path/to/output.pptx \\\n  > /dev/null 2>&1 &\n\necho \"Log: $PPT_LOG\"\n```\n\n- **`--log_path`** (required): Pass the pre-chosen path. The script writes all progress here.\n- **`-o`** (required): Use an absolute path.\n- **`--files`**: JSON array from `DOC_FILES_JSON:` lines **verbatim**. Omit if no reference files.\n\n### 3b. Monitor progress （REQUIRED）\n\n> **STRICT RULES — no exceptions:**\n> 1. **Read the log exactly every 5 seconds.** Do NOT extend the interval, do NOT skip reads.\n> 2. **Before every read, check if the process is still alive.** If alive → only read log, NEVER restart.\n\n**Every 5 seconds, run this exact sequence:**\n```bash\n# Step 1: extract PID from log\nPPT_PID=$(grep '^\\[PID\\]' \"$PPT_LOG\" | tail -1 | awk '{print $2}')\n# Step 2: check if process is alive\nkill -0 \"$PPT_PID\" 2>/dev/null && PPT_ALIVE=true || PPT_ALIVE=false\n# Step 3: read the log regardless\ntail -20 \"$PPT_LOG\"\n```\n- If process is **RUNNING** → report status to user, wait 5s, repeat. Do NOT touch the script.\n- If process is **not running** AND log ends with `[DONE]` or `[ERROR]` → stop polling, proceed to deliver/handle error.\n- If process is **not running** AND no `[DONE]`/`[ERROR]` in log → the script crashed; report error to user, ask whether to retry. **Both conditions must hold: PID gone AND no terminal log line. NEVER retry without explicit user confirmation.**\n\nEach line is plain text:\n- `[PID] <pid>` — process ID written at startup\n- `[START]` — job started\n- `[PHASE] <message>` — stage transition (outline, slides, export, etc.)\n- `[PING] <progress>% | <stage>` — heartbeat every few seconds with current progress and stage label\n- `[OUTLINE]` — outline content (appears once after outline_done)\n- `[DONE] saved=<path> download_url=<url>` — finished\n- `[ERROR] <message>` — failed\n\n**After each read, report status to the user:**\n```\n[Main stage] | [current action]\nExample: Generating slides | Working on page 3 \n```\n\nMap phase messages to main stages:\n\n| Message contains | Main stage |\n|-----------------|------------|\n| \"outline\" | Generating outline |\n| \"slide\" / \"page\" / \"content\" | Generating slides |\n| \"image\" / \"HTML\" | Rendering images |\n| \"Export\" / \"export\" | Exporting PPTX |\n| \"Parsing existing PPTX\" | Parsing original PPTX |\n| \"update plan\" | Planning updates |\n| \"template\" | Processing template |\n\n**Stop polling** as soon as you see `[DONE]` or `[ERROR]`.\n\n---\n\n## 4. Deliver\n\n### Success\n\nProvide all of the following:\n1. Download link\n2. Local `.pptx` absolute path\n3. Presentation title\n4. Brief description of each slide's content\n\n### Failure\n\nBriefly explain the error. \n\n## Technical Notes\n- **Timeout**: PPT generation takes ~10 minutes, set sufficient timeout\n\nFile v1.0.7:workflow_imitate.md\n\n# PPT Imitation Workflow\n\nThe user provides an existing PPTX file as a layout/style reference. Generate a new presentation on a different topic that follows the same visual structure.\n\nFollow these steps in order: identify intent → locate template → web search → upload template → run script (streaming) → **output progress at every phase** (required) → save file → deliver. **Never go silent for an extended period — always stream progress as it arrives.**\n\n---\n\n## 0. Confirm imitation intent\n\nUse this workflow (instead of the standard generate flow) when **both** of the following are true:\n\n- The user mentions a template, style reference, or an existing file — e.g. \"use this template\", \"match the style of this PPT\", \"imitate this layout\" — **or** provides a `.pptx` file path or filename.\n- The user has a new generation request (topic, content, slide count, etc.).\n\nIf the user provides a template but no new topic, **ask what they want to create** before proceeding.\n\n---\n\n## 1. Locate the local template file\n\nExtract the local PPTX path from the user's message. It may appear as:\n\n- An absolute path: `/Users/xxx/templates/style.pptx`\n- A relative path or filename: `my_template.pptx` (ask the user to confirm the exact full path before using it)\n- An attachment uploaded in the conversation (the platform will provide a local temp path)\n\n**If the path is ambiguous, ask the user for the full absolute path.**\n\n---\n\n## 2. Parse reference files (optional — only if the user provides local files as content source)\n\nIf the user provides additional local files (PDF, DOCX, PPTX, images, etc.) to use as content source — separate from the template — parse each file with the document parse service.\n\nRun `parse_file.py` once per file, this may cost a few minutes to finish completely:\n\n```bash\n$PYTHON_CMD scripts/parse_file.py /path/to/file1.pdf\n$PYTHON_CMD scripts/parse_file.py /path/to/file2.docx\n```\n- **exec tool `yieldMs`**: Must be set to `600000` (10 minutes) when invoking the exec tool.\n\nEach call prints a `PARSED_FILE:` line on success:\n```\nPARSED_FILE: {\"filename\": \"file1.pdf\", \"url\": \"https://...\", \"file_id\": \"123456789\"}\n```\n\nCollect every `PARSED_FILE:` result and assemble them into a JSON array as `DOC_FILES_JSON`:\n```json\n[\n  {\"filename\":\"file1.pdf\",\"url\":\"https://...\",\"file_id\":\"123456789\",\"file_type\":\"pdf\"},\n  {\"filename\":\"file2.docx\",\"url\":\"https://...\",\"file_id\":\"987654321\",\"file_type\":\"docx\"}\n]\n```\n\nPass this array to `--files` in Step 6. If no additional content files are provided, skip this step entirely.\n\n---\n\n## 3. Web search (required if no relevant content is already in the conversation)\n\nSkip if the user has already provided sufficient reference material or reference files.\nOtherwise, run up to 3 targeted searches on the **new PPT topic**:\n\n```bash\n$PYTHON_CMD scripts/web_search.py \"query1\" \"query2\" \"query3\"\n```\n\nProduce a detailed reference report following the same format and constraints as the generate workflow (target 800–2000 words, preserve all specific details, never fewer than 500 words).\n\nAfter writing the reference report, save it to a local temp file:\n```bash\ncat > /tmp/ppt_reference.md << 'REFERENCE_EOF'\n<paste the full reference report here>\nREFERENCE_EOF\n```\nUse this file path as `--reference-file` in Step 6.\n\n---\n\n## 4. Upload the template to OSS\n\n```bash\n$PYTHON_CMD scripts/upload_files.py \"/absolute/path/to/template.pptx\"\n```\n\n- Script output format: `[OK] /path/to/file.pptx -> https://cdn.xxx/skills/upload/yyyy-mm-dd/uuid_filename.pptx`\n- Extract the OSS URL from the output and call it `TEMPLATE_URL`.\n- If the upload fails, inform the user and stop.\n\n---\n\n## 5. Confirm generation parameters\n\n- **query** (required): Faithfully reproduce the user's full request — include every instruction (slide count, style, audience, etc.). Do not fabricate or omit anything.\n- **language** (required): Language for the slides, e.g. `Chinese`, `English`.\n- **language** (required): Detect from the user's input language — if the user writes in Chinese pass `Chinese`; English → `English`; etc. Never default to a fixed value.\n- **template_urls** (required): The OSS URL(s) from Step 4. Multiple URLs are supported (comma-separated) — the backend selects the best-matching layout from each. One URL is sufficient in most cases; pass multiple only if the user provided several template files.\n- **--reference-file** (optional): Path to the temp file written at the end of Step 3 (e.g. `/tmp/ppt_reference.md`). Omit if no search was performed.\n- **--files** (optional): Pass the JSON array assembled from the `PARSED_FILE:` lines in Step 2. Omit if no content files were provided. Format: `[{\"filename\":\"...\",\"url\":\"...\",\"file_id\":\"...\", \"file_type\": \"pdf\"},...]`\n\n---\n\n## 6. Run the script\n\nPPT generation takes ~10 minutes. Run it in the **background**, then read the progress log file every 5 seconds until done.\n\n### 6a. Choose a log path and start in background\n```bash\nPPT_LOG=/tmp/ppt_$(date +%s).log\n\n$PYTHON_CMD scripts/run_ppt_write.py \"user query\" \\\n  --language Chinese \\\n  --template_urls \"TEMPLATE_URL1,TEMPLATE_URL2\" \\\n  --reference-file /tmp/ppt_reference.md \\\n  --files '[{\"file_name\":\"report.pdf\",\"url\":\"https://...\", \"file_id\":\"1212121\", \"file_type\":\"pdf\"}]' \\\n  --log_path \"$PPT_LOG\" \\\n  -o /absolute/path/to/output.pptx \\\n  > /dev/null 2>&1 &\n\necho \"Log: $PPT_LOG\"\n```\n\n- **`--log_path`** (required): Pass the pre-chosen path. The script writes all progress here.\n- **`-o`** (required): Use an absolute path for reliable delivery.\n- **`--template_urls`**: Comma-separated OSS URLs of template files from Step 4.\n- **`--files`**: Pass the JSON array assembled from `PARSED_FILE:` lines **verbatim**. Omit if no reference files.\n\n### 6b. Monitor progress （REQUIRED）\n\n> **STRICT RULES — no exceptions:**\n> 1. **Read the log exactly every 5 seconds.** Do NOT extend the interval, do NOT skip reads.\n> 2. **Before every read, check if the process is still alive.** If alive → only read log, NEVER restart.\n\n**Every 5 seconds, run this exact sequence:**\n```bash\n# Step 1: extract PID from log\nPPT_PID=$(grep '^\\[PID\\]' \"$PPT_LOG\" | tail -1 | awk '{print $2}')\n# Step 2: check if process is alive\nkill -0 \"$PPT_PID\" 2>/dev/null && PPT_ALIVE=true || PPT_ALIVE=false\n# Step 3: read the log regardless\ntail -20 \"$PPT_LOG\"\n```\n- If process is **RUNNING** → report status to user, wait 5s, repeat. Do NOT touch the script.\n- If process is **not running** AND log ends with `[DONE]` or `[ERROR]` → stop polling, proceed to deliver/handle error.\n- If process is **not running** AND no `[DONE]`/`[ERROR]` in log → the script crashed; report error to user, ask whether to retry. **Both conditions must hold: PID gone AND no terminal log line. NEVER retry without explicit user confirmation.**\n\n\nEach line is plain text: \n- `[PID] <pid>` — process ID written at startup\n- `[START]` — job started\n- `[PHASE] <message>` — in progress\n- `[DONE] saved=<path> download_url=<url>` — finished\n- `[ERROR] <message>` — failed\n\n**After each read, report status to the user:**\n```\n[Main stage] | [current action] \nExample: Generating slides | Working on page 3 \n```\n\n**Stop polling** as soon as you see `[DONE]` or `[ERROR]`.\n\n\n## 7. Deliver\n\n### Success\n\nProvide all of the following:\n1. Download link\n2. Local `.pptx` absolute path\n3. Presentation title\n4. Brief description of each slide's content\n5. Template filename used (so the user can verify)\n\n### Failure\n\nBriefly explain the error.\n---\n\n## Appendix — Intent classification examples\n\n| User input | Use this workflow? |\n|------------|--------------------|\n| Make me a PPT about Beijing travel | ❌ Standard generate |\n| Use this template to make a PPT on AI trends — template at `/tmp/style.pptx` | ✅ Imitate |\n| Imitate the uploaded pptx style, 10-slide quarterly review | ✅ Imitate |\n| What style is this template? | ❌ Not a generation request — just answer the question |\n\nFile v1.0.7:workflow_local.md\n\n# Local PPTX Operations Workflow (Layer 3)\n\nNo backend or token needed — uses `python-pptx` to operate on local `.pptx` files directly.\n\n---\n\n## Install Dependencies\n\n```bash\npip install python-pptx\n```\n\n---\n\n## Trigger Keywords\n\nWhen the user expresses the following intents, use this workflow (instead of calling the backend API):\n\n| User Intent | Example Keywords |\n|----------|-----------|\n| View file info | View PPT page count, how many pages, pptx info |\n| Delete specific slides | Delete slide N, remove slide 3, delete slide 3, remove page 5 |\n| Reorder slides | Reorder PPT, rearrange slide order, reorder slides |\n| Extract slides | Extract slides 1-3, export certain slides, extract slides |\n| Merge files | Merge two PPTs, merge pptx, combine a and b |\n\n---\n\n## Unified Entry Point\n\nAll operations are done via `scripts/local_pptx_ops.py`:\n\n```bash\n$PYTHON_CMD scripts/local_pptx_ops.py <subcommand> [arguments]\n```\n\n---\n\n## Subcommand Details\n\n### info — View file info\n\n```bash\n$PYTHON_CMD scripts/local_pptx_ops.py info --file my.pptx\n```\n\nOutput: file path, total slides, dimensions, title of each slide.\n\n---\n\n### delete — Delete slides\n\n```bash\n# Delete slide 3\n$PYTHON_CMD scripts/local_pptx_ops.py delete --file my.pptx --slides 3\n\n# Delete slides 3, 5, 7-9, overwrite the original file\n$PYTHON_CMD scripts/local_pptx_ops.py delete --file my.pptx --slides 3,5,7-9\n\n# Save to a new file after deletion (don't overwrite the original)\n$PYTHON_CMD scripts/local_pptx_ops.py delete --file my.pptx --slides 3,5,7-9 -o trimmed.pptx\n```\n\n**Note**:\n- Page numbers are 1-based (slide 1 = 1)\n- Supports comma-separated and `-` ranges, e.g. `1,3,5-8,10`\n- If `-o` is not specified, the original file is overwritten\n\n---\n\n### reorder — Reorder slide order\n\n```bash\n# Move original slide 2 to position 1, slide 1 to position 2 (rest unchanged)\n$PYTHON_CMD scripts/local_pptx_ops.py reorder --file my.pptx --order 2,1,3,4,5\n\n# Save to a new file\n$PYTHON_CMD scripts/local_pptx_ops.py reorder --file my.pptx --order 2,1,3,4,5 -o reordered.pptx\n```\n\n**Note**: `--order` must include all page numbers — no omissions or duplicates.\n\n---\n\n### extract — Extract specific slides\n\n```bash\n# Extract slides 1 through 3\n$PYTHON_CMD scripts/local_pptx_ops.py extract --file my.pptx --slides 1-3 -o subset.pptx\n\n# Extract slides 1, 3, 5\n$PYTHON_CMD scripts/local_pptx_ops.py extract --file my.pptx --slides 1,3,5 -o subset.pptx\n```\n\nExtracted result is saved as a new file (original file is not modified).\n\n---\n\n### merge — Merge multiple files\n\n```bash\n# Merge two files\n$PYTHON_CMD scripts/local_pptx_ops.py merge --files a.pptx b.pptx -o merged.pptx\n\n# Merge three or more\n$PYTHON_CMD scripts/local_pptx_ops.py merge --files a.pptx b.pptx c.pptx -o merged.pptx\n```\n\n**Note**: The slide dimensions of the first file are used as the standard; shapes are preserved as much as possible during merging, but complex animations/video effects may be lost.\n\n---\n\n## Agent Decision Logic\n\nUser intent → Route selection:\n\n```\nUser says \"Generate a PPT about X\"\n  → Layer 1: scripts/run_ppt_write.py (call backend to generate)\n\nUser says \"Delete slide 3 from this PPT\" / \"Merge these two pptx\" / \"Extract the first 5 slides\"\n  → Layer 3: scripts/local_pptx_ops.py (local operation, no token needed)\n```\n\n---\n\n## FAQ\n\n**Q: Do page numbers change after deletion?**\nA: Yes. After deletion, page numbers are renumbered starting from 1. If you need to delete multiple slides, it's recommended to pass them all at once (`--slides 3,5,7`) rather than running multiple times.\n\n**Q: What if styles are wrong after merging?**\nA: Merging uses deep-copy of the shape tree; themes/masters come from the first file. If there are significant style differences, manual adjustments in PowerPoint are recommended.\n\n**Q: Does python-pptx support deleting slides?**\nA: Not natively. This tool operates on the underlying XML (`_sldIdLst`), consistent with common python-pptx community approaches.\n\nArchive v1.0.6: 14 files, 32372 bytes\n\nFiles: references/apikey-fetch.md (1791b), scripts/constant.py (81b), scripts/local_pptx_ops.py (13562b), scripts/parse_file.py (6798b), scripts/run_ppt_write.py (15459b), scripts/skywork_auth.py (284b), scripts/upload_files.py (4900b), scripts/web_search.py (2493b), SKILL.md (9988b), workflow_edit.md (4275b), workflow_generate.md (9584b), workflow_imitate.md (7946b), workflow_local.md (3981b), _meta.json (130b)\n\nFile v1.0.6:SKILL.md\n\n---\nname: Skywork-ppt\ndescription: |\n  Skywork PPT (skywork) - Use this skill when the user wants to work with PowerPoint presentations. Triggers include:\n  - Generating a new PPT from a topic: 'generate a PPT' / '帮我做个PPT' / 'PPTを作って' / 'PPT 만들어줘', 'create a presentation about X' / '生成关于X的演示文稿' / 'Xについてのプレゼンを作って' / 'X에 대한 발표 자료 만들어줘', 'help me make slides' / '帮我做幻灯片' / 'スライドを作って' / '슬라이드 만들어줘'\n  - Imitating an existing .pptx style/template: 'use this template' / '用这个模板' / 'このテンプレートを使って' / '이 템플릿을 써줘', 'imitate this PPT' / '仿照这个PPT' / 'このPPTを真似して' / '이 PPT를 따라 해줘', 'imitate this style' / '仿照这个风格' / 'このスタイルを真似して' / '이 스타일을 따라 해줘'\n  - Editing an existing PPT via natural language: 'modify slide N' / '修改第N页' / 'N枚目のスライドを修正して' / 'N번 슬라이드 수정해줘', 'change the background' / '更换背景' / '背景を変えて' / '배경 바꿔줘', 'add a slide' / '新增一页幻灯片' / 'スライドを追加して' / '슬라이드 추가해줘', 'make it more beautiful' / '美化一下PPT' / 'もっときれいにして' / '더 예쁘게 다듬어줘', 'edit this PPT' / '改一下这个PPT' / 'このPPTを編集して' / '이 PPT 수정해줘'\n  - Local file operations on .pptx (no backend): 'delete slide N' / '删除第N页' / 'N枚目のスライドを削除して' / 'N번 슬라이드 삭제해줘', 'reorder slides' / '调整幻灯片顺序' / 'スライドを並べ替えて' / '슬라이드 순서 바꿔줘', 'merge pptx' / '合并PPT' / 'pptxを結合して' / 'pptx 합쳐줘', 'extract slides' / '提取幻灯片' / 'スライドを抽出して' / '슬라이드 추출해줘', 'how many slides' / '有多少页幻灯片' / 'スライドは何枚ある' / '슬라이드 몇 장이야'\nmetadata:\n  openclaw:\n    requires:\n      bins:\n        - python3\n      env:\n        - SKYWORK_API_KEY\n    primaryEnv: SKYWORK_API_KEY\n---\n\n# PPT Write Skill\n\nFour capabilities: **generate**, **template imitation**, **edit existing PPT**, and **local file operations**.\n\n---\n\n## Prerequisites\n\n### API Key Configuration (Required First)\nThis skill requires a **SKYWORK_API_KEY** to be configured in OpenClaw.\n\nIf you don't have an API key yet, please visit:\n**https://skywork.ai**\n\nFor detailed setup instructions, see:\n[references/apikey-fetch.md](references/apikey-fetch.md)\n\n---\n\n## Privacy & Remote Calls (Read Before Use)\n\n- **Remote upload & processing**: Layers 1/2/4 upload local files and send the full, verbatim user query to the Skywork service. Avoid sensitive or confidential content unless you trust the remote service and its data handling policies.\n- **Local-only operations**: Layer 3 (local ops) runs entirely on-device and does **not** call the remote gateway. Use Layer 3 if you need strict local processing.\n- **Polling behavior**: The generation/edit workflows include periodic status polling (about every 5 seconds) while waiting for backend jobs. This is expected.\n\n---\n\n## Routing — Identify the user's intent first\n\n| User intent | Which path |\n|-------------|------------|\n| Generate a new PPT from a topic, set of requirements or reference files | **Layer 1** — Generate |\n| Use an existing .pptx as a layout/style template to create a new presentation | **Layer 2** — Imitate |\n| Edit an existing PPT: modify slides, add slides, change style, split/merge | **Layer 4** — Edit |\n| Delete / reorder / extract / merge slides in a local file (no backend) | **Layer 3** — Local ops |\n\n---\n\n## Environment check (always run this first)\n\n**This skill requires Python 3 (>=3.8). Run the following before any script to locate a valid Python binary and install dependencies.**\n\n```bash\nPYTHON_CMD=\"\"\nfor cmd in python3 python python3.13 python3.12 python3.11 python3.10 python3.9 python3.8; do\n  if command -v \"$cmd\" &>/dev/null && \"$cmd\" -c \"import sys; exit(0 if sys.version_info >= (3,8) else 1)\" 2>/dev/null; then\n    PYTHON_CMD=\"$cmd\"\n    break\n  fi\ndone\n\nif [ -z \"$PYTHON_CMD\" ]; then\n  echo \"ERROR: Python 3.8+ not found.\"\n  echo \"Install on macOS: brew install python3  or visit https://www.python.org/downloads/\"\n  exit 1\nfi\n\necho \"Found Python: $PYTHON_CMD ($($PYTHON_CMD --version))\"\n\n$PYTHON_CMD -m pip install -q --break-system-packages python-pptx\necho \"Dependencies ready.\"\n```\n\n> After this check, replace `python` with the discovered `$PYTHON_CMD` (e.g. `python3`) in all subsequent commands.\n\n---\n\n## Layer 1 — Generate PPT\n\n### Steps\n0. **REQUIRED FIRST STEP** — Read [workflow_generate.md](workflow_generate.md) NOW, before taking any other action. After reading, output exactly: `✅ workflow_generate.md loaded.` — then proceed.\n1. **Environment check** — run the check above to get `$PYTHON_CMD`.\n2. **Upload reference files** (if the user provides local files as content source) — parse the file using tool in script/parse_file.py and pass the result to `--files`. See the `--files` note below.\n3. **Web search** (required if no relevant content is already in the conversation) — call web_search tool in script to search the topic and distill results into a `reference-file` file of ≤ 2000 words.\n4. **Run the script**:\n   > **Important**: set exec tool `yieldMs` to `600000` (10 minutes).\n5. **Deliver** — provide the absolute `.pptx` path and the download URL.\n\n---\n\n## Layer 2 — Imitate PPT (template-based generation)\n\n### Steps\n0. **REQUIRED FIRST STEP** - Read [workflow_imitate.md](workflow_imitate.md) immidiately before any action you do!!!\n1. **Environment check** — run the check above to get `$PYTHON_CMD`.\n2. **Locate the template** — extract the absolute path of the local `.pptx` from the user's message; ask the user if it's unclear.\n3. **Upload the template** — upload it and extract `TEMPLATE_URL` from the output.\n4. **Upload reference files** (if the user provides additional local files as content source) — parse the file using tool in script/parse_file.py and pass the result to `--files`. See the `--files` \n5. **Web search** (required if no relevant content is already in the conversation) — call web_search tool in script to search the new topic and distill results into a `reference-file` file of ≤ 2000 words.\n6. **Run the script**:\n   > **Important**: set exec tool `yieldMs` to `600000` (10 minutes).\n7. **Deliver** — provide the absolute `.pptx` path, the download URL, and the template filename used.\n\n---\n\n## Layer 4 — Edit PPT (AI-powered modification)\n\nUse this layer when the user wants to modify an existing PPT using natural language. Requires an OSS/CDN URL of the PPTX (from a previous generation or upload).\n\n### Steps\n0. **Detailed workflow** - Read [workflow_edit.md](workflow_edit.md) immediately before any action you do!!!\n1. **Environment check** — run the check above to get `$PYTHON_CMD`.\n2. **Get PPTX URL** — from the user's message or upload a local file first.\n3. **Run the script** with `--pptx-url`:\n   ```bash\n   $PYTHON_CMD scripts/run_ppt_write.py \"edit instruction\" \\\n     --language Chinese \\\n     --pptx-url \"https://cdn.example.com/file.pptx\" \\\n     -o /absolute/path/output.pptx\n   ```\n   > **Important**: set exec tool `yieldMs` to `600000` (10 minutes).\n4. **Deliver** — provide download link, local path, and summary of changes.\n\n---\n\n## Layer 3 — Local file operations\n\n```bash\n# Inspect slide count and titles\n$PYTHON_CMD scripts/local_pptx_ops.py info --file my.pptx\n\n# Delete slides (1-based index; supports ranges like 3,5,7-9; omit -o to overwrite in place)\n$PYTHON_CMD scripts/local_pptx_ops.py delete --file my.pptx --slides 3,5,7-9 -o trimmed.pptx\n\n# Reorder slides (must list every slide, no omissions)\n$PYTHON_CMD scripts/local_pptx_ops.py reorder --file my.pptx --order 2,1,4,3,5\n\n# Extract a subset of slides into a new file\n$PYTHON_CMD scripts/local_pptx_ops.py extract --file my.pptx --slides 1-3 -o subset.pptx\n\n# Merge multiple files\n$PYTHON_CMD scripts/local_pptx_ops.py merge --files a.pptx b.pptx -o merged.pptx\n```\n\nRead [workflow_local.md](workflow_local.md) immidiately before any action you do!!!\n\n---\n\n## Error Handling\n\n- **Insufficient benefit**: When calling scripts (generate, imitate, or edit), the script or log may show a message like `Insufficient benefit. Please upgrade your account at {url}`, meaning the user's benefit level does not meet the requirement for this skill.\n\n### How to reply when benefit is insufficient\n\nWhen you detect the above, **reply in the user's current language** — do not echo the English message. Use this pattern:\n\n- Convey: \"Sorry, PPT generation failed. This skill requires upgrading your Skywork membership to use.\" then a single call-to-action link.\n- **Format**: One short sentence in the user's language + a link like `[Upgrade now →](url)` or the equivalent in their language .\n- **URL**: Extract the upgrade URL from the log/script output (e.g. the `at https://...` part).\n\n> Note: Only suggest upgrading when the error is **Insufficient benefit**. For auth errors like `NO_TOKEN` / `INVALID_TOKEN` / `401` / “invalid API key”, keep the error code / raw message and guide users to update `SKYWORK_API_KEY`. **Do not** suggest upgrading membership.\n\n---\n\n## Dependencies\n\n- **Python 3.8+** (required) — `python3` / `python` must be on PATH\n- Layer 3 local ops: `pip install python-pptx --break-system-packages`\n\n(The environment check step installs all required dependencies automatically.)\n\n---\n\n## Which layer to trigger?\n\n| Scenario | Use |\n|----------|-----|\n| Generate a PPT from a topic or existing reference files | Layer 1 |\n| Imitate the layout/style of an existing .pptx | Layer 2 |\n| Edit/modify an existing PPT via natural language | Layer 4 |\n| Delete / reorder / extract / merge local .pptx files (no backend) | Layer 3 |\n\nFile v1.0.6:_meta.json\n\n{\n  \"ownerId\": \"kn70ct0m3p4538a9t49cjcwern82ky02\",\n  \"slug\": \"skywork-ppt\",\n  \"version\": \"1.0.6\",\n  \"publishedAt\": 1775736498926\n}\n\nFile v1.0.6:references/apikey-fetch.md\n\n# Skywork API Key Setup Guide (OpenClaw)\n\n## SKYWORK_API_KEY Not Configured\n\nWhen the `SKYWORK_API_KEY` environment variable is not set, follow these steps:\n\n### 1. Get API Key\n\nVisit the Skywork website and sign in to your account:\n\n**https://skywork.ai**\n\n- Log in with your Skywork account\n- Open account / Settings / API Key (**https://skywork.ai/?openApiKeySetting=1**)\n- Create or copy your **API key**\n\nIf your organization uses a separate console or test environment, use the URL and credentials your team provides.\n\n### 2. Configure OpenClaw\n\nEdit the OpenClaw configuration file: `~/.openclaw/openclaw.json`\n\nIn current OpenClaw, Skywork skills store the key under `skills.entries.<Skill Name>.apiKey` (not under `env`).\nOpenClaw will inject this value into the skill's `SKYWORK_API_KEY` environment when `primaryEnv` matches.\nAdd or merge the following structure (adjust the skill name to match the installed skill):\n\n```json\n{\n  \"skills\": {\n    \"entries\": {\n      \"Skywork-ppt\": {\n        \"enabled\": true,\n        \"apiKey\": \"your_actual_skywork_api_key_here\"\n      }\n    }\n  }\n}\n```\n\nReplace `\"your_actual_skywork_api_key_here\"` with your real key.\n\nFor multiple Skywork skills, repeat the same `apiKey` field on each skill entry.\n\n### 3. Verify Configuration\n\n```bash\n# Check JSON format\ncat ~/.openclaw/openclaw.json | python3 -m json.tool\n```\n\n### 4. Restart OpenClaw\n\n```bash\nopenclaw gateway restart\n```\n\n## Troubleshooting\n\n- Ensure `~/.openclaw/openclaw.json` exists and is valid JSON\n- Confirm the API key is active and not expired\n- Check Skywork account status, membership, or quota if requests fail with auth or benefit errors\n- Restart OpenClaw after configuration changes\n\n**Recommended**: Use the OpenClaw configuration file for centralized environment management.\n\nFile v1.0.6:workflow_edit.md\n\n# PPT Edit Workflow\n\nEdit an existing PPT via natural language: modify individual slides, add new slides, change the overall style, split or merge slides.\n\nFollow these steps in order: get pptx_url → confirm intent → run script (background) → **read log every 5s and report progress** (required) → deliver. **Never go silent — always report status as you poll the log.**\n\n---\n\n## 1. Get the PPTX URL\n\nThe user must supply a publicly accessible OSS/CDN URL of the existing PPTX to edit.\n\n- If the user provides a **local file path** instead of a URL, upload it first:\n  ```bash\n  $PYTHON_CMD scripts/upload_files.py \"/absolute/path/to/file.pptx\"\n  ```\n  Extract the URL from the `[OK] ... -> https://...` output line.\n\n- If the URL is already provided (e.g. from a previous generation's `Download URL:` output), use it directly.\n\n---\n\n## 2. Confirm edit intent\n\nUnderstand what the user wants to change. Supported operations include:\n\n| Operation | Example user intent |\n|-----------|---------------------|\n| Modify a slide | \"change page 4 background to black, text to white\" |\n| Add a new slide | \"insert a new slide after page 3 about X\" |\n| Change overall style | \"make all slides use a dark theme\" |\n| Split a slide | \"split page 5 into two slides\" |\n| Merge slides | \"merge pages 2 and 3 into one slide\" |\n\nPass the user's original instruction verbatim as `query`. Do not paraphrase — the backend interprets it directly.\n\n---\n\n## 3. Run the script\n\nRun in the **background**, then read the progress log file every 5 seconds until done.\n\n### 3a. Choose a log path and start in background\n```bash\nPPT_LOG=/tmp/ppt_$(date +%s).log\n\n$PYTHON_CMD scripts/run_ppt_write.py \"user's edit instruction\" \\\n  --language Chinese \\\n  --pptx-url \"https://cdn.example.com/path/to/file.pptx\" \\\n  --log_path \"$PPT_LOG\" \\\n  -o /absolute/path/to/output.pptx \\\n  > /dev/null 2>&1 &\n\necho \"Log: $PPT_LOG\"\n```\n\n- **`--log_path`** (required): Pass the pre-chosen path. The script writes all progress here.\n- **`--pptx-url`** (required): OSS URL of the PPTX to edit. This triggers edit mode.\n- **`--language`** (required): Detect from user input — `Chinese` or `English`.\n- **`-o`** (required): Absolute output path for the edited PPTX.\n\n### 3b. Monitor progress （REQUIRED）\n\n> **STRICT RULES — no exceptions:**\n> 1. **Read the log exactly every 5 seconds.** Do NOT extend the interval, do NOT skip reads.\n> 2. **Before every read, check if the process is still alive.** If alive → only read log, NEVER restart.\n\n**Every 5 seconds, run this exact sequence:**\n```bash\n# Step 1: extract PID from log\nPPT_PID=$(grep '^\\[PID\\]' \"$PPT_LOG\" | tail -1 | awk '{print $2}')\n# Step 2: check if process is alive\nkill -0 \"$PPT_PID\" 2>/dev/null && PPT_ALIVE=true || PPT_ALIVE=false\n# Step 3: read the log regardless\ntail -20 \"$PPT_LOG\"\n```\n- If process is **RUNNING** → report status to user, wait 5s, repeat. Do NOT touch the script.\n- If process is **not running** AND log ends with `[DONE]` or `[ERROR]` → stop polling, proceed to deliver/handle error.\n- If process is **not running** AND no `[DONE]`/`[ERROR]` in log → the script crashed; report error to user, ask whether to retry. **Both conditions must hold: PID gone AND no terminal log line. NEVER retry without explicit user confirmation.**\n\nEach line is plain text: \n- `[PID] <pid>` — process ID written at startup\n- `[START]` — job started\n- `[PHASE] <message>` — in progress\n- `[DONE] saved=<path> download_url=<url>` — finished\n- `[ERROR] <message>` — failed\n\n**After each read, report status to the user:**\n```\n[Main stage] | [current action] \nExample: Generating slides | Working on page 3 \n```\n\nProgress phases:\n\n| Message contains | Main stage |\n|-----------------|------------|\n| \"Parsing existing PPTX\" | Parsing original PPTX |\n| \"update plan\" | Planning updates |\n| \"updated slides\" / \"Slide N updated\" | Generating updated slides |\n| \"Exporting\" / \"Export complete\" | Exporting PPTX |\n\n**Stop polling** as soon as you see `[DONE]` or `[ERROR]`.\n\n---\n\n## 4. Deliver\n\nProvide all of the following:\n1. Download link (`download_url` from the completion event)\n2. Local `.pptx` absolute path\n3. Brief summary of what was changed (which pages, what modifications)\n\n### Failure\n\nBriefly explain the error.\n\nFile v1.0.6:workflow_generate.md\n\n# PPT Generate Workflow\n\nFollow these steps in order: confirm inputs → run script (streaming) → **output progress at every phase** (required) → save file → deliver. **Never go silent for an extended period — always stream progress as it arrives.**\n\n---\n\n## 1. Parse reference files (optional — only if the user provides local files)\n\nIf the user provides local files (PDF, DOCX, PPTX, images, etc.) as content source for the PPT, parse each file with the document parse service. This uploads the file, extracts its content, and returns metadata (file_id, file_url).\n\nRun `parse_file.py` once per filet, his may cost a few minutes to finish completely::\n\n```bash\n$PYTHON_CMD scripts/parse_file.py /path/to/file1.pdf\n$PYTHON_CMD scripts/parse_file.py /path/to/file2.docx\n```\n- **exec tool `yieldMs`**: Must be set to `600000` (10 minutes) when invoking the exec tool.\n\nEach call prints a `PARSED_FILE:` line on success:\n```\nPARSED_FILE: {\"filename\": \"file1.pdf\", \"url\": \"https://...\", \"file_id\": \"123456789\"}\n```\n\nCollect every `PARSED_FILE:` result and assemble them into a JSON array as `DOC_FILES_JSON`:\n```json\n[\n  {\"filename\":\"file1.pdf\",\"url\":\"https://...\",\"file_id\":\"123456789\",\"file_type\":\"pdf\"},\n  {\"filename\":\"file2.docx\",\"url\":\"https://...\",\"file_id\":\"987654321\",\"file_type\":\"docx\"}\n]\n```\n\nPass this array to `--files` in Step 3. If no local files are provided, skip this step entirely.\n\n---\n\n## 2. Web search (required if no relevant content is already in the conversation)\n\nSkip this step if the user has already provided sufficient reference material or reference files.\nOtherwise, run up to 3 targeted searches on the topic, make sure your query contains the date if you need to search the latest information:\n\n### Run searches\n\n```bash\n$PYTHON_CMD scripts/web_search.py \"query1\" \"query2\" \"query3\"\n```\n\n- Break the topic into 1–3 focused queries (e.g. for \"Beijing travel guide\": \"Beijing top attractions\", \"Beijing food recommendations\", \"Beijing transportation tips\").\n- **If the topic involves current events, trends, statistics, or anything time-sensitive**, append the current year (e.g. `2026`) or a date range to each query to ensure results are up to date. Example: `\"AI agent market trends 2026\"` instead of `\"AI agent market trends\"`.\n- Deduplicate and distill all results into a `reference` text to enrich the PPT content.\n\n### Synthesize search results\n\n**If reference files were parsed in Step 1**, use their `parsed_content` as the primary source and supplement with search results. The parsed content contains the full document text — extract and preserve all detail, do not compress it into a short summary.\n\nProduce a detailed **reference report**. **Target 800–2000 words — do not stop early.** Write as much specific detail as the sources provide:\n\n```\n## Key Findings\n3–5 sentences covering the main conclusions, background, and why it matters.\n\n## Key Data & Facts\n- List every specific number, percentage, date, and metric found. Do not skip data.\n- Format: \"Exact figure — what it measures (source)\"\n- Aim for at least 5 data points if the source contains them.\n\n## Topic Breakdown\nOrganize by sub-topic. For each sub-topic write 3–5 specific bullet points.\nDo not use vague phrases like \"it is important\" — state the actual fact.\nPreserve names of people, companies, products, places, and dates exactly as found.\n\n## Cases & Examples (if available)\nConcrete examples, case studies, or use cases with specific details and outcomes.\n\n## Summary\n3–5 bullet points capturing the core message the PPT must convey.\n```\n\n**Hard constraints**:\n- Only include information that **explicitly appears** in the sources. Do not invent or infer.\n- Numbers, percentages, and proper nouns must be quoted exactly — do not paraphrase or round.\n- **Never produce fewer than 500 words** unless the source material is genuinely sparse.\n- If a section has no relevant information, omit that section entirely.\n- **Note the publication date of each source.** Always include the current date context in the summary where relevant.\n\nAfter writing the reference report, save it to a local temp file to avoid shell encoding issues:\n```bash\ncat > /tmp/ppt_reference.md << 'REFERENCE_EOF'\n<paste the full reference report here>\nREFERENCE_EOF\n```\nUse this file path as `--reference-file` in Step 3.\n\n---\n\n## 2. Confirm inputs\n\n- **query** (required): Faithfully reproduce the user's full request — include every instruction the user mentioned. Cover the following if the user specified them; do not add anything they didn't mention:\n  - Slide count (if the user set a limit, it must be included — never drop it)\n  - Topic / content direction\n  - Style preference (e.g. business, academic, playful, minimalist)\n  - Audience / purpose (e.g. \"exec briefing for the CXO\", \"science explainer for kids\")\n  - Structure preference (e.g. \"data-heavy\", \"one case study per slide\")\n  - Other constraints (tone, things to avoid, required talking points, etc.)\n\n  **Rule**: Do not fabricate requirements the user never mentioned, and do not omit anything they explicitly said. If the user gives only a title, the query is exactly that title — don't add qualifiers.\n\n  **Examples**:\n\n  | User input | Correct query |\n  |------------|---------------|\n  | Make me a PPT about Beijing travel | `Beijing Travel Guide PPT` |\n  | 8-page English slides on AI Agent, clean business style, targeting investors | `8-page English slides on AI Agent, clean business style, targeting investors` |\n  | PPT for our Q1 sales summary, 10 slides, with data charts, formal style | `Q1 Sales Summary PPT, 10 slides, data charts, formal business style` |\n  | A fun solar system PPT for elementary school kids, 6 pages | `Solar System explainer PPT for elementary school kids, fun and engaging style, 6 slides` |\n\n- **language** (required): Detect from the user's input language — if the user writes in Chinese pass `Chinese`; English → `English`; etc. Never default to a fixed value.\n- **--reference-file** (optional): Pass the path to the temp file written at the end of Step 2 (e.g. `/tmp/ppt_reference.md`). Omit if no search was performed.\n- **--files** (optional): Pas\n\nArchive v1.0.5: 14 files, 32365 bytes\n\nFiles: references/apikey-fetch.md (1791b), scripts/constant.py (81b), scripts/local_pptx_ops.py (13562b), scripts/parse_file.py (6798b), scripts/run_ppt_write.py (15459b), scripts/skywork_auth.py (284b), scripts/upload_files.py (4900b), scripts/web_search.py (2493b), SKILL.md (9964b), workflow_edit.md (4275b), workflow_generate.md (9584b), workflow_imitate.md (7946b), workflow_local.md (3981b), _meta.json (130b)\n\nArchive v1.0.4: 14 files, 32031 bytes\n\nFiles: references/apikey-fetch.md (1690b), scripts/constant.py (81b), scripts/local_pptx_ops.py (13562b), scripts/parse_file.py (6834b), scripts/run_ppt_write.py (15459b), scripts/skywork_auth.py (284b), scripts/upload_files.py (4898b), scripts/web_search.py (2493b), SKILL.md (9352b), workflow_edit.md (4275b), workflow_generate.md (9584b), workflow_imitate.md (7946b), workflow_local.md (3981b), _meta.json (130b)\n\nArchive v1.0.3: 13 files, 33713 bytes\n\nFiles: scripts/config.py (630b), scripts/local_pptx_ops.py (13562b), scripts/parse_file.py (6745b), scripts/run_ppt_write.py (15431b), scripts/skywork_auth.py (9872b), scripts/upload_files.py (4794b), scripts/web_search.py (2406b), SKILL.md (8906b), workflow_edit.md (4275b), workflow_generate.md (9584b), workflow_imitate.md (7946b), workflow_local.md (3981b), _meta.json (130b)\n\nArchive v1.0.2: 13 files, 33786 bytes\n\nFiles: scripts/config.py (630b), scripts/local_pptx_ops.py (13562b), scripts/parse_file.py (6745b), scripts/run_ppt_write.py (15431b), scripts/skywork_auth.py (9872b), scripts/upload_files.py (4794b), scripts/web_search.py (2406b), SKILL.md (9142b), workflow_edit.md (4240b), workflow_generate.md (9612b), workflow_imitate.md (7911b), workflow_local.md (3981b), _meta.json (130b)\n\nArchive v1.0.1: 13 files, 33684 bytes\n\nFiles: scripts/config.py (630b), scripts/local_pptx_ops.py (13562b), scripts/parse_file.py (6745b), scripts/run_ppt_write.py (15431b), scripts/skywork_auth.py (9872b), scripts/upload_files.py (4794b), scripts/web_search.py (2406b), SKILL.md (8858b), workflow_edit.md (4240b), workflow_generate.md (9612b), workflow_imitate.md (7911b), workflow_local.md (3981b), _meta.json (130b)\n\nArchive v1.0.0: 13 files, 33597 bytes\n\nFiles: scripts/config.py (630b), scripts/local_pptx_ops.py (13562b), scripts/parse_file.py (6745b), scripts/run_ppt_write.py (15333b), scripts/skywork_auth.py (9872b), scripts/upload_files.py (4794b), scripts/web_search.py (2333b), SKILL.md (8858b), workflow_edit.md (4240b), workflow_generate.md (9612b), workflow_imitate.md (7911b), workflow_local.md (3981b), _meta.json (130b)","readmeExcerpt":"Skill: Skywork PPT Owner: gxcun17 Summary: Skywork PPT (skywork) - Use when the user wants to work with PowerPoint presentations. Triggers: (1) Generate a new PPT from a topic — 'generate a PPT', 'cre... Tags: latest:1.0.9 Version history: v1.0.9 | 2026-04-23T12:59:48.398Z | user **Added support for converting NotebookLM-exported files to editable PPTX.** - New capability: Convert .pptx or .pdf exported from Notebook","codeSnippets":[],"executableExamples":[{"language":"bash","snippet":"PYTHON_CMD=\"\"\nfor cmd in python3 python python3.13 python3.12 python3.11 python3.10 python3.9 python3.8; do\n  if command -v \"$cmd\" &>/dev/null && \"$cmd\" -c \"import sys; exit(0 if sys.version_info >= (3,8) else 1)\" 2>/dev/null; then\n    PYTHON_CMD=\"$cmd\"\n    break\n  fi\ndone\n\nif [ -z \"$PYTHON_CMD\" ]; then\n  echo \"ERROR: Python 3.8+ not found.\"\n  echo \"Install on macOS: brew install python3  or visit https://www.python.org/downloads/\"\n  exit 1\nfi\n\necho \"Found Python: $PYTHON_CMD ($($PYTHON_CMD --version))\"\n\n$PYTHON_CMD -m pip install -q --break-system-packages python-pptx\necho \"Dependencies ready.\""},{"language":"bash","snippet":"$PYTHON_CMD scripts/run_ppt_write.py \"edit instruction\" \\\n     --language Chinese \\\n     --pptx-url \"https://cdn.example.com/file.pptx\" \\\n     -o /absolute/path/output.pptx"},{"language":"bash","snippet":"$PYTHON_CMD scripts/run_editable_convert.py \\\n     --file-url \"https://cdn.example.com/source.pptx\" \\\n     --file-type \"pptx\" \\\n     -o /absolute/path/output_editable.pptx"},{"language":"bash","snippet":"# Inspect slide count and titles\n$PYTHON_CMD scripts/local_pptx_ops.py info --file my.pptx\n\n# Delete slides (1-based index; supports ranges like 3,5,7-9; omit -o to overwrite in place)\n$PYTHON_CMD scripts/local_pptx_ops.py delete --file my.pptx --slides 3,5,7-9 -o trimmed.pptx\n\n# Reorder slides (must list every slide, no omissions)\n$PYTHON_CMD scripts/local_pptx_ops.py reorder --file my.pptx --order 2,1,4,3,5\n\n# Extract a subset of slides into a new file\n$PYTHON_CMD scripts/local_pptx_ops.py extract --file my.pptx --slides 1-3 -o subset.pptx\n\n# Merge multiple files\n$PYTHON_CMD scripts/local_pptx_ops.py merge --files a.pptx b.pptx -o merged.pptx"},{"language":"json","snippet":"{\n  \"skills\": {\n    \"entries\": {\n      \"Skywork-ppt\": {\n        \"enabled\": true,\n        \"apiKey\": \"your_actual_skywork_api_key_here\"\n      }\n    }\n  }\n}"},{"language":"bash","snippet":"export SKYWORK_API_KEY=\"your_actual_skywork_api_key_here\""}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: Skywork-ppt\ndescription: \"Skywork PPT (skywork) - Use when the user wants to work with PowerPoint presentations. Triggers: (1) Generate a new PPT from a topic — 'generate a PPT', 'create a presentation about X', 'make slides', '帮我做个PPT', '生成演示文稿', 'PPTを作って', 'スライドを作って', 'PPT 만들어줘', '슬라이드 만들어줘'; (2) Imitate an existing .pptx style/template — 'use this template', 'imitate this PPT/style', '用这个模板', '仿照这个PPT', 'このテンプレートを使って', '이 템플릿 써줘'; (3) Edit existing PPT via natural language — 'modify slide N', 'change background', 'add a slide', 'make it more beautiful', '修改第N页', '更换背景', '新增一页', '美化一下', 'N枚目を修正', '背景を変えて', 'きれいにして', 'N번 슬라이드 수정', '배경 바꿔줘'; (4) Convert NotebookLM-exported pptx/pdf into editable pptx — 'make this notebooklm ppt editable', 'convert notebooklm export to editable pptx', '把这个notebooklm导出的pptx改成可编辑pptx', '把这个pdf转成可编辑pptx'; (5) Local .pptx file ops — 'delete slide N', 'reorder slides', 'merge pptx', 'extract slides', 'how many slides', '删除第N页', '调整顺序', '合并PPT', '提取幻灯片', 'スライドを削除/並べ替え/結合/抽出', '슬라이드 삭제/순서 변경/합치기/추출'.\"\nmetadata:\n  openclaw:\n    requires:\n      bins:\n        - python3\n      env:\n        - SKYWORK_API_KEY\n    primaryEnv: SKYWORK_API_KEY\n---\n\n# PPT Write Skill\n\nFive capabilities: **generate**, **template imitation**, **edit existing PPT**, **convert NotebookLM export to editable PPTX**, and **local file operations**.\n\n---\n\n## Prerequisites\n\n### API Key Configuration (Required First)\nThis skill requires a **SKYWORK_API_KEY** to be configured before use.\n\nIf you don't have an API key yet, please visit:\n**https://skywork.ai**\n\nFor detailed setup instructions, see:\n[references/apikey-fetch.md](references/apikey-fetch.md)\n\n---\n\n## Privacy & Remote Calls (Read Before Use)\n\n- **Remote upload & processing**: Layers 1/2/4/5 upload local files and send the full, verbatim user query to the Skywork service. Avoid sensitive or confidential content unless you trust the remote service and its data handling policies.\n- **Polling behavior**: The generation/edit workflows include periodic status polling (about every 5 seconds) while waiting for backend jobs. This is expected.\n\n---\n\n## Routing — Identify the user's intent first\n\n| User intent | Which path |\n|-------------|------------|\n| Generate a new PPT from a topic, set of requirements or reference files | **Layer 1** — Generate |\n| Use an existing .pptx as a layout/style template to create a new presentation | **Layer 2** — Imitate |\n| Edit an existing PPT: modify slides, add slides, change style, split/merge | **Layer 4** — Edit |\n| Convert a NotebookLM-exported `.pptx` or `.pdf` into an editable `.pptx` | **Layer 5** — Convert to editable PPTX |\n| Delete / reorder / extract / merge slides in a local file (no backend) | **Layer 3** — Local ops |\n\n---\n\n## Environment check (always run this first)\n\n**This skill requires Python 3 (>=3.8). Run the following before any script to locate a valid Python binary and install dependencies.**\n\n```bash\nPYTHON_CMD=\"\"\nfor cmd in python3 python"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn70ct0m3p4538a9t49cjcwern82ky02\",\n  \"slug\": \"skywork-ppt\",\n  \"version\": \"1.0.9\",\n  \"publishedAt\": 1776949188398\n}"},{"path":"references/apikey-fetch.md","content":"# Skywork API Key Setup Guide\n\n## SKYWORK_API_KEY Not Configured\n\nWhen the `SKYWORK_API_KEY` environment variable is not set, follow these steps:\n\n### 1. Get API Key\n\nVisit the Skywork website and sign in to your account:\n\n**https://skywork.ai**\n\n- Log in with your Skywork account\n- Open account / Settings / API Key (**https://skywork.ai/?openApiKeySetting=1**)\n- Create or copy your **API key**\n\nIf your organization uses a separate console or test environment, use the URL and credentials your team provides.\n\n### 2. Configure OpenClaw\n\nEdit the OpenClaw configuration file: `~/.openclaw/openclaw.json`\n\nIn current OpenClaw, Skywork skills store the key under `skills.entries.<Skill Name>.apiKey` (not under `env`).\nOpenClaw will inject this value into the skill's `SKYWORK_API_KEY` environment when `primaryEnv` matches.\nAdd or merge the following structure (adjust the skill name to match the installed skill):\n\n```json\n{\n  \"skills\": {\n    \"entries\": {\n      \"Skywork-ppt\": {\n        \"enabled\": true,\n        \"apiKey\": \"your_actual_skywork_api_key_here\"\n      }\n    }\n  }\n}\n```\n\nReplace `\"your_actual_skywork_api_key_here\"` with your real key.\n\nFor multiple Skywork skills, repeat the same `apiKey` field on each skill entry.\n\n### 3. Configure Claude Code\n\nIf you are using Claude Code, use one of these lightweight options:\n\n**Option A — shell environment**\n\nExport the API key before running the skill:\n\n```bash\nexport SKYWORK_API_KEY=\"your_actual_skywork_api_key_here\"\n```\n\nTo persist it across sessions, add the same line to `~/.zshrc` or `~/.bashrc`, then reload the shell.\n\n**Option B — Claude Code settings**\n\nAdd the variable to `~/.claude/settings.json`:\n\n```json\n{\n  \"env\": {\n    \"SKYWORK_API_KEY\": \"your_actual_skywork_api_key_here\"\n  }\n}\n```\n\nUse the method that best matches how you run Claude Code.\n\n### 4. Verify Configuration\n\n```bash\n# Check that the environment variable is available\necho \"$SKYWORK_API_KEY\"\n```\n\nFor OpenClaw, you can also validate the config file:\n\n```bash\ncat ~/.openclaw/openclaw.json | python3 -m json.tool\n```\n\n### 5. Restart OpenClaw\n\n```bash\nopenclaw gateway restart\n```\n\n## Troubleshooting\n\n- Ensure `~/.openclaw/openclaw.json` exists and is valid JSON\n- Ensure `SKYWORK_API_KEY` is available in Claude Code through your shell or `~/.claude/settings.json`\n- Confirm the API key is active and not expired\n- Check Skywork account status, membership, or quota if requests fail with auth or benefit errors\n- Restart OpenClaw after configuration changes\n\n**Recommended**: Use the setup method that matches your runtime. OpenClaw should use the OpenClaw config file; Claude Code can use either the shell environment or `~/.claude/settings.json`."},{"path":"skill-card.md","content":"## Description:\n\nSkywork PPT helps agents generate new PowerPoint presentations, imitate an existing presentation style, edit decks through natural-language requests, convert NotebookLM exports to editable PPTX files, and run local PPTX operations.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[gxcun17](https://clawhub.ai/user/gxcun17)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers and external users use this skill to create, transform, and inspect PowerPoint presentations from topics, templates, existing decks, NotebookLM exports, and local PPTX files.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Skywork-backed workflows may send selected prompts and files to Skywork or cloud storage.\n\nMitigation: Use only with content approved for that service, and avoid confidential decks unless organizational policy permits it.\n\nRisk: The skill requires a Skywork API key for remote workflows.\n\nMitigation: Store the key in a protected secret store, use a revocable key, and avoid printing it in logs.\n\nRisk: Local slide-editing operations can modify presentation files.\n\nMitigation: Use explicit output paths or keep backups before running operations that may overwrite local decks.\n\nRisk: The security verdict is suspicious because the skill uploads local documents and can modify files without strong safeguards.\n\nMitigation: Review the skill before deployment and run dependencies in a virtual environment.\n\n## Reference(s):\n\n- [Skywork API key setup](references/apikey-fetch.md)\n- [Skywork AI](https://skywork.ai)\n- [ClawHub skill page](https://clawhub.ai/gxcun17/skills/skywork-ppt)\n\n## Skill Output:\n\n**Output Type(s):** [text, markdown, code, shell commands, configuration, files, guidance]\n\n**Output Format:** [Markdown guidance with shell commands and generated or modified PPTX files]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Requires Python 3 and SKYWORK_API_KEY for Skywork-backed workflows; local PPTX operations use python-pptx.]\n\n## Skill Version(s):\n\n1.0.9 (source: server release evidence)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment."},{"path":"workflow_convert_editable.md","content":"# Convert NotebookLM Export to Editable PPTX Workflow\n\nUse this workflow when the user provides a local `.pptx` or `.pdf` file and wants to convert a NotebookLM-exported deck into an editable `.pptx`.\n\nFollow these steps in order: identify the source file → upload it → run the conversion script in background → **read the log every 5 seconds and report progress** → deliver.\n\n---\n\n## 1. Confirm the source file\n\nThe user must provide a local `.pptx` or `.pdf` file.\n\n- If the file path is ambiguous, ask the user for the full absolute path.\n- If the file extension is not `.pptx` or `.pdf`, stop and explain that this workflow only supports those two input types.\n\n---\n\n## 2. Upload the source file to OSS\n\n```bash\n$PYTHON_CMD scripts/upload_files.py \"/absolute/path/to/source.pptx\"\n```\n\nor\n\n```bash\n$PYTHON_CMD scripts/upload_files.py \"/absolute/path/to/source.pdf\"\n```\n\n- Extract the OSS URL from the `[OK] ... -> https://...` output line.\n- Call this value `SOURCE_URL`.\n\n---\n\n## 3. Run the conversion script\n\nRun in the **background**, then read the progress log file every 5 seconds until done.\n\n### 3a. Choose a log path and start in background\n\n```bash\nPPT_LOG=/tmp/ppt_editable_$(date +%s).log\n\n$PYTHON_CMD scripts/run_editable_convert.py \\\n  --file-url \"SOURCE_URL\" \\\n  --file-type \"pptx\" \\\n  --log_path \"$PPT_LOG\" \\\n  -o /absolute/path/to/output_editable.pptx \\\n  > /dev/null 2>&1 &\n\necho \"Log: $PPT_LOG\"\n```\n\nor for pdf:\n\n```bash\n$PYTHON_CMD scripts/run_editable_convert.py \\\n  --file-url \"SOURCE_URL\" \\\n  --file-type \"pdf\" \\\n  --log_path \"$PPT_LOG\" \\\n  -o /absolute/path/to/output_editable.pptx \\\n  > /dev/null 2>&1 &\n```\n\n- **`--file-url`** (required): OSS URL of the uploaded source file.\n- **`--file-type`** (recommended): explicitly pass `pptx` or `pdf`.\n- **`--log_path`** (required): pass the pre-chosen path.\n- **`-o`** (required): absolute output path for the converted `.pptx`.\n\n### 3b. Monitor progress （REQUIRED）\n\n> **STRICT RULES — no exceptions:**\n> 1. **Read the log exactly every 5 seconds.** Do NOT extend the interval, do NOT skip reads.\n> 2. **Before every read, check if the process is still alive.** If alive → only read log, NEVER restart.\n\n**Every 5 seconds, run this exact sequence:**\n\n```bash\n# Step 1: extract PID from log\nPPT_PID=$(grep '^\\[PID\\]' \"$PPT_LOG\" | tail -1 | awk '{print $2}')\n# Step 2: check if process is alive\nkill -0 \"$PPT_PID\" 2>/dev/null && PPT_ALIVE=true || PPT_ALIVE=false\n# Step 3: read the log regardless\ntail -20 \"$PPT_LOG\"\n```\n\n- If process is **RUNNING** → report status to user, wait 5s, repeat. Do NOT touch the script.\n- If process is **not running** AND log ends with `[DONE]` or `[ERROR]` → stop polling, proceed to deliver/handle error.\n- If process is **not running** AND no `[DONE]`/`[ERROR]` in log → the script crashed; report error to user, ask whether to retry.\n\nEach line is plain text:\n- `[PID] <pid>` — process ID written at startup\n- `[START]` — job started\n- `[PHASE] <message>` — in progress\n- `[PROGRESS] <message>` —"}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":null,"editorialQuality":{"score":100,"threshold":65,"status":"thin","wordCount":1343,"uniquenessScore":42,"reasons":["uniqueness-below-45"]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-09T03:14:26.946Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-09T03:14:26.946Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-09T14:24:31.848Z","emptyReason":null},"items":[{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-10T18:48:31.762Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}