{"id":"d9f4d564-44ae-49c6-ad96-98e84f4c84be","shortId":"2TZjsX","kind":"skill","title":"sn-ppt-creative","tagline":"Creative-mode PPT pipeline. One full-page 16:9 PNG per slide.\nLLM / VLM calls go through sn-ppt-standard/lib/model_client.py (shared thin client).\nText-to-image (the actual png rendering) goes through sn-image-base/scripts/sn_agent_runner.py.\nExpects task_pack.json + info_pack.js","description":"# sn-ppt-creative\n\n## Call-routing policy\n\n| Kind | Backend |\n|---|---|\n| LLM (text) | `$PPT_STANDARD_DIR/lib/model_client.py` → `llm(sys, user)` |\n| VLM (image understanding) | `$PPT_STANDARD_DIR/lib/model_client.py` → `vlm(sys, user, images)` |\n| T2I (image generation) | `$SN_IMAGE_BASE/scripts/sn_agent_runner.py sn-image-generate` |\n\nNever mix — LLM / VLM through sn-image-base, or T2I through model_client — both violate policy.\n\n## Preconditions\n\n- `<deck_dir>/task_pack.json` exists and `ppt_mode == \"creative\"`\n- `<deck_dir>/info_pack.json` exists\n- `<deck_dir>/pages/` exists\n- `$SN_IMAGE_BASE` env var (OpenClaw-injected) points at the sn-image-base skill root\n- `$PPT_STANDARD_DIR` env var points at the sn-ppt-standard skill root (so we can import `model_client`)\n\nAny missing → stop and tell user to enter via `/skill sn-ppt-entry`.\n\n## Resume\n\n```bash\npython3 $SKILL_DIR/scripts/resume_scan.py --deck-dir <deck_dir>\n# => {\"style_spec_done\": bool, \"outline_done\": bool, \"pptx_done\": bool,\n#     \"pages\": [{\"page_no\": 1, \"action\": \"skip|render_only|full\"}, ...]}\n```\n\nDispatch:\n\n| Manifest | Do |\n|---|---|\n| `style_spec_done == false` | Run Stage 2 |\n| `outline_done == false` | Run Stage 3 |\n| per-page `action == \"full\"` | Run Stage 4.1 + 4.2 |\n| per-page `action == \"render_only\"` | Run Stage 4.2 only (prompt.txt already on disk) |\n| per-page `action == \"skip\"` | Skip |\n| `pptx_done == false` (all pages done or failed) | Run Stage 5 |\n\n## Stage 2 — style_spec.md  (LLM or VLM via model_client)\n\nOne independent exec tool_call. Two branches based on reference images.\n\n**Branch A (no ref images, or all missing on disk)** — use `model_client.llm`:\n\n```bash\npython3 -c \"\nimport sys, pathlib, json\nsys.path.insert(0, '$PPT_STANDARD_DIR/lib')\nfrom model_client import llm\n\ndeck = pathlib.Path('<deck_dir>')\ntp = json.loads((deck / 'task_pack.json').read_text())\nip = json.loads((deck / 'info_pack.json').read_text())\n\nsys_prompt = open('$SKILL_DIR/prompts/style_from_query.md').read()\nuser_prompt = json.dumps({\n    'params': tp['params'],\n    'query': ip.get('user_query'),\n    'digest': ip.get('document_digest'),\n}, ensure_ascii=False)\n\nmd = llm(sys_prompt, user_prompt)\n(deck / 'style_spec.md').write_text(md, encoding='utf-8')\nprint('style_spec.md ok')\n\"\n```\n\n**Branch B (≥1 reference image on disk)** — use `model_client.vlm`:\n\n```bash\npython3 -c \"\nimport sys, pathlib, json\nsys.path.insert(0, '$PPT_STANDARD_DIR/lib')\nfrom model_client import vlm\n\ndeck = pathlib.Path('<deck_dir>')\nip = json.loads((deck / 'info_pack.json').read_text())\ntp = json.loads((deck / 'task_pack.json').read_text())\n\nrefs = [p for p in (ip.get('user_assets') or {}).get('reference_images', []) if pathlib.Path(p).exists()]\n\nsys_prompt = open('$SKILL_DIR/prompts/style_from_image.md').read()\nuser_prompt = f'PPT 主题/参数: {json.dumps(tp[\\\"params\\\"], ensure_ascii=False)}\\nuser_query: {ip.get(\\\"user_query\\\") or \\\"\\\"}'\n\nmd = vlm(sys_prompt, user_prompt, images=refs)\n(deck / 'style_spec.md').write_text(md, encoding='utf-8')\nprint(f'style_spec.md ok (from {len(refs)} ref images)')\n\"\n```\n\nIf `user_assets.reference_images` is non-empty but **all** paths missing on disk: fall through to Branch A and prepend a line `reference_images_missing: <original paths>` at the top of style_spec.md.\n\n## Stage 3 — outline.json  (LLM via model_client)\n\n```bash\npython3 -c \"\nimport sys, pathlib, json\nsys.path.insert(0, '$PPT_STANDARD_DIR/lib')\nfrom model_client import llm\n\ndeck = pathlib.Path('<deck_dir>')\ntp = json.loads((deck / 'task_pack.json').read_text())\nip = json.loads((deck / 'info_pack.json').read_text())\nstyle = (deck / 'style_spec.md').read_text()\n\nsys_prompt = open('$SKILL_DIR/prompts/outline.md').read()\nuser_prompt = json.dumps({\n    'style_spec_markdown': style,\n    'params': tp['params'],\n    'query': ip.get('user_query'),\n    'digest': ip.get('document_digest'),\n}, ensure_ascii=False)\n\nraw = llm(sys_prompt, user_prompt).strip()\nif raw.startswith('\\`\\`\\`'):\n    raw = raw.split('\\n', 1)[1].rsplit('\\`\\`\\`', 1)[0]\ndata = json.loads(raw)\nassert len(data['pages']) == tp['params']['page_count'], 'page_count mismatch'\n(deck / 'outline.json').write_text(json.dumps(data, ensure_ascii=False, indent=2))\nprint(f'outline ok, {len(data[\\\"pages\\\"])} pages')\n\"\n```\n\nOn failure (non-JSON / length mismatch): **abort**.\n\n## Stage 4 — per-page: one independent exec per page\n\n### 4.1 Compose prompt  (LLM via model_client) — skip if `action == \"render_only\"`\n\n```bash\npython3 -c \"\nimport sys, pathlib, json\nsys.path.insert(0, '$PPT_STANDARD_DIR/lib')\nfrom model_client import llm\n\ndeck = pathlib.Path('<deck_dir>')\nN = <NNN>\nstyle = (deck / 'style_spec.md').read_text()\noutline = json.loads((deck / 'outline.json').read_text())\npage = next(p for p in outline['pages'] if int(p['page_no']) == N)\n\nsys_prompt = open('$SKILL_DIR/prompts/page_prompt.md').read()\nuser_prompt = json.dumps({'style_spec_markdown': style, 'page': page}, ensure_ascii=False)\n\ntxt = llm(sys_prompt, user_prompt)\n(deck / 'pages' / f'page_{N:03d}.prompt.txt').write_text(txt, encoding='utf-8')\nprint(f'prompt page {N} ok')\n\"\n\n# sanitize the written prompt in-place: strip hex/rgb/hsl/CSS/px/em/rem etc\n# to prevent T2I server-side prompt-enhance from baking them into the image.\n# Silent: no chat-facing notification; removals go to stderr only.\npython3 $SKILL_DIR/scripts/sanitize_prompt.py --path <deck_dir>/pages/page_<NNN>.prompt.txt\n```\n\n### 4.2 Generate image  (T2I via sn-image-base)\n\n`--negative-prompt` 是针对可能带自身 prompt-enhance 的 T2I 后端的最后一道防线：\n即使前面的 sanitize 没拦住、或后端重写时引入了新的样式元数据，也通过反向约束压制模型把它们画出来。这段字符串在所有页上都一致。\n\n```bash\npython $SN_IMAGE_BASE/scripts/sn_agent_runner.py sn-image-generate \\\n  --prompt \"$(cat <deck_dir>/pages/page_<NNN>.prompt.txt)\" \\\n  --negative-prompt \"hex color code, #RRGGBB, rgb(), rgba(), hsl(), hsla(), css, json, yaml, code snippet, pixel values, px, em, rem, pt, color palette text, typography label, design spec, style guide, font stack, hex code, layout annotation, dimensional callout, figma-style spec sheet, wireframe annotation, swatch with numbers\" \\\n  --aspect-ratio 16:9 \\\n  --image-size 2k \\\n  --save-path <deck_dir>/pages/page_<NNN>.png \\\n  --output-format json\n```\n\n### 4.3 Failure handling\n\n- 4.1 failure (model timeout / empty / malformed): record `page_no` into `failed_pages`, echo failure line, continue.\n- 4.2 failure: same — record, echo, continue.\n- **No retries.** **No placeholder PNG.** Don't write 1x1 transparent PNGs to fake success.\n- `.prompt.txt` may remain on disk for a later manual re-run of 4.2 only.\n\n## Stage 5 — pptx 打包（一次独立 exec）\n\n所有页图生成后（含部分失败的情况），把 `pages/page_*.png` 平铺打包成 16:9 整册 PPTX，每张图满版一页。由 `scripts/build_pptx.py` 完成，模型只负责执行脚本。\n\n```bash\npython3 $SKILL_DIR/scripts/build_pptx.py --deck-dir <deck_dir>\n# => {\"deck_id\": \"...\", \"output\": \"<deck_dir>/<deck_id>.pptx\",\n#     \"total_slides\": N, \"included_pages\": [...], \"missing_pages\": [...]}\n```\n\n行为约定：\n\n- 输出路径默认 `<deck_dir>/<deck_id>.pptx`；可用 `--output` 覆盖。\n- 页序按 `outline.json` 的 `page_no` 排；缺失 `outline.json` 时按 `page_001..page_NNN` 走。\n- 缺失的 PNG 会插入空白页并在 stderr 记录一行，**不中止**；这样跟 Stage 4 的\"失败跳过\"语义一致。\n- 脚本失败（依赖缺失 / 写盘失败）：echo 失败原因，**不中止整个 skill**，仍进入 Stage 6 收尾；PNG 已在磁盘上。\n\n依赖：`python-pptx`（与 `sn-ppt-standard` 共用的打包思路；若运行环境未装，由 `sn-ppt-doctor` 的 env check 提示安装）。\n\n## Stage 6 — closing\n\nEmit:\n\n```\n创意模式已完成。\n\n📁 输出目录：<deck_dir>\n📄 结果文件：\n  - style_spec.md\n  - outline.json\n  - pages/page_001.png ~ page_NNN.png（失败 M 页：page_..., page_...）\n  - <deck_id>.pptx（整册，缺失页插入空白）\n\n⚠️ 未完成：\n  - page_007：生图返回超时，已跳过（pptx 中为空白页）\n\n下一步：\n  - 可直接打开 <deck_id>.pptx 查看整册\n  - 或在 pages/ 目录查看 PNG\n```\n\n## Progress echo — MANDATORY\n\n| Stage | Example |\n|---|---|\n| After resume_scan | `已进入 sn-ppt-creative，共 N 页` |\n| After Stage 2 | `[1] style_spec.md ✓` |\n| After Stage 3 | `[2] outline.json ✓（N 页）` |\n| Per page-prompt (4.1) | `[prompt 3/10] ✓` |\n| Per page-image (4.2) | `[图 3/10] page_003.png ✓` or `[图 3/10] ✗ 超时` |\n| After Stage 5 | `[pptx] <deck_id>.pptx ✓（N 页，缺失 M 页）` or `[pptx] ✗ <reason>` |\n| Closing | full summary above |\n\n- Each echo is a chat reply, not a log write.\n- Per-page echo is the heartbeat for Stage 4.\n- On failure, echo failure line with reason before moving on.\n\n## 🚫 Hard rules\n\n1. **Do NOT loop inside a single exec.** One page = one tool_call.\n2. **Do NOT fake images.** Failed T2I → record failed, move on. No 1x1 placeholder PNGs.\n3. **Do NOT use `model_client.t2i`** — T2I must go through `sn-image-base`. `model_client` handles only LLM / VLM.\n4. **Do NOT use `sn-text-optimize` or `sn-image-recognize`** from sn-image-base — those must go through `model_client.llm` / `model_client.vlm`.\n5. **Do NOT retry on first failure.**\n6. **Do NOT generate editable JSON from PNG** (out of scope).","tags":["ppt","creative","sensenova","skills","opensensenova","agent","agent-skills","ai-agents","ai-assistant","data-analysis","document-processing","office-automation"],"capabilities":["skill","source-opensensenova","skill-sn-ppt-creative","topic-agent","topic-agent-skills","topic-ai-agents","topic-ai-assistant","topic-data-analysis","topic-document-processing","topic-office-automation","topic-presentation-slides"],"categories":["SenseNova-Skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/OpenSenseNova/SenseNova-Skills/sn-ppt-creative","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add OpenSenseNova/SenseNova-Skills","source_repo":"https://github.com/OpenSenseNova/SenseNova-Skills","install_from":"skills.sh"}},"qualityScore":"0.700","qualityRationale":"deterministic score 0.70 from registry signals: · indexed on github topic:agent-skills · 1627 github stars · SKILL.md body (8,691 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-18T18:53:05.372Z","embedding":null,"createdAt":"2026-05-15T06:53:10.480Z","updatedAt":"2026-05-18T18:53:05.372Z","lastSeenAt":"2026-05-18T18:53:05.372Z","tsv":"'-8':349,448,719 '/info_pack.json':112 '/lib/model_client.py':28 '/pages':114 '/pages/page_':766,804,867 '/scripts/sn_agent_runner.py':46 '/skill':162 '/task_pack.json':106 '0':290,370,503,574,646 '001':982 '007':1052 '03d':712 '1':188,355,570,571,573,1084,1160 '16':14,858,939 '1x1':906,1185 '2':203,251,599,1083,1089,1173 '2k':863 '3':209,489,1088,1188 '3/10':1099,1106,1110 '4':617,994,1147,1208 '4.1':217,626,876,1097 '4.2':218,227,768,892,925,1104 '4.3':873 '5':249,928,1114,1232 '6':1007,1032,1239 '9':15,859,940 'abort':615 'action':189,213,222,236,635 'actual':37 'alreadi':230 'annot':842,851 'ascii':334,425,556,596,699 'aspect':856 'aspect-ratio':855 'assert':578 'asset':400 'b':354 'backend':59 'bake':746 'base':45,96,118,130,266,776,1201,1225 'base/scripts/sn_agent_runner.py':83,797 'bash':168,282,362,495,638,793,948 'bool':178,181,184 'branch':265,270,353,474 'c':284,364,497,640 'call':21,55,263,1172 'call-rout':54 'callout':844 'cat':803 'chat':754,1132 'chat-fac':753 'check':1029 'client':31,101,152,258,296,376,494,509,632,652,1203 'client.t2i':1193 'close':1033,1124 'code':811,820,840 'color':810,828 'compos':627 'continu':891,897 'count':585,587 'creativ':4,6,53,111,1077 'creative-mod':5 'css':817 'data':575,580,594,605 'deck':173,299,303,309,342,379,383,389,441,512,516,522,527,589,655,659,665,707,953,955 'deck-dir':172,952 'design':833 'digest':329,332,551,554 'dimension':843 'dir':135,174,954 'dir/lib':293,373,506,649 'dir/lib/model_client.py':64,73 'dir/prompts/outline.md':535 'dir/prompts/page_prompt.md':687 'dir/prompts/style_from_image.md':413 'dir/prompts/style_from_query.md':317 'dir/scripts/build_pptx.py':951 'dir/scripts/resume_scan.py':171 'dir/scripts/sanitize_prompt.py':764 'disk':232,279,359,470,916 'dispatch':194 'doctor':1026 'document':331,553 'done':177,180,183,199,205,240,244 'echo':888,896,1001,1066,1129,1141,1150 'edit':1243 'em':825 'emit':1034 'empti':464,880 'encod':347,446,717 'enhanc':744,783 'ensur':333,424,555,595,698 'enter':160 'entri':166 'env':119,136,1028 'etc':735 'exampl':1069 'exec':261,623,932,1167 'exist':107,113,115,408 'expect':47 'f':417,450,601,709,721 'face':755 'fail':246,886,1178,1181 'failur':609,874,877,889,893,1149,1151,1238 'fake':910,1176 'fall':471 'fals':200,206,241,335,426,557,597,700 'figma':846 'figma-styl':845 'first':1237 'font':837 'format':871 'full':12,193,214,1125 'full-pag':11 'generat':80,87,769,801,1242 'get':402 'go':22,758,1196,1228 'goe':40 'guid':836 'handl':875,1204 'hard':1158 'heartbeat':1144 'hex':809,839 'hex/rgb/hsl/css/px/em/rem':734 'hsl':815 'hsla':816 'id':956 'imag':35,44,69,77,79,82,86,95,117,129,269,274,357,404,439,457,460,481,750,770,775,796,800,861,1103,1177,1200,1219,1224 'image-s':860 'import':150,285,297,365,377,498,510,641,653 'in-plac':730 'includ':962 'indent':598 'independ':260,622 'info_pack.js':49 'info_pack.json':310,384,523 'inject':123 'insid':1164 'int':678 'ip':307,381,520 'ip.get':326,330,398,429,548,552 'json':288,368,501,612,644,818,872,1244 'json.dumps':321,421,539,593,691 'json.loads':302,308,382,388,515,521,576,664 'kind':58 'label':832 'later':919 'layout':841 'len':454,579,604 'length':613 'line':479,890,1152 'llm':19,60,65,90,253,298,337,491,511,559,629,654,702,1206 'log':1136 'loop':1163 'm':1043,1120 'malform':881 'mandatori':1067 'manifest':195 'manual':920 'markdown':542,694 'may':913 'md':336,346,433,445 'mismatch':588,614 'miss':154,277,468,482,964 'mix':89 'mode':7,110 'model':100,151,257,295,375,493,508,631,651,878,1192,1202 'model_client.llm':281,1230 'model_client.vlm':361,1231 'move':1156,1182 'must':1195,1227 'n':569,657,682,711,724,961,1079,1091,1117 'negat':778,807 'negative-prompt':777,806 'never':88 'next':670 'nnn':984 'non':463,611 'non-empti':462 'non-json':610 'notif':756 'number':854 'nuser':427 'ok':352,452,603,725 'one':10,259,621,1168,1170 'open':315,411,533,685 'openclaw':122 'openclaw-inject':121 'optim':1215 'outlin':179,204,602,663,675 'outline.json':490,590,666,973,979,1039,1090 'output':870,957,970 'output-format':869 'p':394,396,407,671,673,679 'page':13,185,186,212,221,235,243,581,584,586,606,607,620,625,669,676,680,696,697,708,710,723,883,887,963,965,975,981,983,1045,1046,1051,1062,1095,1102,1140,1169 'page-imag':1101 'page-prompt':1094 'page_003.png':1107 'page_nnn.png':1041 'pages/page_':936 'pages/page_001.png':1040 'palett':829 'param':322,324,423,544,546,583 'path':467,765,866 'pathlib':287,367,500,643 'pathlib.path':300,380,406,513,656 'per':17,211,220,234,619,624,1093,1100,1139 'per-pag':210,219,233,618,1138 'pipelin':9 'pixel':822 'place':732 'placehold':901,1186 'png':16,38,868,902,937,987,1009,1064,1246 'pngs':908,1187 'point':124,138 'polici':57,104 'ppt':3,8,26,52,62,71,109,133,143,165,291,371,418,504,647,1018,1025,1076 'pptx':182,239,929,942,958,968,1014,1047,1055,1059,1115,1116,1123 'precondit':105 'prepend':477 'prevent':737 'print':350,449,600,720 'progress':1065 'prompt':314,320,339,341,410,416,436,438,532,538,561,563,628,684,690,704,706,722,729,743,779,782,802,808,1096,1098 'prompt-enh':742,781 'prompt.txt':229,713,767,805,912 'pt':827 'px':824 'python':794,1013 'python-pptx':1012 'python3':169,283,363,496,639,762,949 'queri':325,328,428,431,547,550 'ratio':857 'raw':558,567,577 'raw.split':568 'raw.startswith':566 're':922 're-run':921 'read':305,311,318,385,391,414,518,524,529,536,661,667,688 'reason':1154 'recogn':1220 'record':882,895,1180 'ref':273,393,440,455,456 'refer':268,356,403,480 'rem':826 'remain':914 'remov':757 'render':39,191,223,636 'repli':1133 'resum':167,1071 'retri':899,1235 'rgb':813 'rgba':814 'root':132,146 'rout':56 'rrggbb':812 'rsplit':572 'rule':1159 'run':201,207,215,225,247,923 'sanit':726,788 'save':865 'save-path':864 'scan':1072 'scope':1249 'scripts/build_pptx.py':945 'server':740 'server-sid':739 'share':29 'sheet':849 'side':741 'silent':751 'singl':1166 'size':862 'skill':131,145,170,316,412,534,686,763,950,1004 'skill-sn-ppt-creative' 'skip':190,237,238,633 'slide':18,960 'sn':2,25,43,51,81,85,94,116,128,142,164,774,795,799,1017,1024,1075,1199,1213,1218,1223 'sn-image-bas':42,93,127,773,1198,1222 'sn-image-gener':84,798 'sn-image-recogn':1217 'sn-ppt-creativ':1,50,1074 'sn-ppt-doctor':1023 'sn-ppt-entri':163 'sn-ppt-standard':24,141,1016 'sn-text-optim':1212 'snippet':821 'source-opensensenova' 'spec':176,198,541,693,834,848 'stack':838 'stage':202,208,216,226,248,250,488,616,927,993,1006,1031,1068,1082,1087,1113,1146 'standard':27,63,72,134,144,292,372,505,648,1019 'stderr':760,989 'stop':155 'strip':564,733 'style':175,197,526,540,543,658,692,695,835,847 'style_spec.md':252,343,351,442,451,487,528,660,1038,1085 'success':911 'summari':1126 'swatch':852 'sys':66,75,286,313,338,366,409,435,499,531,560,642,683,703 'sys.path.insert':289,369,502,645 't2i':78,98,738,771,785,1179,1194 'task_pack.json':48,304,390,517 'tell':157 'text':33,61,306,312,345,386,392,444,519,525,530,592,662,668,715,830,1214 'text-to-imag':32 'thin':30 'timeout':879 'tool':262,1171 'top':485 'topic-agent' 'topic-agent-skills' 'topic-ai-agents' 'topic-ai-assistant' 'topic-data-analysis' 'topic-document-processing' 'topic-office-automation' 'topic-presentation-slides' 'total':959 'tp':301,323,387,422,514,545,582 'transpar':907 'two':264 'txt':701,716 'typographi':831 'understand':70 'use':280,360,1191,1211 'user':67,76,158,319,327,340,399,415,430,437,537,549,562,689,705 'user_assets.reference':459 'utf':348,447,718 'valu':823 'var':120,137 'via':161,256,492,630,772 'violat':103 'vlm':20,68,74,91,255,378,434,1207 'wirefram':850 'write':344,443,591,714,905,1137 'written':728 'yaml':819 '一次独立':931 '下一步':1057 '不中止':991 '不中止整个':1003 '与':1015 '中为空白页':1056 '主题':419 '也通过反向约束压制模型把它们画出来':791 '仍进入':1005 '会插入空白页并在':988 '依赖':1011 '依赖缺失':999 '共':1078 '共用的打包思路':1020 '写盘失败':1000 '创意模式已完成':1035 '即使前面的':787 '参数':420 '可用':969 '可直接打开':1058 '后端的最后一道防线':786 '含部分失败的情况':934 '图':1105,1109 '失败':1042 '失败原因':1002 '失败跳过':996 '完成':946 '已在磁盘上':1010 '已跳过':1054 '已进入':1073 '平铺打包成':938 '或后端重写时引入了新的样式元数据':790 '或在':1061 '所有页图生成后':933 '打包':930 '把':935 '排':977 '提示安装':1030 '收尾':1008 '整册':941,1048 '时按':980 '是针对可能带自身':780 '未完成':1050 '查看整册':1060 '模型只负责执行脚本':947 '每张图满版一页':943 '没拦住':789 '生图返回超时':1053 '由':944,1022 '的':784,974,995,1027 '目录查看':1063 '结果文件':1037 '缺失':978,1119 '缺失的':986 '缺失页插入空白':1049 '脚本失败':998 '若运行环境未装':1021 '行为约定':966 '覆盖':971 '记录一行':990 '语义一致':997 '走':985 '超时':1111 '输出目录':1036 '输出路径默认':967 '这样跟':992 '这段字符串在所有页上都一致':792 '页':1044,1080,1092,1118,1121 '页序按':972","prices":[{"id":"7dd41e4e-d1c5-4aa4-8dde-c1a014afdb5e","listingId":"d9f4d564-44ae-49c6-ad96-98e84f4c84be","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"OpenSenseNova","category":"SenseNova-Skills","install_from":"skills.sh"},"createdAt":"2026-05-15T06:53:10.480Z"}],"sources":[{"listingId":"d9f4d564-44ae-49c6-ad96-98e84f4c84be","source":"github","sourceId":"OpenSenseNova/SenseNova-Skills/sn-ppt-creative","sourceUrl":"https://github.com/OpenSenseNova/SenseNova-Skills/tree/main/skills/sn-ppt-creative","isPrimary":false,"firstSeenAt":"2026-05-15T06:53:10.480Z","lastSeenAt":"2026-05-18T18:53:05.372Z"}],"details":{"listingId":"d9f4d564-44ae-49c6-ad96-98e84f4c84be","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"OpenSenseNova","slug":"sn-ppt-creative","github":{"repo":"OpenSenseNova/SenseNova-Skills","stars":1627,"topics":["agent","agent-skills","ai-agents","ai-assistant","data-analysis","document-processing","office-automation","presentation-slides"],"license":"mit","html_url":"https://github.com/OpenSenseNova/SenseNova-Skills","pushed_at":"2026-05-15T04:43:37Z","description":"Modular SenseNova skills for building AI-powered office assistants and productivity workflows","skill_md_sha":"c5f86654a85348f2c8547b5723f758509465e07d","skill_md_path":"skills/sn-ppt-creative/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/OpenSenseNova/SenseNova-Skills/tree/main/skills/sn-ppt-creative"},"layout":"multi","source":"github","category":"SenseNova-Skills","frontmatter":{"name":"sn-ppt-creative","description":"Creative-mode PPT pipeline. One full-page 16:9 PNG per slide.\nLLM / VLM calls go through sn-ppt-standard/lib/model_client.py (shared thin client).\nText-to-image (the actual png rendering) goes through sn-image-base/scripts/sn_agent_runner.py.\nExpects task_pack.json + info_pack.json already written by sn-ppt-entry."},"skills_sh_url":"https://skills.sh/OpenSenseNova/SenseNova-Skills/sn-ppt-creative"},"updatedAt":"2026-05-18T18:53:05.372Z"}}