[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M70FWKT5BFWRD619VZHTA4PK":3,"skill-same:01M70FWKT5BFWRD619VZHTA4PK":67},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":23,"publishedAt":40,"linkOnly":41,"markdownContent":42,"markdownBody":43,"frontMatter":44,"refName":46,"commitSha":47,"skillDirectory":48,"forksCount":49,"repositoryHtmlUrl":50,"repositoryHomepageUrl":6,"ownerHtmlUrl":51,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":52,"install":53,"resources":66},"01M70FWKT5BFWRD619VZHTA4PK","slack-block-action-handlers",null,"Slack 按钮点击 (block_action) 的确定性路由协议——新建审批卡按钮时必须在 `profiles\u002F\u003Cyour-profile>\u002Fscripts\u002Fhandlers\u002F` 下放同名 handler 脚本，adapter 按 action_id 直接执行（零 LLM、零 worker fork）。Use when 需要新建带按钮的 Slack 卡片、修改 handler 脚本、或排查按钮点击无响应。","KarryViber\u002FOrb","KarryViber","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F223777671?v=4","01M70FTGZ485AP97T3CJCYW1Z2","Karryz","01M70FTGZRWF3FEQBYZ3JWTSPR",66,"MIT","https:\u002F\u002Fgithub.com\u002FKarryViber\u002FOrb\u002Fblob\u002Fmain\u002Fprofiles\u002F.claude\u002Fskills\u002Fslack-block-action-handlers\u002FSKILL.md",[18],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000005","邮件与沟通","SCENARIO","使用场景",[24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39],"slack","block","action","slack block action handlers","user","profile","use","按钮","worker","id","scripts","adapter","profiles","fork","handler","when","2026-11-10 10:12:30",false,"---\nname: slack-block-action-handlers\ndescription: Slack 按钮点击 (block_action) 的确定性路由协议——新建审批卡按钮时必须在 `profiles\u002F\u003Cyour-profile>\u002Fscripts\u002Fhandlers\u002F` 下放同名 handler 脚本，adapter 按 action_id 直接执行（零 LLM、零 worker fork）。Use when 需要新建带按钮的 Slack 卡片、修改 handler 脚本、或排查按钮点击无响应。\nprovenance: user-authored\n---\n\n# Slack block_action Handlers\n\n> 🚧 **待 adapter 实现** — 本 skill 描述目标协议（见 `specs\u002Fslack-block-action-handlers.md`）。当前 `src\u002Fadapters\u002Fslack.js:865` 仍静默丢弃 block_action，按钮点击不会触发 handler。spec 落地后本标记移除。\n\n外部脚本（cron \u002F Python \u002F Node）自推的审批卡按钮被点击后，Slack 回传 block_action 事件。Orb adapter 做**确定性路由**——按 `action_id` 找同名 handler 脚本执行，**不走 LLM，不 fork worker**。\n\n## 发现规则\n\n```\nprofiles\u002F{profile}\u002Fscripts\u002Fhandlers\u002F{action_id}.{py,sh,js}\n```\n\n- `action_id` 必须匹配正则 `^[a-z][a-z0-9_]{0,63}$`（snake_case，防路径穿越）\n- 扩展名查找顺序：`.py` → `.sh` → `.js`\n- **未找到 handler** → adapter chat.update 成 `⚠️ 未注册 handler: {action_id}` 并 @Karry\n\n## 现有 handlers（04-21）\n\n```\norb_x_post_approve.py     — X 拟稿审批通过 → 发推\norb_x_post_reject.py      — X 拟稿拒绝\norb_x_reply_approve.py    — X 回复审批通过\norb_x_reply_reject.py     — X 回复拒绝\n```\n\n新增按钮前先看有没有可复用的 action_id 命名。\n\n## Handler 接口（stdin JSON）\n\nadapter spawn handler 时通过 **stdin 单行 JSON** 传 context（避免 env 长度限制和 argv 注入）：\n\n```json\n{\n  \"action_id\": \"orb_x_post_approve\",\n  \"value\": \"\u003Cbutton value 原样透传，可能是 base64 payload>\",\n  \"user_id\": \"U0123456789\",\n  \"channel\": \"C0AP013V056\",\n  \"message_ts\": \"1776702715.774950\",\n  \"thread_ts\": \"1776702715.774949\",\n  \"profile\": \"\u003Cprofile-name>\",\n  \"response_url\": \"\u003CSlack response_url>\"\n}\n```\n\nhandler 模板（Python）：\n\n```python\n#!\u002Fusr\u002Fbin\u002Fenv python3\nimport sys, json, os\n\nctx = json.loads(sys.stdin.read())\naction = ctx[\"action_id\"]\nvalue = ctx[\"value\"]\nchannel = ctx[\"channel\"]\nmessage_ts = ctx[\"message_ts\"]\n\n# 业务逻辑...\n\n# 自己 chat.update 最终态（Slack Web API 或 response_url）\n# adapter 不会替你改卡面！\n```\n\n## 生命周期（重点）\n\n**adapter 不持有 handler 进程**。流程：\n\n1. Adapter 收到 block_action，ack Slack\n2. Adapter chat.update 原卡为 `⏳ 处理中… \u003C@{user}> clicked \\`{action_id}\\``（禁用按钮，防重复点）\n3. Adapter spawn handler，**detach + unref**（不 wait、不超时、不 kill）\n4. Adapter 记 `logs\u002Fhandlers\u002Fpids.log` 一行：`{ts} pid={pid} action_id={id} message_ts={ts}`\n5. Handler 自己跑完业务，**自己 chat.update 最终态**（用 response_url 或 Slack Web API token）\n\n## Handler 自律清单（必做）\n\n- [ ] 读 stdin 拿 context\n- [ ] 执行业务\n- [ ] **chat.update 最终态**（成功\u002F失败\u002F跳过都要更新，否则卡面永远显示 ⏳）\n- [ ] 业务自带超时（发推 10s \u002F LLM 生成 60s），超时内部自己写 `❌ 超时` + exit\n- [ ] stdout 日志 adapter 捕获到 `logs\u002Fhandlers\u002F{action_id}-{ts}.log`\n\n## 并发去重\n\nadapter 维护 `Set\u003Cmessage_ts>`：\n- 点击时 message_ts 已在集合里 → 仅 ack，不再 spawn\n- 释放条件：chat.update 已变成非 `⏳ 处理中` 状态（handler 通过 update 隐式宣告完成）\n- 兜底：10min 定时清理\n\n## 安全边界\n\n- handler 路径硬限 `profiles\u002F{profile}\u002Fscripts\u002Fhandlers\u002F`，`..` \u002F 绝对路径被拒\n- 执行用户同 daemon（没有额外 sandbox）\n- `action_id` 白名单正则已覆盖大部分注入面\n- `value` 字段 adapter 不解析，原样透传给 handler——**handler 自己验证 payload**（别信 value）\n\n## Gotchas\n\n1. **handler 漏写 chat.update** → 卡面永远 ⏳（不是 adapter bug，是脚本 bug）。模板必带 try\u002Fexcept + finally chat.update\n2. **button value 超 2000 字** 会被 Slack 截断。payload 太大就存文件，value 只放引用 id\n3. **action_id 命名** 要能表达「什么操作 + 什么对象」（好：`orb_x_post_approve`；坏：`btn1`）\n4. **adapter 不重试**。handler crash = 卡面永远 ⏳，Karry 手动点醒或查 `logs\u002Fhandlers\u002F`\n5. **新 handler 首次上线** 在 DM 先跑一张测试卡，别直接在对外频道首发\n6. **Python handler 缺依赖** spawn 时 silent 失败（stderr 进 log 文件，卡面不变）；新增前先 `python3 handlers\u002Ffoo.py \u003C test.json` 跑一次\n\n## 新建按钮的完整工作流\n\n1. 想好 action_id（snake_case，表达「操作+对象」）\n2. 复制最像的 existing handler 作模板\n3. 本地 dry-run：构造 test.json → `python3 handlers\u002F{new_id}.py \u003C test.json`，验证能 chat.update\n4. 在生成卡片的脚本里新增按钮：\n   ```python\n   {\"type\": \"button\", \"text\": {\"type\": \"plain_text\", \"text\": \"✅ Approve\"}, \"action_id\": \"new_action_id\", \"value\": \"...\"}\n   ```\n5. DM 先测，验证 adapter 路由 + handler chat.update 都走通\n6. 推到对外频道\n","# Slack block_action Handlers\n\n> 🚧 **待 adapter 实现** — 本 skill 描述目标协议（见 `specs\u002Fslack-block-action-handlers.md`）。当前 `src\u002Fadapters\u002Fslack.js:865` 仍静默丢弃 block_action，按钮点击不会触发 handler。spec 落地后本标记移除。\n\n外部脚本（cron \u002F Python \u002F Node）自推的审批卡按钮被点击后，Slack 回传 block_action 事件。Orb adapter 做**确定性路由**——按 `action_id` 找同名 handler 脚本执行，**不走 LLM，不 fork worker**。\n\n## 发现规则\n\n```\nprofiles\u002F{profile}\u002Fscripts\u002Fhandlers\u002F{action_id}.{py,sh,js}\n```\n\n- `action_id` 必须匹配正则 `^[a-z][a-z0-9_]{0,63}$`（snake_case，防路径穿越）\n- 扩展名查找顺序：`.py` → `.sh` → `.js`\n- **未找到 handler** → adapter chat.update 成 `⚠️ 未注册 handler: {action_id}` 并 @Karry\n\n## 现有 handlers（04-21）\n\n```\norb_x_post_approve.py     — X 拟稿审批通过 → 发推\norb_x_post_reject.py      — X 拟稿拒绝\norb_x_reply_approve.py    — X 回复审批通过\norb_x_reply_reject.py     — X 回复拒绝\n```\n\n新增按钮前先看有没有可复用的 action_id 命名。\n\n## Handler 接口（stdin JSON）\n\nadapter spawn handler 时通过 **stdin 单行 JSON** 传 context（避免 env 长度限制和 argv 注入）：\n\n```json\n{\n  \"action_id\": \"orb_x_post_approve\",\n  \"value\": \"\u003Cbutton value 原样透传，可能是 base64 payload>\",\n  \"user_id\": \"U0123456789\",\n  \"channel\": \"C0AP013V056\",\n  \"message_ts\": \"1776702715.774950\",\n  \"thread_ts\": \"1776702715.774949\",\n  \"profile\": \"\u003Cprofile-name>\",\n  \"response_url\": \"\u003CSlack response_url>\"\n}\n```\n\nhandler 模板（Python）：\n\n```python\n#!\u002Fusr\u002Fbin\u002Fenv python3\nimport sys, json, os\n\nctx = json.loads(sys.stdin.read())\naction = ctx[\"action_id\"]\nvalue = ctx[\"value\"]\nchannel = ctx[\"channel\"]\nmessage_ts = ctx[\"message_ts\"]\n\n# 业务逻辑...\n\n# 自己 chat.update 最终态（Slack Web API 或 response_url）\n# adapter 不会替你改卡面！\n```\n\n## 生命周期（重点）\n\n**adapter 不持有 handler 进程**。流程：\n\n1. Adapter 收到 block_action，ack Slack\n2. Adapter chat.update 原卡为 `⏳ 处理中… \u003C@{user}> clicked \\`{action_id}\\``（禁用按钮，防重复点）\n3. Adapter spawn handler，**detach + unref**（不 wait、不超时、不 kill）\n4. Adapter 记 `logs\u002Fhandlers\u002Fpids.log` 一行：`{ts} pid={pid} action_id={id} message_ts={ts}`\n5. Handler 自己跑完业务，**自己 chat.update 最终态**（用 response_url 或 Slack Web API token）\n\n## Handler 自律清单（必做）\n\n- [ ] 读 stdin 拿 context\n- [ ] 执行业务\n- [ ] **chat.update 最终态**（成功\u002F失败\u002F跳过都要更新，否则卡面永远显示 ⏳）\n- [ ] 业务自带超时（发推 10s \u002F LLM 生成 60s），超时内部自己写 `❌ 超时` + exit\n- [ ] stdout 日志 adapter 捕获到 `logs\u002Fhandlers\u002F{action_id}-{ts}.log`\n\n## 并发去重\n\nadapter 维护 `Set\u003Cmessage_ts>`：\n- 点击时 message_ts 已在集合里 → 仅 ack，不再 spawn\n- 释放条件：chat.update 已变成非 `⏳ 处理中` 状态（handler 通过 update 隐式宣告完成）\n- 兜底：10min 定时清理\n\n## 安全边界\n\n- handler 路径硬限 `profiles\u002F{profile}\u002Fscripts\u002Fhandlers\u002F`，`..` \u002F 绝对路径被拒\n- 执行用户同 daemon（没有额外 sandbox）\n- `action_id` 白名单正则已覆盖大部分注入面\n- `value` 字段 adapter 不解析，原样透传给 handler——**handler 自己验证 payload**（别信 value）\n\n## Gotchas\n\n1. **handler 漏写 chat.update** → 卡面永远 ⏳（不是 adapter bug，是脚本 bug）。模板必带 try\u002Fexcept + finally chat.update\n2. **button value 超 2000 字** 会被 Slack 截断。payload 太大就存文件，value 只放引用 id\n3. **action_id 命名** 要能表达「什么操作 + 什么对象」（好：`orb_x_post_approve`；坏：`btn1`）\n4. **adapter 不重试**。handler crash = 卡面永远 ⏳，Karry 手动点醒或查 `logs\u002Fhandlers\u002F`\n5. **新 handler 首次上线** 在 DM 先跑一张测试卡，别直接在对外频道首发\n6. **Python handler 缺依赖** spawn 时 silent 失败（stderr 进 log 文件，卡面不变）；新增前先 `python3 handlers\u002Ffoo.py \u003C test.json` 跑一次\n\n## 新建按钮的完整工作流\n\n1. 想好 action_id（snake_case，表达「操作+对象」）\n2. 复制最像的 existing handler 作模板\n3. 本地 dry-run：构造 test.json → `python3 handlers\u002F{new_id}.py \u003C test.json`，验证能 chat.update\n4. 在生成卡片的脚本里新增按钮：\n   ```python\n   {\"type\": \"button\", \"text\": {\"type\": \"plain_text\", \"text\": \"✅ Approve\"}, \"action_id\": \"new_action_id\", \"value\": \"...\"}\n   ```\n5. DM 先测，验证 adapter 路由 + handler chat.update 都走通\n6. 推到对外频道\n",{"name":5,"provenance":45,"description":7},"user-authored","main","cb33813b8990e4602b7c2d501659f77ebba5999f","profiles\u002F.claude\u002Fskills\u002Fslack-block-action-handlers",8,"https:\u002F\u002Fgithub.com\u002FKarryViber\u002FOrb","https:\u002F\u002Fgithub.com\u002FKarryViber","2026-05-14 18:44:03",{"source":8,"skillName":5,"commands":54,"prompt":64,"zipAvailable":65},[55,58,61],{"tool":56,"command":57},"npx","npx skills add KarryViber\u002FOrb --skill slack-block-action-handlers",{"tool":59,"command":60},"bunx","bunx skills add KarryViber\u002FOrb --skill slack-block-action-handlers",{"tool":62,"command":63},"pnpm","pnpm dlx skills add KarryViber\u002FOrb --skill slack-block-action-handlers","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FKarryViber\u002FOrb\u002Fblob\u002Fmain\u002Fprofiles\u002F.claude\u002Fskills\u002Fslack-block-action-handlers\u002FSKILL.md",true,[],[68,100,114,136,155,168],{"skillNo":69,"name":70,"nameZh":6,"description":71,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":72,"licenseFileUrl":73,"sourceHtmlUrl":74,"categories":75,"keywords":82,"publishedAt":40},"01M70G0637CFCHAY3DYTMYS07K","webapp-testing","Toolkit for interacting with and testing local web applications using Playwright. Supports verifying frontend functionality, debugging UI behavior, capturing browser screenshots, and viewing browser logs.","Apache-2.0","https:\u002F\u002Fgithub.com\u002FKarryViber\u002FOrb\u002Fblob\u002Fmain\u002Fprofiles\u002F.claude\u002Fskills\u002Fwebapp-testing\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002FKarryViber\u002FOrb\u002Fblob\u002Fmain\u002Fprofiles\u002F.claude\u002Fskills\u002Fwebapp-testing\u002FSKILL.md",[76,79],{"categoryNo":77,"categoryName":78,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000008","测试与质量",{"categoryNo":80,"categoryName":81,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000009","前端开发",[83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99],"webapp","testing","webapp testing","playwright","screenshots","ui","behavior","web","for","with","browser","logs","toolkit","debugging","frontend","local","applications",{"skillNo":101,"name":102,"nameZh":6,"description":103,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":104,"categories":105,"keywords":106,"publishedAt":40},"01M70FZXCJ5AHJ3JW2Q12F04TA","vendor-doc-actionability","对外合作文档（交付文档 \u002F POC 文档 \u002F Solution Doc \u002F 提案书）必须为每个「需对方执行」的动作写清具体操作入口（URL \u002F 工单系统 \u002F 脚本路径 \u002F 联系人 + 联系方式 \u002F 步骤编号）。Use when 给客户、vendor、合作方写交付文档、POC 文档、Solution Doc、提案书；或检视已有对外文档是否抽象到无法执行。","https:\u002F\u002Fgithub.com\u002FKarryViber\u002FOrb\u002Fblob\u002Fmain\u002Fprofiles\u002F.claude\u002Fskills\u002Fvendor-doc-actionability\u002FSKILL.md",[],[107,108,109,110,111,30,112,39,113,28],"vendor","doc","vendor doc actionability","poc","文档","提案","URL",{"skillNo":115,"name":116,"nameZh":6,"description":117,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":118,"categories":119,"keywords":128,"publishedAt":40},"01M70FZARY5P7VRJKVFATTCVX9","vendor-api-param-validation","第三方 API \u002F SDK 集成开工前，强制先列参数 checklist 并对照官方文档逐项验证（名称 \u002F 类型 \u002F 必填 \u002F 默认 \u002F 上限），通过后再编码——不是「写完再调通」。Use when 新接 vendor API\u002FSDK（Slack \u002F LongPort \u002F freee \u002F LLM API 等）、既有集成追加新 endpoint 或新字段、用户说「调通某接口」「接入 X」「集成 X」。","https:\u002F\u002Fgithub.com\u002FKarryViber\u002FOrb\u002Fblob\u002Fmain\u002Fprofiles\u002F.claude\u002Fskills\u002Fvendor-api-param-validation\u002FSKILL.md",[120,123],{"categoryNo":121,"categoryName":122,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000010","后端与接口",{"categoryNo":124,"categoryName":125,"taxonomyType":126,"taxonomyTypeDesc":127},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[129,130,107,131,24,132,133,111,134,30,39,28,135],"vendor api param validation","validation","api","sdk","llm api","checklist","endpoint",{"skillNo":137,"name":138,"nameZh":6,"description":139,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":140,"categories":141,"keywords":143,"publishedAt":40},"01M70FYW81TRN7VAS8WTN08STH","truth-ladder","状态放行三层阶梯（attempted \u002F observed \u002F confirmed）—— 汇报任务、API、命令、消息或外部动作状态时强制分层，避免把\"动作已发起\"误写成\"结果已达成\"。Use when 准备写「任务已完成」「API 返回成功」「exit code 0」「用户已收到」「ok:true」类状态汇报；或在 cron 报告 \u002F Slack 回报 \u002F project status \u002F receipt 中表达完成度时。","https:\u002F\u002Fgithub.com\u002FKarryViber\u002FOrb\u002Fblob\u002Fmain\u002Fprofiles\u002F.claude\u002Fskills\u002Ftruth-ladder\u002FSKILL.md",[142],{"categoryNo":124,"categoryName":125,"taxonomyType":126,"taxonomyTypeDesc":127},[144,145,146,131,147,39,30,148,149,150,151,152,153,24,154],"ladder","truth ladder","ok","code","exit","true","status","报告","cron","project","project status",{"skillNo":156,"name":157,"nameZh":6,"description":158,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":159,"categories":160,"keywords":161,"publishedAt":40},"01M70FYTESF5WQYBVRX8BXYJQF","thread-object-realignment","长 thread 切题后的对象重定协议——thread 历史 ≥5 条且检测到切题信号时，回复前必做「用户最后显式问题对象 vs 待发回复对象」一致性校验，不一致则改写或反问。Use when Slack thread 历史 ≥5 条且当前用户消息出现切题信号（主题词突变、问句指向新实体、时间线跳跃、出现「另外」「话说」「回到 X」「换个话题」等切题语，或 ≥3 turn 后用户显式问题对象与最近 assistant 回复对象不同）。","https:\u002F\u002Fgithub.com\u002FKarryViber\u002FOrb\u002Fblob\u002Fmain\u002Fprofiles\u002F.claude\u002Fskills\u002Fthread-object-realignment\u002FSKILL.md",[],[162,163,164,24,165,28,166,39,167,30],"object","thread","thread object realignment","校验","slack thread","assistant",{"skillNo":169,"name":170,"nameZh":6,"description":171,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":72,"licenseFileUrl":172,"sourceHtmlUrl":173,"categories":174,"keywords":178,"publishedAt":40},"01M70FYFC1Y2J16FJFEFQ5WYRE","theme-factory","Toolkit for styling artifacts with a theme. These artifacts can be slides, docs, reportings, HTML landing pages, etc. There are 10 pre-set themes with colors\u002Ffonts that you can apply to any artifact that has been creating, or can generate a new theme on-the-fly.","https:\u002F\u002Fgithub.com\u002FKarryViber\u002FOrb\u002Fblob\u002Fmain\u002Fprofiles\u002F.claude\u002Fskills\u002Ftheme-factory\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002FKarryViber\u002FOrb\u002Fblob\u002Fmain\u002Fprofiles\u002F.claude\u002Fskills\u002Ftheme-factory\u002FSKILL.md",[175],{"categoryNo":176,"categoryName":177,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000015","视觉设计",[179,180,181,182,183,184,185,186,92,187,188,95,189,190,191,192,193,91,194,195],"theme factory","factory","theme","apply","styling","fly","generate","artifact","fonts","can","artifacts","you","themes","pages","landing","slides","SET"]