sophhub 0.4.19 → 0.4.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (633) hide show
  1. package/README.md +199 -187
  2. package/agents/ai-cs-admin/.config.json +51 -51
  3. package/agents/ai-cs-admin/AGENTS.md +293 -293
  4. package/agents/ai-cs-admin/HEARTBEAT.md +18 -18
  5. package/agents/ai-cs-qa/.config.json +47 -47
  6. package/agents/ai-cs-qa/BOOTSTRAP.md +22 -22
  7. package/agents/ai-cs-qa/scripts/setup_links.sh +39 -39
  8. package/agents/beauty/.config.json +17 -17
  9. package/agents/beauty/AGENTS.md +234 -234
  10. package/agents/beauty/BOOTSTRAP.md +55 -55
  11. package/agents/beauty/HEARTBEAT.md +5 -5
  12. package/agents/beauty/IDENTITY.md +5 -5
  13. package/agents/beauty/MEMORY.md +44 -44
  14. package/agents/beauty/SOUL.md +64 -64
  15. package/agents/beauty/TOOLS.md +160 -160
  16. package/agents/beauty/USER.md +114 -114
  17. package/agents/intern-admin/.config.json +60 -60
  18. package/agents/intern-admin/AGENTS.md +267 -267
  19. package/agents/intern-admin/BOOTSTRAP.md +21 -21
  20. package/agents/intern-admin/HEARTBEAT.md +3 -3
  21. package/agents/intern-admin/IDENTITY.md +6 -6
  22. package/agents/intern-admin/MEMORY.md +21 -21
  23. package/agents/intern-admin/SOUL.md +23 -23
  24. package/agents/intern-admin/TOOLS.md +93 -93
  25. package/agents/intern-admin/USER.md +16 -16
  26. package/agents/intern-admin/scripts/init_workspace.sh +27 -27
  27. package/agents/intern-qa/.config.json +46 -46
  28. package/agents/intern-qa/AGENTS.md +303 -303
  29. package/agents/intern-qa/BOOTSTRAP.md +16 -16
  30. package/agents/intern-qa/HEARTBEAT.md +3 -3
  31. package/agents/intern-qa/IDENTITY.md +6 -6
  32. package/agents/intern-qa/MEMORY.md +22 -22
  33. package/agents/intern-qa/SOUL.md +24 -24
  34. package/agents/intern-qa/TOOLS.md +24 -24
  35. package/agents/intern-qa/USER.md +27 -27
  36. package/agents/intern-qa/scripts/setup_links.sh +54 -54
  37. package/agents/parent-toddler/.config.json +37 -37
  38. package/agents/parent-toddler/AGENTS.md +51 -51
  39. package/agents/parent-toddler/BOOTSTRAP.md +55 -55
  40. package/agents/parent-toddler/HEARTBEAT.md +5 -5
  41. package/agents/parent-toddler/IDENTITY.md +5 -5
  42. package/agents/parent-toddler/MEMORY.md +22 -22
  43. package/agents/parent-toddler/SOUL.md +35 -35
  44. package/agents/parent-toddler/TOOLS.md +31 -31
  45. package/agents/parent-toddler/USER.md +44 -44
  46. package/agents/vip-admin/.config.json +51 -51
  47. package/agents/vip-admin/AGENTS.md +314 -314
  48. package/agents/vip-admin/BOOTSTRAP.md +21 -21
  49. package/agents/vip-admin/HEARTBEAT.md +19 -19
  50. package/agents/vip-admin/IDENTITY.md +6 -6
  51. package/agents/vip-admin/MEMORY.md +30 -30
  52. package/agents/vip-admin/SOUL.md +25 -25
  53. package/agents/vip-admin/TOOLS.md +108 -108
  54. package/agents/vip-admin/USER.md +31 -31
  55. package/agents/vip-qa/.config.json +58 -58
  56. package/agents/vip-qa/AGENTS.md +319 -319
  57. package/agents/vip-qa/BOOTSTRAP.md +73 -73
  58. package/agents/vip-qa/HEARTBEAT.md +23 -23
  59. package/agents/vip-qa/IDENTITY.md +7 -7
  60. package/agents/vip-qa/MEMORY.md +23 -23
  61. package/agents/vip-qa/SOUL.md +34 -34
  62. package/agents/vip-qa/TOOLS.md +41 -41
  63. package/agents/vip-qa/USER.md +16 -16
  64. package/agents/vip-qa/scripts/setup_links.sh +39 -39
  65. package/bin/sophhub.js +25 -25
  66. package/package.json +35 -33
  67. package/skills/agent-install/skill.json +34 -34
  68. package/skills/agent-install/src/SKILL.md +240 -240
  69. package/skills/agent-install/src/pyproject.toml +6 -6
  70. package/skills/agent-install/src/scripts/backup_agent.py +120 -120
  71. package/skills/agent-install/src/scripts/check_installed.py +479 -479
  72. package/skills/agent-install/src/scripts/common.py +568 -568
  73. package/skills/agent-install/src/scripts/copy_agent_files.py +59 -59
  74. package/skills/agent-install/src/scripts/list_agents.py +285 -285
  75. package/skills/agent-install/src/scripts/resolve_install_params.py +90 -90
  76. package/skills/agent-install/src/scripts/update_agent_md.py +76 -76
  77. package/skills/agent-install/src/scripts/update_openclaw.py +193 -193
  78. package/skills/agent-install/src/scripts/verify_download.py +148 -148
  79. package/skills/aippt/skill.json +20 -20
  80. package/skills/aippt/src/SKILL.md +235 -235
  81. package/skills/aippt/src/pyproject.toml +8 -8
  82. package/skills/aippt/src/scripts/auth.py +122 -122
  83. package/skills/aippt/src/scripts/ppt.py +361 -361
  84. package/skills/aippt/src/scripts/provider_docmee.py +299 -299
  85. package/skills/beauty-salon-inventory/skill.json +16 -16
  86. package/skills/beauty-salon-inventory/src/SKILL.md +69 -69
  87. package/skills/beauty-salon-inventory/src/scripts/init_salon_inventory.py +39 -39
  88. package/skills/beauty-salon-inventory/src/scripts/init_salon_inventory.sh +4 -4
  89. package/skills/beauty-salon-inventory/src/scripts/salon_inventory_cli.py +244 -244
  90. package/skills/beauty-salon-marketing/skill.json +10 -10
  91. package/skills/beauty-salon-marketing/src/SKILL.md +36 -36
  92. package/skills/beauty-salon-marketing/src/playbooks/beauty-salon-festival.md +19 -19
  93. package/skills/beauty-salon-marketing/src/playbooks/beauty-salon-segment.md +18 -18
  94. package/skills/beauty-salon-marketing/src/scripts/beauty_marketing_cli.py +99 -99
  95. package/skills/beauty-salon-marketing/src/scripts/member_segment.py +114 -114
  96. package/skills/beauty-salon-member-appointment/skill.json +10 -10
  97. package/skills/beauty-salon-member-appointment/src/SKILL.md +36 -36
  98. package/skills/beauty-salon-member-appointment/src/pyproject.toml +9 -9
  99. package/skills/beauty-salon-member-appointment/src/scripts/run_e2e_smoke.py +160 -160
  100. package/skills/beauty-salon-member-appointment/src/src/member_appt_cli/__init__.py +1 -1
  101. package/skills/beauty-salon-member-appointment/src/src/member_appt_cli/__main__.py +4 -4
  102. package/skills/beauty-salon-member-appointment/src/src/member_appt_cli/cli.py +921 -921
  103. package/skills/beauty-salon-member-appointment/src/src/member_appt_cli/db.py +30 -30
  104. package/skills/beauty-salon-membership/skill.json +20 -20
  105. package/skills/beauty-salon-membership/src/SKILL.md +67 -67
  106. package/skills/beauty-salon-product-service/skill.json +12 -12
  107. package/skills/beauty-salon-product-service/src/SKILL.md +42 -42
  108. package/skills/beauty-salon-product-service/src/pyproject.toml +9 -9
  109. package/skills/beauty-salon-product-service/src/src/product_service_cli/__init__.py +1 -1
  110. package/skills/beauty-salon-product-service/src/src/product_service_cli/__main__.py +4 -4
  111. package/skills/beauty-salon-product-service/src/src/product_service_cli/cli.py +329 -329
  112. package/skills/beauty-salon-product-service/src/src/product_service_cli/db.py +29 -29
  113. package/skills/beauty-salon-staff/skill.json +10 -10
  114. package/skills/beauty-salon-staff/src/SKILL.md +37 -37
  115. package/skills/beauty-salon-staff/src/pyproject.toml +9 -9
  116. package/skills/beauty-salon-staff/src/src/staff_cli/__init__.py +1 -1
  117. package/skills/beauty-salon-staff/src/src/staff_cli/__main__.py +4 -4
  118. package/skills/beauty-salon-staff/src/src/staff_cli/cli.py +479 -479
  119. package/skills/beauty-salon-staff/src/src/staff_cli/db.py +28 -28
  120. package/skills/beauty-salon-suite/skill.json +13 -13
  121. package/skills/beauty-salon-suite/src/SKILL.md +18 -18
  122. package/skills/beauty-salon-suite/src/beauty_db/__init__.py +2 -2
  123. package/skills/beauty-salon-suite/src/beauty_db/db.py +249 -249
  124. package/skills/beauty-salon-traffic/skill.json +20 -20
  125. package/skills/beauty-salon-traffic/src/SKILL.md +84 -84
  126. package/skills/bing-image-search/skill.json +20 -20
  127. package/skills/bing-image-search/src/SKILL.md +105 -105
  128. package/skills/bot-api-status/skill.json +44 -44
  129. package/skills/bot-api-status/src/SKILL.md +99 -99
  130. package/skills/bot-api-status/src/pyproject.toml +5 -5
  131. package/skills/bot-api-status/src/scripts/secret.py +496 -496
  132. package/skills/bot-secret/skill.json +35 -35
  133. package/skills/bot-secret/src/SKILL.md +51 -51
  134. package/skills/bot-secret/src/pyproject.toml +5 -5
  135. package/skills/bot-secret/src/scripts/secret.py +120 -120
  136. package/skills/cake-flower-holiday-campaign/skill.json +20 -20
  137. package/skills/cake-flower-holiday-campaign/src/SKILL.md +68 -68
  138. package/skills/cake-flower-order-sop/skill.json +20 -20
  139. package/skills/cake-flower-order-sop/src/SKILL.md +65 -65
  140. package/skills/claw-agent-get-send/skill.json +32 -32
  141. package/skills/claw-agent-get-send/src/SKILL.md +43 -43
  142. package/skills/claw-agent-get-send/src/pyproject.toml +5 -5
  143. package/skills/claw-agent-get-send/src/scripts/appia_claw.py +379 -379
  144. package/skills/compact-context/skill.json +20 -20
  145. package/skills/compact-context/src/SKILL.md +133 -133
  146. package/skills/compact-context/src/scripts/check.sh +381 -381
  147. package/skills/compact-context/src/scripts/set-keep-recent.mjs +1337 -1337
  148. package/skills/compact-context/src/scripts/setup.sh +96 -96
  149. package/skills/consensus/skill.json +20 -20
  150. package/skills/consensus/src/SKILL.md +93 -93
  151. package/skills/deepwiki/skill.json +20 -20
  152. package/skills/deepwiki/src/SKILL.md +45 -45
  153. package/skills/deepwiki/src/_meta.json +5 -5
  154. package/skills/deepwiki/src/scripts/deepwiki.js +135 -135
  155. package/skills/didi-ride/skill.json +20 -20
  156. package/skills/didi-ride/src/SKILL.md +309 -309
  157. package/skills/didi-ride/src/_meta.json +5 -5
  158. package/skills/didi-ride/src/assets/PREFERENCE.md +58 -58
  159. package/skills/didi-ride/src/package.json +15 -15
  160. package/skills/didi-ride/src/references/api_references.md +171 -171
  161. package/skills/didi-ride/src/references/error_handling.md +68 -68
  162. package/skills/didi-ride/src/references/setup.md +73 -73
  163. package/skills/didi-ride/src/references/workflow.md +150 -150
  164. package/skills/feishu-bitable/skill.json +20 -20
  165. package/skills/feishu-bitable/src/CHECKLIST.md +149 -149
  166. package/skills/feishu-bitable/src/README.md +177 -177
  167. package/skills/feishu-bitable/src/SKILL.md +113 -113
  168. package/skills/feishu-bitable/src/_meta.json +5 -5
  169. package/skills/feishu-bitable/src/api.js +380 -380
  170. package/skills/feishu-bitable/src/bin/cli.js +283 -283
  171. package/skills/feishu-bitable/src/description.md +142 -142
  172. package/skills/feishu-bitable/src/examples/create-records.json +51 -51
  173. package/skills/feishu-bitable/src/examples/create-table.json +63 -63
  174. package/skills/feishu-bitable/src/package-lock.json +324 -324
  175. package/skills/feishu-bitable/src/package.json +32 -32
  176. package/skills/feishu-bitable/src/publish-config.json +13 -13
  177. package/skills/feishu-bitable/src/test-simple.js +60 -60
  178. package/skills/feishu-bitable/src/utils.js +260 -260
  179. package/skills/feishu-notes-assistant-universal/skill.json +20 -20
  180. package/skills/feishu-notes-assistant-universal/src/README.md +55 -55
  181. package/skills/feishu-notes-assistant-universal/src/SKILL.md +159 -159
  182. package/skills/feishu-notes-assistant-universal/src/scripts/_resolve_lark_cli.py +58 -58
  183. package/skills/feishu-notes-assistant-universal/src/scripts/openclaw_meeting_minutes.py +462 -462
  184. package/skills/feishu-notes-assistant-universal/src/scripts/openclaw_notes_crud.py +547 -547
  185. package/skills/feishu-notes-assistant-universal/src/scripts/openclaw_notes_crud_test.py +181 -181
  186. package/skills/feishu-notes-assistant-universal/src/scripts/run_meeting_minutes.py +80 -80
  187. package/skills/feishu-notes-assistant-universal/src/scripts/run_meeting_minutes.sh +5 -5
  188. package/skills/feishu-notes-assistant-universal/src/scripts/run_note_crud.py +32 -32
  189. package/skills/feishu-notes-assistant-universal/src/scripts/run_note_crud.sh +5 -5
  190. package/skills/flight-booking/skill.json +36 -36
  191. package/skills/flight-booking/src/SKILL.md +288 -288
  192. package/skills/flight-booking/src/scripts/flight_booking.py +1237 -1237
  193. package/skills/flyai/skill.json +20 -20
  194. package/skills/flyai/src/SKILL.md +119 -119
  195. package/skills/flyai/src/references/fliggy-fast-search.md +53 -53
  196. package/skills/flyai/src/references/search-flight.md +89 -89
  197. package/skills/flyai/src/references/search-hotels.md +57 -57
  198. package/skills/flyai/src/references/search-poi.md +48 -48
  199. package/skills/google-maps/skill.json +20 -20
  200. package/skills/google-maps/src/SKILL.md +237 -237
  201. package/skills/google-maps/src/_meta.json +5 -5
  202. package/skills/google-maps/src/lib/map_helper.py +912 -912
  203. package/skills/image-classify/skill.json +42 -42
  204. package/skills/image-classify/src/SKILL.md +368 -368
  205. package/skills/image-classify/src/references/config.json +4 -4
  206. package/skills/image-classify/src/scripts/face_search.py +1276 -1276
  207. package/skills/image-description/skill.json +34 -34
  208. package/skills/image-description/src/SKILL.md +33 -33
  209. package/skills/image-description/src/pyproject.toml +8 -8
  210. package/skills/image-description/src/scripts/ana_image.py +112 -112
  211. package/skills/image-identify-world/skill.json +20 -20
  212. package/skills/image-identify-world/src/SKILL.md +40 -40
  213. package/skills/image-identify-world/src/pyproject.toml +8 -8
  214. package/skills/image-identify-world/src/scripts/identify_world.py +115 -115
  215. package/skills/insurance-policy-review/skill.json +27 -27
  216. package/skills/insurance-policy-review/src/SKILL.md +75 -75
  217. package/skills/insurance-sales-playbook/skill.json +20 -20
  218. package/skills/insurance-sales-playbook/src/SKILL.md +58 -58
  219. package/skills/inventory-management/skill.json +20 -20
  220. package/skills/inventory-management/src/SKILL.md +241 -241
  221. package/skills/inventory-management/src/scripts/inventory.py +1844 -1844
  222. package/skills/large-task-router/skill.json +20 -20
  223. package/skills/large-task-router/src/SKILL.md +79 -79
  224. package/skills/large-task-router/src/templates/plan.md +74 -74
  225. package/skills/lawding-contract-review/skill.json +20 -20
  226. package/skills/lawding-contract-review/src/SKILL.md +284 -284
  227. package/skills/lawding-contract-review/src/references/legal-language-library.md +1385 -1385
  228. package/skills/lawding-contract-review/src/scripts/build_reminders.py +471 -471
  229. package/skills/lawding-contract-review/src/scripts/register_contract_cron.py +457 -457
  230. package/skills/md2pdf-converter/skill.json +20 -20
  231. package/skills/md2pdf-converter/src/SKILL.md +244 -244
  232. package/skills/md2pdf-converter/src/_meta.json +5 -5
  233. package/skills/md2pdf-converter/src/scripts/generate_emoji_mapping.py +74 -74
  234. package/skills/md2pdf-converter/src/scripts/md2pdf-local.sh +291 -291
  235. package/skills/notes-hub-assistant/skill.json +20 -20
  236. package/skills/notes-hub-assistant/src/SKILL.md +233 -233
  237. package/skills/notes-hub-assistant/src/scripts/_resolve_lark_cli.py +48 -48
  238. package/skills/notes-hub-assistant/src/scripts/openclaw_meeting_minutes.py +473 -473
  239. package/skills/notes-hub-assistant/src/scripts/openclaw_notes_crud.py +596 -596
  240. package/skills/notes-hub-assistant/src/scripts/openclaw_wolai_notes_crud.py +364 -364
  241. package/skills/notes-hub-assistant/src/scripts/run_meeting_minutes.py +79 -79
  242. package/skills/notes-hub-assistant/src/scripts/run_note_crud.py +37 -37
  243. package/skills/notes-hub-assistant/src/scripts/run_notionbot.py +36 -36
  244. package/skills/notes-hub-assistant/src/scripts/run_wolai_note_crud.py +27 -27
  245. package/skills/schedule-reminder/skill.json +20 -20
  246. package/skills/schedule-reminder/src/SKILL.md +619 -619
  247. package/skills/schedule-reminder/src/schedule_template.md +68 -68
  248. package/skills/schedule-reminder/src/scripts/append_event.py +204 -204
  249. package/skills/schedule-reminder/src/scripts/create_reminders.sh +163 -163
  250. package/skills/schedule-reminder/src/scripts/daily_activate.sh +175 -175
  251. package/skills/schedule-reminder/src/scripts/parse_schedule.py +704 -704
  252. package/skills/schedule-reminder/src/scripts/setup.sh +242 -242
  253. package/skills/schedule-reminder/src//347/224/250/346/210/267/346/214/207/345/215/227.md +311 -311
  254. package/skills/sessions-analysis/skill.json +34 -34
  255. package/skills/sessions-analysis/src/SKILL.md +81 -81
  256. package/skills/sessions-analysis/src/pyproject.toml +5 -5
  257. package/skills/sessions-analysis/src/scripts/ana_logs.py +205 -205
  258. package/skills/share-skill/skill.json +20 -20
  259. package/skills/share-skill/src/SKILL.md +261 -261
  260. package/skills/share-skill/src/scripts/share_skill_to_friend.py +1031 -1031
  261. package/skills/skill-creator/skill.json +20 -20
  262. package/skills/skill-creator/src/SKILL.md +370 -370
  263. package/skills/skill-creator/src/license.txt +202 -202
  264. package/skills/skill-creator/src/scripts/init_skill.py +378 -378
  265. package/skills/skill-creator/src/scripts/package_skill.py +111 -111
  266. package/skills/skill-creator/src/scripts/quick_validate.py +101 -101
  267. package/skills/skillhub/skill.json +27 -27
  268. package/skills/skillhub/src/SKILL.md +121 -121
  269. package/skills/sophnet-age-appearance/skill.json +20 -20
  270. package/skills/sophnet-age-appearance/src/SKILL.md +83 -83
  271. package/skills/sophnet-age-appearance/src/pyproject.toml +10 -10
  272. package/skills/sophnet-age-appearance/src/scripts/age_appearance.py +395 -395
  273. package/skills/sophnet-age-appearance/src/scripts/age_face_crop.py +313 -313
  274. package/skills/sophnet-bot-client/skill.json +20 -20
  275. package/skills/sophnet-bot-client/src/SKILL.md +255 -255
  276. package/skills/sophnet-bot-client/src/pyproject.toml +13 -13
  277. package/skills/sophnet-bot-client/src/scripts/bot_client_proxy.py +165 -165
  278. package/skills/sophnet-bot-client/src/scripts/bot_client_safe.sh +29 -29
  279. package/skills/sophnet-bot-client/src/scripts/bot_client_setup.py +502 -502
  280. package/skills/sophnet-bot-client/src/tests/test_bot_client_proxy.py +255 -255
  281. package/skills/sophnet-bot-client/src/tests/test_bot_client_setup.py +679 -679
  282. package/skills/sophnet-bot-client/src/uv.lock +8 -8
  283. package/skills/sophnet-customer-management/skill.json +20 -20
  284. package/skills/sophnet-customer-management/src/SKILL.md +270 -270
  285. package/skills/sophnet-customer-management/src/pyproject.toml +15 -15
  286. package/skills/sophnet-customer-management/src/src/customer_mgmt_cli/__init__.py +2 -2
  287. package/skills/sophnet-customer-management/src/src/customer_mgmt_cli/__main__.py +5 -5
  288. package/skills/sophnet-customer-management/src/src/customer_mgmt_cli/cli.py +67 -67
  289. package/skills/sophnet-customer-management/src/src/customer_mgmt_cli/commands/__init__.py +2 -2
  290. package/skills/sophnet-customer-management/src/src/customer_mgmt_cli/commands/customer.py +60 -60
  291. package/skills/sophnet-customer-management/src/src/customer_mgmt_cli/commands/export_file.py +18 -18
  292. package/skills/sophnet-customer-management/src/src/customer_mgmt_cli/commands/import_file.py +15 -15
  293. package/skills/sophnet-customer-management/src/src/customer_mgmt_cli/commands/reminder.py +26 -26
  294. package/skills/sophnet-customer-management/src/src/customer_mgmt_cli/commands/schema.py +28 -28
  295. package/skills/sophnet-customer-management/src/src/customer_mgmt_cli/config.py +54 -54
  296. package/skills/sophnet-customer-management/src/src/customer_mgmt_core/__init__.py +2 -2
  297. package/skills/sophnet-customer-management/src/src/customer_mgmt_core/exporter.py +85 -85
  298. package/skills/sophnet-customer-management/src/src/customer_mgmt_core/models.py +84 -84
  299. package/skills/sophnet-customer-management/src/src/customer_mgmt_core/normalizer.py +144 -144
  300. package/skills/sophnet-customer-management/src/src/customer_mgmt_core/parser.py +241 -241
  301. package/skills/sophnet-customer-management/src/src/customer_mgmt_core/query.py +109 -109
  302. package/skills/sophnet-customer-management/src/src/customer_mgmt_core/reminder.py +121 -121
  303. package/skills/sophnet-customer-management/src/src/customer_mgmt_core/repository.py +397 -397
  304. package/skills/sophnet-customer-management/src/src/customer_mgmt_core/schema.py +106 -106
  305. package/skills/sophnet-customer-management/src/src/customer_mgmt_core/service.py +565 -565
  306. package/skills/sophnet-customer-management/src/uv.lock +48 -48
  307. package/skills/sophnet-customized-marketing/skill.json +28 -28
  308. package/skills/sophnet-customized-marketing/src/SKILL.md +144 -144
  309. package/skills/sophnet-customized-marketing/src/playbooks/campaign-planning.md +187 -187
  310. package/skills/sophnet-customized-marketing/src/playbooks/content-generation.md +124 -124
  311. package/skills/sophnet-customized-marketing/src/playbooks/marketing-calendar.md +59 -59
  312. package/skills/sophnet-customized-marketing/src/playbooks/multi-channel-bundle.md +94 -94
  313. package/skills/sophnet-customized-marketing/src/playbooks/poster-generation.md +182 -182
  314. package/skills/sophnet-customized-marketing/src/playbooks/style-profile-workflow.md +103 -103
  315. package/skills/sophnet-customized-marketing/src/pyproject.toml +8 -8
  316. package/skills/sophnet-customized-marketing/src/references/campaign-mechanics.md +168 -168
  317. package/skills/sophnet-customized-marketing/src/references/content-safety.md +26 -26
  318. package/skills/sophnet-customized-marketing/src/references/marketing-date-checklist.md +99 -99
  319. package/skills/sophnet-customized-marketing/src/references/platform-writing-guidelines.md +88 -88
  320. package/skills/sophnet-customized-marketing/src/references/quality-checklist.md +44 -44
  321. package/skills/sophnet-customized-marketing/src/scripts/generate_poster.py +572 -572
  322. package/skills/sophnet-customized-marketing/src/scripts/style_profile.py +215 -215
  323. package/skills/sophnet-dailynews/skill.json +20 -20
  324. package/skills/sophnet-dailynews/src/SKILL.md +179 -179
  325. package/skills/sophnet-dailynews/src/cache.json +150 -150
  326. package/skills/sophnet-dailynews/src/sources.json +230 -230
  327. package/skills/sophnet-docx/skill.json +20 -20
  328. package/skills/sophnet-docx/src/SKILL.md +463 -463
  329. package/skills/sophnet-docx/src/package-lock.json +208 -208
  330. package/skills/sophnet-docx/src/package.json +16 -16
  331. package/skills/sophnet-docx/src/pyproject.toml +11 -11
  332. package/skills/sophnet-docx/src/scripts/__init__.py +1 -1
  333. package/skills/sophnet-docx/src/scripts/accept_changes.py +135 -135
  334. package/skills/sophnet-docx/src/scripts/comment.py +318 -318
  335. package/skills/sophnet-docx/src/scripts/ensure_uv_env.sh +68 -68
  336. package/skills/sophnet-docx/src/scripts/office/helpers/merge_runs.py +199 -199
  337. package/skills/sophnet-docx/src/scripts/office/helpers/simplify_redlines.py +197 -197
  338. package/skills/sophnet-docx/src/scripts/office/pack.py +159 -159
  339. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -1499
  340. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -146
  341. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -1085
  342. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -11
  343. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -3081
  344. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -23
  345. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -185
  346. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -287
  347. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -1676
  348. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -28
  349. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -144
  350. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -174
  351. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -25
  352. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -18
  353. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -59
  354. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -56
  355. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -195
  356. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -582
  357. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -25
  358. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -4439
  359. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -570
  360. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -509
  361. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -12
  362. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -108
  363. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -96
  364. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -3646
  365. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -116
  366. package/skills/sophnet-docx/src/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -42
  367. package/skills/sophnet-docx/src/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -50
  368. package/skills/sophnet-docx/src/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -49
  369. package/skills/sophnet-docx/src/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -33
  370. package/skills/sophnet-docx/src/scripts/office/schemas/mce/mc.xsd +75 -75
  371. package/skills/sophnet-docx/src/scripts/office/schemas/microsoft/wml-2010.xsd +560 -560
  372. package/skills/sophnet-docx/src/scripts/office/schemas/microsoft/wml-2012.xsd +67 -67
  373. package/skills/sophnet-docx/src/scripts/office/schemas/microsoft/wml-2018.xsd +14 -14
  374. package/skills/sophnet-docx/src/scripts/office/schemas/microsoft/wml-cex-2018.xsd +20 -20
  375. package/skills/sophnet-docx/src/scripts/office/schemas/microsoft/wml-cid-2016.xsd +13 -13
  376. package/skills/sophnet-docx/src/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -4
  377. package/skills/sophnet-docx/src/scripts/office/schemas/microsoft/wml-symex-2015.xsd +8 -8
  378. package/skills/sophnet-docx/src/scripts/office/soffice.py +183 -183
  379. package/skills/sophnet-docx/src/scripts/office/unpack.py +132 -132
  380. package/skills/sophnet-docx/src/scripts/office/validate.py +111 -111
  381. package/skills/sophnet-docx/src/scripts/office/validators/__init__.py +15 -15
  382. package/skills/sophnet-docx/src/scripts/office/validators/base.py +847 -847
  383. package/skills/sophnet-docx/src/scripts/office/validators/docx.py +446 -446
  384. package/skills/sophnet-docx/src/scripts/office/validators/pptx.py +275 -275
  385. package/skills/sophnet-docx/src/scripts/office/validators/redlining.py +247 -247
  386. package/skills/sophnet-docx/src/scripts/templates/comments.xml +3 -3
  387. package/skills/sophnet-docx/src/scripts/templates/commentsExtended.xml +3 -3
  388. package/skills/sophnet-docx/src/scripts/templates/commentsExtensible.xml +3 -3
  389. package/skills/sophnet-docx/src/scripts/templates/commentsIds.xml +3 -3
  390. package/skills/sophnet-docx/src/scripts/templates/people.xml +3 -3
  391. package/skills/sophnet-docx/src/scripts/upload_file.sh +96 -96
  392. package/skills/sophnet-docx/src/uv.lock +320 -320
  393. package/skills/sophnet-face-search/skill.json +20 -20
  394. package/skills/sophnet-face-search/src/SKILL.md +115 -115
  395. package/skills/sophnet-face-search/src/pyproject.toml +11 -11
  396. package/skills/sophnet-face-search/src/scripts/face_search.py +335 -335
  397. package/skills/sophnet-face-search/src/uv.lock +508 -508
  398. package/skills/sophnet-id-photo/skill.json +20 -20
  399. package/skills/sophnet-id-photo/src/SKILL.md +107 -107
  400. package/skills/sophnet-id-photo/src/pyproject.toml +10 -10
  401. package/skills/sophnet-id-photo/src/scripts/id_photo.py +540 -540
  402. package/skills/sophnet-id-photo/src/scripts/id_photo_compliance.py +215 -215
  403. package/skills/sophnet-id-photo/src/scripts/id_photo_face_crop.py +313 -313
  404. package/skills/sophnet-image-edit/skill.json +20 -20
  405. package/skills/sophnet-image-edit/src/SKILL.md +140 -140
  406. package/skills/sophnet-image-edit/src/pyproject.toml +9 -9
  407. package/skills/sophnet-image-edit/src/scripts/edit_and_preview.sh +68 -68
  408. package/skills/sophnet-image-edit/src/scripts/edit_image.py +279 -279
  409. package/skills/sophnet-image-edit/src/uv.lock +234 -234
  410. package/skills/sophnet-image-generate/skill.json +20 -20
  411. package/skills/sophnet-image-generate/src/SKILL.md +62 -62
  412. package/skills/sophnet-image-generate/src/pyproject.toml +9 -9
  413. package/skills/sophnet-image-generate/src/scripts/generate_image.py +156 -156
  414. package/skills/sophnet-image-generate/src/uv.lock +234 -234
  415. package/skills/sophnet-image-ocr/skill.json +20 -20
  416. package/skills/sophnet-image-ocr/src/SKILL.md +167 -167
  417. package/skills/sophnet-image-ocr/src/pyproject.toml +13 -13
  418. package/skills/sophnet-image-ocr/src/scripts/ocr.py +225 -225
  419. package/skills/sophnet-image-ocr/src/uv.lock +234 -234
  420. package/skills/sophnet-infinite-talk/skill.json +20 -20
  421. package/skills/sophnet-infinite-talk/src/SKILL.md +140 -140
  422. package/skills/sophnet-infinite-talk/src/pyproject.toml +9 -9
  423. package/skills/sophnet-infinite-talk/src/scripts/gen.py +172 -172
  424. package/skills/sophnet-oss/skill.json +27 -27
  425. package/skills/sophnet-oss/src/SKILL.md +118 -118
  426. package/skills/sophnet-oss/src/pyproject.toml +8 -8
  427. package/skills/sophnet-oss/src/scripts/upload_file.py +43 -43
  428. package/skills/sophnet-pdf/skill.json +20 -20
  429. package/skills/sophnet-pdf/src/SKILL.md +413 -413
  430. package/skills/sophnet-pdf/src/forms.md +297 -297
  431. package/skills/sophnet-pdf/src/pyproject.toml +14 -14
  432. package/skills/sophnet-pdf/src/reference.md +611 -611
  433. package/skills/sophnet-pdf/src/scripts/check_bounding_boxes.py +65 -65
  434. package/skills/sophnet-pdf/src/scripts/check_fillable_fields.py +11 -11
  435. package/skills/sophnet-pdf/src/scripts/convert_pdf_to_images.py +33 -33
  436. package/skills/sophnet-pdf/src/scripts/create_validation_image.py +37 -37
  437. package/skills/sophnet-pdf/src/scripts/enhance_tutorial.py +557 -557
  438. package/skills/sophnet-pdf/src/scripts/ensure_uv_env.sh +68 -68
  439. package/skills/sophnet-pdf/src/scripts/extract_form_field_info.py +122 -122
  440. package/skills/sophnet-pdf/src/scripts/extract_form_structure.py +115 -115
  441. package/skills/sophnet-pdf/src/scripts/extract_pdf_content.py +34 -34
  442. package/skills/sophnet-pdf/src/scripts/fill_fillable_fields.py +98 -98
  443. package/skills/sophnet-pdf/src/scripts/fill_pdf_form_with_annotations.py +107 -107
  444. package/skills/sophnet-pdf/src/scripts/upload_file.sh +88 -88
  445. package/skills/sophnet-pdf/src/uv.lock +537 -537
  446. package/skills/sophnet-qa-install/skill.json +27 -27
  447. package/skills/sophnet-qa-install/src/SKILL.md +210 -210
  448. package/skills/sophnet-qa-install/src/pyproject.toml +6 -6
  449. package/skills/sophnet-qa-install/src/scripts/backup_md.py +35 -35
  450. package/skills/sophnet-qa-install/src/scripts/check_installed.py +143 -143
  451. package/skills/sophnet-qa-install/src/scripts/update_config.py +142 -142
  452. package/skills/sophnet-qa-install/src/scripts/update_md.py +73 -73
  453. package/skills/sophnet-schedule/skill.json +20 -20
  454. package/skills/sophnet-schedule/src/ARCHITECTURE.md +321 -321
  455. package/skills/sophnet-schedule/src/IMPROVEMENTS.md +145 -145
  456. package/skills/sophnet-schedule/src/SKILL.md +1050 -1050
  457. package/skills/sophnet-schedule/src/_meta.json +6 -6
  458. package/skills/sophnet-schedule/src/api/models.py +245 -245
  459. package/skills/sophnet-schedule/src/apps/add_event.py +237 -237
  460. package/skills/sophnet-schedule/src/apps/check_reminders.py +112 -112
  461. package/skills/sophnet-schedule/src/apps/check_roc.py +246 -246
  462. package/skills/sophnet-schedule/src/apps/generate_daily_plan.py +342 -342
  463. package/skills/sophnet-schedule/src/apps/import_events.py +216 -216
  464. package/skills/sophnet-schedule/src/apps/monitor_calendar_changes.py +140 -140
  465. package/skills/sophnet-schedule/src/apps/register_tasks.py +169 -169
  466. package/skills/sophnet-schedule/src/apps/sync_roc_to_gcal.py +174 -174
  467. package/skills/sophnet-schedule/src/compat.py +66 -66
  468. package/skills/sophnet-schedule/src/config/reminder_rules.yaml +96 -96
  469. package/skills/sophnet-schedule/src/config/roc_events.yaml +44 -44
  470. package/skills/sophnet-schedule/src/config/settings.py +133 -133
  471. package/skills/sophnet-schedule/src/config/task_registry.yaml +92 -92
  472. package/skills/sophnet-schedule/src/docs/FRONTEND_INTEGRATION_GUIDE.md +437 -437
  473. package/skills/sophnet-schedule/src/gcal/client.py +374 -374
  474. package/skills/sophnet-schedule/src/gcal/models.py +91 -91
  475. package/skills/sophnet-schedule/src/requirements.txt +6 -6
  476. package/skills/sophnet-schedule/src/scripts/setup_gcal_token.py +85 -85
  477. package/skills/sophnet-schedule/src/server.py +669 -669
  478. package/skills/sophnet-schedule/src/services/calendar_backend.py +139 -139
  479. package/skills/sophnet-schedule/src/services/conflict_detector.py +96 -96
  480. package/skills/sophnet-schedule/src/services/datetime_utils.py +117 -117
  481. package/skills/sophnet-schedule/src/services/event_classifier.py +100 -100
  482. package/skills/sophnet-schedule/src/services/event_diff.py +160 -160
  483. package/skills/sophnet-schedule/src/services/google_integration.py +500 -500
  484. package/skills/sophnet-schedule/src/services/job_store.py +100 -100
  485. package/skills/sophnet-schedule/src/services/local_event_store.py +266 -266
  486. package/skills/sophnet-schedule/src/services/reminder_planner.py +116 -116
  487. package/skills/sophnet-schedule/src/services/runtime_utils.py +31 -31
  488. package/skills/sophnet-schedule/src/services/table_parser.py +286 -286
  489. package/skills/sophnet-schedule/src/services/task_builder.py +167 -167
  490. package/skills/sophnet-schedule/src/services/time_window.py +72 -72
  491. package/skills/sophnet-sticker-edit/skill.json +27 -27
  492. package/skills/sophnet-sticker-edit/src/SKILL.md +80 -80
  493. package/skills/sophnet-sticker-edit/src/pyproject.toml +9 -9
  494. package/skills/sophnet-sticker-edit/src/scripts/edit_sticker_image.py +403 -403
  495. package/skills/sophnet-stock/skill.json +20 -20
  496. package/skills/sophnet-stock/src/App-Plan.md +442 -442
  497. package/skills/sophnet-stock/src/README.md +214 -214
  498. package/skills/sophnet-stock/src/SKILL.md +236 -236
  499. package/skills/sophnet-stock/src/TODO.md +394 -394
  500. package/skills/sophnet-stock/src/_meta.json +5 -5
  501. package/skills/sophnet-stock/src/docs/ARCHITECTURE.md +408 -408
  502. package/skills/sophnet-stock/src/docs/CONCEPT.md +233 -233
  503. package/skills/sophnet-stock/src/docs/HOT_SCANNER.md +288 -288
  504. package/skills/sophnet-stock/src/docs/README.md +95 -95
  505. package/skills/sophnet-stock/src/docs/USAGE.md +465 -465
  506. package/skills/sophnet-stock/src/scripts/analyze_stock.py +2565 -2565
  507. package/skills/sophnet-stock/src/scripts/dividends.py +365 -365
  508. package/skills/sophnet-stock/src/scripts/hot_scanner.py +582 -582
  509. package/skills/sophnet-stock/src/scripts/portfolio.py +548 -548
  510. package/skills/sophnet-stock/src/scripts/rumor_scanner.py +342 -342
  511. package/skills/sophnet-stock/src/scripts/test_stock_analysis.py +409 -409
  512. package/skills/sophnet-stock/src/scripts/watchlist.py +336 -336
  513. package/skills/sophnet-training-install/skill.json +27 -27
  514. package/skills/sophnet-training-install/src/SKILL.md +211 -211
  515. package/skills/sophnet-training-install/src/pyproject.toml +6 -6
  516. package/skills/sophnet-training-install/src/scripts/backup_md.py +35 -35
  517. package/skills/sophnet-training-install/src/scripts/check_installed.py +144 -144
  518. package/skills/sophnet-training-install/src/scripts/update_config.py +142 -142
  519. package/skills/sophnet-training-install/src/scripts/update_md.py +73 -73
  520. package/skills/sophnet-tts/skill.json +20 -20
  521. package/skills/sophnet-tts/src/SKILL.md +79 -79
  522. package/skills/sophnet-tts/src/pyproject.toml +9 -9
  523. package/skills/sophnet-tts/src/scripts/gen_tts.py +130 -130
  524. package/skills/sophnet-video-generate/skill.json +37 -37
  525. package/skills/sophnet-video-generate/src/SKILL.md +117 -117
  526. package/skills/sophnet-video-generate/src/scripts/gen_video.py +321 -321
  527. package/skills/sophnet-xlsx/skill.json +20 -20
  528. package/skills/sophnet-xlsx/src/SKILL.md +399 -399
  529. package/skills/sophnet-xlsx/src/pyproject.toml +11 -11
  530. package/skills/sophnet-xlsx/src/scripts/ensure_uv_env.sh +68 -68
  531. package/skills/sophnet-xlsx/src/scripts/office/helpers/merge_runs.py +199 -199
  532. package/skills/sophnet-xlsx/src/scripts/office/helpers/simplify_redlines.py +197 -197
  533. package/skills/sophnet-xlsx/src/scripts/office/pack.py +159 -159
  534. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -1499
  535. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -146
  536. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -1085
  537. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -11
  538. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -3081
  539. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -23
  540. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -185
  541. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -287
  542. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -1676
  543. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -28
  544. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -144
  545. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -174
  546. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -25
  547. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -18
  548. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -59
  549. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -56
  550. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -195
  551. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -582
  552. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -25
  553. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -4439
  554. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -570
  555. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -509
  556. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -12
  557. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -108
  558. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -96
  559. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -3646
  560. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -116
  561. package/skills/sophnet-xlsx/src/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -42
  562. package/skills/sophnet-xlsx/src/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -50
  563. package/skills/sophnet-xlsx/src/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -49
  564. package/skills/sophnet-xlsx/src/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -33
  565. package/skills/sophnet-xlsx/src/scripts/office/schemas/mce/mc.xsd +75 -75
  566. package/skills/sophnet-xlsx/src/scripts/office/schemas/microsoft/wml-2010.xsd +560 -560
  567. package/skills/sophnet-xlsx/src/scripts/office/schemas/microsoft/wml-2012.xsd +67 -67
  568. package/skills/sophnet-xlsx/src/scripts/office/schemas/microsoft/wml-2018.xsd +14 -14
  569. package/skills/sophnet-xlsx/src/scripts/office/schemas/microsoft/wml-cex-2018.xsd +20 -20
  570. package/skills/sophnet-xlsx/src/scripts/office/schemas/microsoft/wml-cid-2016.xsd +13 -13
  571. package/skills/sophnet-xlsx/src/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -4
  572. package/skills/sophnet-xlsx/src/scripts/office/schemas/microsoft/wml-symex-2015.xsd +8 -8
  573. package/skills/sophnet-xlsx/src/scripts/office/soffice.py +183 -183
  574. package/skills/sophnet-xlsx/src/scripts/office/unpack.py +132 -132
  575. package/skills/sophnet-xlsx/src/scripts/office/validate.py +111 -111
  576. package/skills/sophnet-xlsx/src/scripts/office/validators/__init__.py +15 -15
  577. package/skills/sophnet-xlsx/src/scripts/office/validators/base.py +847 -847
  578. package/skills/sophnet-xlsx/src/scripts/office/validators/docx.py +446 -446
  579. package/skills/sophnet-xlsx/src/scripts/office/validators/pptx.py +275 -275
  580. package/skills/sophnet-xlsx/src/scripts/office/validators/redlining.py +247 -247
  581. package/skills/sophnet-xlsx/src/scripts/recalc.py +184 -184
  582. package/skills/sophnet-xlsx/src/scripts/upload_file.sh +96 -96
  583. package/skills/sophnet-xlsx/src/uv.lock +319 -319
  584. package/skills/ui-ux-pro-max/skill.json +20 -20
  585. package/skills/ui-ux-pro-max/src/SKILL.md +377 -377
  586. package/skills/ui-ux-pro-max/src/data/icons.csv +101 -101
  587. package/skills/ui-ux-pro-max/src/data/react-performance.csv +45 -45
  588. package/skills/ui-ux-pro-max/src/data/stacks/astro.csv +54 -54
  589. package/skills/ui-ux-pro-max/src/data/stacks/jetpack-compose.csv +53 -53
  590. package/skills/ui-ux-pro-max/src/data/stacks/nuxt-ui.csv +51 -51
  591. package/skills/ui-ux-pro-max/src/data/stacks/nuxtjs.csv +59 -59
  592. package/skills/ui-ux-pro-max/src/data/stacks/shadcn.csv +61 -61
  593. package/skills/ui-ux-pro-max/src/data/typography.csv +57 -57
  594. package/skills/ui-ux-pro-max/src/data/ui-reasoning.csv +101 -101
  595. package/skills/ui-ux-pro-max/src/data/web-interface.csv +31 -31
  596. package/skills/ui-ux-pro-max/src/scripts/core.py +253 -253
  597. package/skills/ui-ux-pro-max/src/scripts/design_system.py +1067 -1067
  598. package/skills/video-understand/skill.json +20 -20
  599. package/skills/video-understand/src/SKILL.md +79 -79
  600. package/skills/video-understand/src/scripts/video_understand.py +204 -204
  601. package/skills/weather/skill.json +19 -19
  602. package/skills/weather/src/SKILL.md +112 -112
  603. package/skills/web-scraper/skill.json +20 -20
  604. package/skills/web-scraper/src/SKILL.md +101 -101
  605. package/skills/web-scraper/src/scripts/scrape.py +270 -270
  606. package/skills/website-builder/skill.json +20 -20
  607. package/skills/website-builder/src/SKILL.md +266 -266
  608. package/skills/website-builder/src/scripts/deploy_site.sh +46 -46
  609. package/skills/wechat-article-publisher/skill.json +20 -20
  610. package/skills/wechat-article-publisher/src/SKILL.md +60 -60
  611. package/skills/wechat-article-publisher/src/config.json +6 -6
  612. package/skills/wechat-article-publisher/src/pyproject.toml +12 -12
  613. package/skills/wechat-article-publisher/src/scripts/publish_wechat.py +825 -825
  614. package/skills/xiaohongshu/skill.json +20 -20
  615. package/skills/xiaohongshu/src/SKILL.md +91 -91
  616. package/skills/xiaohongshu/src/_meta.json +5 -5
  617. package/skills/xiaohongshu/src/assets/card.html +216 -216
  618. package/skills/xiaohongshu/src/assets/cover.html +82 -82
  619. package/skills/xiaohongshu/src/assets/example.md +84 -84
  620. package/skills/xiaohongshu/src/assets/styles.css +318 -318
  621. package/skills/xiaohongshu/src/scripts/render_xhs_v2.py +737 -737
  622. package/skills/xiaohongshu/src/scripts/sign_server.py +158 -158
  623. package/skills/xiaohongshu/src/scripts/stealth.min.js +6 -6
  624. package/skills/xiaohongshu/src/scripts/xhs_tool.py +186 -186
  625. package/skills/xiaohongshu/src/workflow.py +185 -185
  626. package/src/commands/agent.js +112 -112
  627. package/src/commands/download.js +101 -101
  628. package/src/commands/info.js +58 -58
  629. package/src/commands/list.js +71 -71
  630. package/src/utils/agents.js +36 -36
  631. package/src/utils/config.js +22 -22
  632. package/src/utils/paths.js +31 -31
  633. package/src/utils/versions.js +57 -57
@@ -1,313 +1,313 @@
1
- """
2
- 人脸检测与证件照导向裁切:调用 Sophnet detect_and_embed,将输入落地为本地文件后取置信度达标的人脸中**检测框面积最大**者,
3
- 按目标输出尺寸的宽高比裁切头肩区域,再供图改图使用。多张达标人脸时不拒审,仅按最大脸裁切。
4
- """
5
-
6
- from __future__ import annotations
7
-
8
- import base64
9
- import os
10
- import re
11
- import sys
12
- import tempfile
13
- from typing import Any
14
-
15
- import cv2
16
- import requests
17
-
18
- SOPH_BASE_URL = os.environ.get("SOPH_BASE_URL", "https://www.sophnet.com").rstrip("/")
19
- FACE_API_URL = f"{SOPH_BASE_URL}/api/open-apis/projects/detect_and_embed"
20
-
21
-
22
- def parse_output_size(size_str: str) -> tuple[int, int]:
23
- m = re.match(r"^(\d+)\s*\*\s*(\d+)$", (size_str or "").strip())
24
- if not m:
25
- raise ValueError(f"invalid size: {size_str!r}")
26
- return int(m.group(1)), int(m.group(2))
27
-
28
-
29
- def _decode_data_uri(data_uri: str) -> bytes:
30
- if not data_uri.startswith("data:") or ";base64," not in data_uri:
31
- raise ValueError("not a data URI")
32
- _meta, b64 = data_uri.split(";base64,", 1)
33
- return base64.b64decode(b64)
34
-
35
-
36
- def materialize_image(ref: str, api_key: str, download_timeout: int = 120) -> tuple[str, list[str]]:
37
- """
38
- 将输入落地为本地路径。返回 (local_path, cleanup_paths);cleanup_paths 为需事后删除的临时文件
39
- (不含用户本机原始路径)。
40
- """
41
- raw = ref.lstrip("@").strip()
42
- cleanup: list[str] = []
43
-
44
- if raw.startswith(("http://", "https://")):
45
- headers = {"Authorization": f"Bearer {api_key}"}
46
- resp = requests.get(raw, headers=headers, timeout=download_timeout, stream=True)
47
- resp.raise_for_status()
48
- ext = os.path.splitext(raw.split("?")[0])[-1].lower() or ".jpg"
49
- if ext not in (".jpg", ".jpeg", ".png", ".webp", ".bmp", ".gif"):
50
- ext = ".jpg"
51
- fd, tmp = tempfile.mkstemp(suffix=ext, prefix="id_photo_src_")
52
- os.close(fd)
53
- with open(tmp, "wb") as f:
54
- for chunk in resp.iter_content(8192):
55
- if chunk:
56
- f.write(chunk)
57
- cleanup.append(tmp)
58
- return tmp, cleanup
59
-
60
- if raw.startswith("data:image/"):
61
- blob = _decode_data_uri(raw)
62
- fd, tmp = tempfile.mkstemp(suffix=".jpg", prefix="id_photo_src_")
63
- os.close(fd)
64
- with open(tmp, "wb") as f:
65
- f.write(blob)
66
- cleanup.append(tmp)
67
- return tmp, cleanup
68
-
69
- if os.path.isfile(raw):
70
- return os.path.realpath(raw), cleanup
71
-
72
- raise FileNotFoundError(raw)
73
-
74
-
75
- def detect_faces(image_path: str, api_key: str, timeout: int = 30) -> dict[str, Any]:
76
- """调用 Sophnet detect_and_embed,成功时返回含 output 列表的字典。"""
77
- if not os.path.isfile(image_path):
78
- raise FileNotFoundError(image_path)
79
-
80
- ext = os.path.splitext(image_path)[1].lower()
81
- mime_types = {
82
- ".jpg": "image/jpeg",
83
- ".jpeg": "image/jpeg",
84
- ".png": "image/png",
85
- ".webp": "image/webp",
86
- ".bmp": "image/bmp",
87
- ".gif": "image/gif",
88
- }
89
- mime_type = mime_types.get(ext, "image/jpeg")
90
-
91
- with open(image_path, "rb") as f:
92
- files = {"file": (os.path.basename(image_path), f, mime_type)}
93
- headers = {"Authorization": f"Bearer {api_key}"}
94
- resp = requests.post(FACE_API_URL, files=files, headers=headers, timeout=timeout)
95
-
96
- if resp.status_code != 200:
97
- raise RuntimeError(f"detect_and_embed HTTP {resp.status_code}: {resp.text[:300]}")
98
-
99
- body = resp.json()
100
- return body.get("result") or {}
101
-
102
-
103
- def get_largest_face(faces: list[dict[str, Any]]) -> dict[str, Any] | None:
104
- """在列表中取检测框面积 (x2-x1)*(y2-y1) 最大的人脸。"""
105
- if not faces:
106
- return None
107
- best: dict[str, Any] | None = None
108
- best_area = 0.0
109
- for face in faces:
110
- box = face.get("box") or []
111
- if len(box) < 4:
112
- continue
113
- x1, y1, x2, y2 = (float(box[0]), float(box[1]), float(box[2]), float(box[3]))
114
- area = max(0.0, x2 - x1) * max(0.0, y2 - y1)
115
- if area > best_area:
116
- best_area = area
117
- best = face
118
- return best
119
-
120
-
121
- def compute_id_photo_crop(
122
- img_w: int,
123
- img_h: int,
124
- x1: float,
125
- y1: float,
126
- x2: float,
127
- y2: float,
128
- out_w: int,
129
- out_h: int,
130
- ) -> tuple[int, int, int, int] | None:
131
- """按目标输出宽高比,围绕人脸得到 (left, top, right, bottom),用于 numpy 切片 [top:bottom, left:right]。"""
132
- x1 = max(0.0, min(float(img_w), float(x1)))
133
- y1 = max(0.0, min(float(img_h), float(y1)))
134
- x2 = max(0.0, min(float(img_w), float(x2)))
135
- y2 = max(0.0, min(float(img_h), float(y2)))
136
- if x2 <= x1 or y2 <= y1:
137
- return None
138
-
139
- fh = y2 - y1
140
- cx = (x1 + x2) * 0.5
141
- aspect = out_w / float(out_h)
142
-
143
- margin_top = 0.58 * fh
144
- margin_bot = 1.08 * fh
145
- top_ref = y1 - margin_top
146
- bot_ref = y2 + margin_bot
147
- ref_h = bot_ref - top_ref
148
- ref_h = max(ref_h, fh * 2.15)
149
- ref_h = min(float(img_h), ref_h)
150
-
151
- crop_h = ref_h
152
- crop_w = crop_h * aspect
153
- if crop_w > img_w:
154
- crop_w = float(img_w)
155
- crop_h = crop_w / aspect
156
- if crop_h > img_h:
157
- crop_h = float(img_h)
158
- crop_w = crop_h * aspect
159
-
160
- left = cx - crop_w * 0.5
161
- left = max(0.0, min(left, float(img_w) - crop_w))
162
-
163
- # 头位略靠上:脸顶约在裁切框高度 30% 处
164
- top = y1 - 0.30 * crop_h
165
- top = max(0.0, min(top, float(img_h) - crop_h))
166
-
167
- crop_w_i = int(round(crop_w))
168
- crop_h_i = int(round(crop_h))
169
- left_i = int(round(left))
170
- top_i = int(round(top))
171
- right_i = left_i + crop_w_i
172
- bottom_i = top_i + crop_h_i
173
-
174
- if right_i > img_w:
175
- right_i = img_w
176
- left_i = max(0, right_i - crop_w_i)
177
- if bottom_i > img_h:
178
- bottom_i = img_h
179
- top_i = max(0, bottom_i - crop_h_i)
180
-
181
- if right_i - left_i < 32 or bottom_i - top_i < 32:
182
- return None
183
- return left_i, top_i, right_i, bottom_i
184
-
185
-
186
- def prepare_for_id_photo_edit(
187
- image_ref: str,
188
- api_key: str,
189
- size_str: str,
190
- *,
191
- skip_face_crop: bool = False,
192
- strict_face_gate: bool = False,
193
- det_thr: float = 0.5,
194
- detect_timeout: int = 30,
195
- download_timeout: int = 120,
196
- ) -> dict[str, Any]:
197
- """
198
- 返回:
199
- edit_ref — 送入图改图解析器的路径或 URL/data URI
200
- cleanup — 事后应删除的临时文件列表
201
- face_crop — applied | skipped_disabled | skipped_no_face | failed_* | rejected_no_face
202
- error — 可选:no_face(strict_face_gate 且零张达标人脸)
203
- face_count — 可选:仅 rejected_no_face 时为 0;成功 applied 时可有 face_detected_count
204
- face_detected_count — 可选:置信度达标的人脸数(applied 时≥1)
205
- """
206
- ref = image_ref.lstrip("@")
207
- if skip_face_crop:
208
- return {"edit_ref": ref, "cleanup": [], "face_crop": "skipped_disabled"}
209
-
210
- try:
211
- tw, th = parse_output_size(size_str)
212
- except ValueError as e:
213
- print(f"Warning: {e},将不进行人脸裁切。", file=sys.stderr)
214
- return {"edit_ref": ref, "cleanup": [], "face_crop": "failed_bad_size"}
215
-
216
- try:
217
- local_path, material_cleanup = materialize_image(ref, api_key, download_timeout=download_timeout)
218
- except Exception as e:
219
- print(f"Warning: 无法落地输入以便人脸检测与裁切,改用原始输入: {e}", file=sys.stderr)
220
- return {"edit_ref": ref, "cleanup": [], "face_crop": "failed_materialize"}
221
-
222
- try:
223
- api_result = detect_faces(local_path, api_key, timeout=detect_timeout)
224
- except Exception as e:
225
- print(f"Warning: 人脸检测接口失败,改用未裁切落地图: {e}", file=sys.stderr)
226
- if material_cleanup:
227
- return {"edit_ref": local_path, "cleanup": list(material_cleanup), "face_crop": "failed_detect"}
228
- return {"edit_ref": local_path, "cleanup": [], "face_crop": "failed_detect"}
229
-
230
- faces = api_result.get("output") or []
231
- faces = [f for f in faces if float(f.get("det_score", 0) or 0) >= det_thr]
232
-
233
- def _cleanup_material_only():
234
- for p in material_cleanup:
235
- try:
236
- if p and os.path.isfile(p):
237
- os.unlink(p)
238
- except OSError:
239
- pass
240
-
241
- if strict_face_gate:
242
- if len(faces) == 0:
243
- _cleanup_material_only()
244
- return {
245
- "error": "no_face",
246
- "edit_ref": ref,
247
- "cleanup": [],
248
- "face_crop": "rejected_no_face",
249
- "face_count": 0,
250
- }
251
-
252
- if len(faces) > 1:
253
- print(
254
- f"Warning: 检出 {len(faces)} 张达标人脸,按检测框面积最大者裁切。",
255
- file=sys.stderr,
256
- )
257
-
258
- face = get_largest_face(faces)
259
-
260
- image = cv2.imread(local_path)
261
- if image is None:
262
- print("Warning: OpenCV 无法读取落地图,改用原始输入引用", file=sys.stderr)
263
- for p in material_cleanup:
264
- try:
265
- if os.path.isfile(p):
266
- os.unlink(p)
267
- except OSError:
268
- pass
269
- return {"edit_ref": ref, "cleanup": [], "face_crop": "failed_read"}
270
-
271
- ih, iw = image.shape[:2]
272
-
273
- if not face:
274
- print("Warning: 未检出足够置信度的人脸,整图送图改图", file=sys.stderr)
275
- if material_cleanup:
276
- return {"edit_ref": local_path, "cleanup": list(material_cleanup), "face_crop": "skipped_no_face"}
277
- return {"edit_ref": local_path, "cleanup": [], "face_crop": "skipped_no_face"}
278
-
279
- box = face.get("box") or []
280
- if len(box) < 4:
281
- if material_cleanup:
282
- return {"edit_ref": local_path, "cleanup": list(material_cleanup), "face_crop": "skipped_no_face"}
283
- return {"edit_ref": local_path, "cleanup": [], "face_crop": "skipped_no_face"}
284
-
285
- rect = compute_id_photo_crop(iw, ih, float(box[0]), float(box[1]), float(box[2]), float(box[3]), tw, th)
286
- if not rect:
287
- print("Warning: 无法计算裁切框,使用整图送图改图", file=sys.stderr)
288
- if material_cleanup:
289
- return {"edit_ref": local_path, "cleanup": list(material_cleanup), "face_crop": "failed_crop_math"}
290
- return {"edit_ref": local_path, "cleanup": [], "face_crop": "failed_crop_math"}
291
-
292
- l, t, r, b = rect
293
- cropped = image[t:b, l:r]
294
- fd, out_path = tempfile.mkstemp(suffix=".jpg", prefix="id_photo_crop_")
295
- os.close(fd)
296
- ok = cv2.imwrite(out_path, cropped, [int(cv2.IMWRITE_JPEG_QUALITY), 95])
297
- if not ok:
298
- print("Warning: 裁切图写入失败,使用未裁切落地图", file=sys.stderr)
299
- try:
300
- os.unlink(out_path)
301
- except OSError:
302
- pass
303
- if material_cleanup:
304
- return {"edit_ref": local_path, "cleanup": list(material_cleanup), "face_crop": "failed_write"}
305
- return {"edit_ref": local_path, "cleanup": [], "face_crop": "failed_write"}
306
-
307
- cleanup_all = list(material_cleanup) + [out_path]
308
- return {
309
- "edit_ref": out_path,
310
- "cleanup": cleanup_all,
311
- "face_crop": "applied",
312
- "face_detected_count": len(faces),
313
- }
1
+ """
2
+ 人脸检测与证件照导向裁切:调用 Sophnet detect_and_embed,将输入落地为本地文件后取置信度达标的人脸中**检测框面积最大**者,
3
+ 按目标输出尺寸的宽高比裁切头肩区域,再供图改图使用。多张达标人脸时不拒审,仅按最大脸裁切。
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+ import base64
9
+ import os
10
+ import re
11
+ import sys
12
+ import tempfile
13
+ from typing import Any
14
+
15
+ import cv2
16
+ import requests
17
+
18
+ SOPH_BASE_URL = os.environ.get("SOPH_BASE_URL", "https://www.sophnet.com").rstrip("/")
19
+ FACE_API_URL = f"{SOPH_BASE_URL}/api/open-apis/projects/detect_and_embed"
20
+
21
+
22
+ def parse_output_size(size_str: str) -> tuple[int, int]:
23
+ m = re.match(r"^(\d+)\s*\*\s*(\d+)$", (size_str or "").strip())
24
+ if not m:
25
+ raise ValueError(f"invalid size: {size_str!r}")
26
+ return int(m.group(1)), int(m.group(2))
27
+
28
+
29
+ def _decode_data_uri(data_uri: str) -> bytes:
30
+ if not data_uri.startswith("data:") or ";base64," not in data_uri:
31
+ raise ValueError("not a data URI")
32
+ _meta, b64 = data_uri.split(";base64,", 1)
33
+ return base64.b64decode(b64)
34
+
35
+
36
+ def materialize_image(ref: str, api_key: str, download_timeout: int = 120) -> tuple[str, list[str]]:
37
+ """
38
+ 将输入落地为本地路径。返回 (local_path, cleanup_paths);cleanup_paths 为需事后删除的临时文件
39
+ (不含用户本机原始路径)。
40
+ """
41
+ raw = ref.lstrip("@").strip()
42
+ cleanup: list[str] = []
43
+
44
+ if raw.startswith(("http://", "https://")):
45
+ headers = {"Authorization": f"Bearer {api_key}"}
46
+ resp = requests.get(raw, headers=headers, timeout=download_timeout, stream=True)
47
+ resp.raise_for_status()
48
+ ext = os.path.splitext(raw.split("?")[0])[-1].lower() or ".jpg"
49
+ if ext not in (".jpg", ".jpeg", ".png", ".webp", ".bmp", ".gif"):
50
+ ext = ".jpg"
51
+ fd, tmp = tempfile.mkstemp(suffix=ext, prefix="id_photo_src_")
52
+ os.close(fd)
53
+ with open(tmp, "wb") as f:
54
+ for chunk in resp.iter_content(8192):
55
+ if chunk:
56
+ f.write(chunk)
57
+ cleanup.append(tmp)
58
+ return tmp, cleanup
59
+
60
+ if raw.startswith("data:image/"):
61
+ blob = _decode_data_uri(raw)
62
+ fd, tmp = tempfile.mkstemp(suffix=".jpg", prefix="id_photo_src_")
63
+ os.close(fd)
64
+ with open(tmp, "wb") as f:
65
+ f.write(blob)
66
+ cleanup.append(tmp)
67
+ return tmp, cleanup
68
+
69
+ if os.path.isfile(raw):
70
+ return os.path.realpath(raw), cleanup
71
+
72
+ raise FileNotFoundError(raw)
73
+
74
+
75
+ def detect_faces(image_path: str, api_key: str, timeout: int = 30) -> dict[str, Any]:
76
+ """调用 Sophnet detect_and_embed,成功时返回含 output 列表的字典。"""
77
+ if not os.path.isfile(image_path):
78
+ raise FileNotFoundError(image_path)
79
+
80
+ ext = os.path.splitext(image_path)[1].lower()
81
+ mime_types = {
82
+ ".jpg": "image/jpeg",
83
+ ".jpeg": "image/jpeg",
84
+ ".png": "image/png",
85
+ ".webp": "image/webp",
86
+ ".bmp": "image/bmp",
87
+ ".gif": "image/gif",
88
+ }
89
+ mime_type = mime_types.get(ext, "image/jpeg")
90
+
91
+ with open(image_path, "rb") as f:
92
+ files = {"file": (os.path.basename(image_path), f, mime_type)}
93
+ headers = {"Authorization": f"Bearer {api_key}"}
94
+ resp = requests.post(FACE_API_URL, files=files, headers=headers, timeout=timeout)
95
+
96
+ if resp.status_code != 200:
97
+ raise RuntimeError(f"detect_and_embed HTTP {resp.status_code}: {resp.text[:300]}")
98
+
99
+ body = resp.json()
100
+ return body.get("result") or {}
101
+
102
+
103
+ def get_largest_face(faces: list[dict[str, Any]]) -> dict[str, Any] | None:
104
+ """在列表中取检测框面积 (x2-x1)*(y2-y1) 最大的人脸。"""
105
+ if not faces:
106
+ return None
107
+ best: dict[str, Any] | None = None
108
+ best_area = 0.0
109
+ for face in faces:
110
+ box = face.get("box") or []
111
+ if len(box) < 4:
112
+ continue
113
+ x1, y1, x2, y2 = (float(box[0]), float(box[1]), float(box[2]), float(box[3]))
114
+ area = max(0.0, x2 - x1) * max(0.0, y2 - y1)
115
+ if area > best_area:
116
+ best_area = area
117
+ best = face
118
+ return best
119
+
120
+
121
+ def compute_id_photo_crop(
122
+ img_w: int,
123
+ img_h: int,
124
+ x1: float,
125
+ y1: float,
126
+ x2: float,
127
+ y2: float,
128
+ out_w: int,
129
+ out_h: int,
130
+ ) -> tuple[int, int, int, int] | None:
131
+ """按目标输出宽高比,围绕人脸得到 (left, top, right, bottom),用于 numpy 切片 [top:bottom, left:right]。"""
132
+ x1 = max(0.0, min(float(img_w), float(x1)))
133
+ y1 = max(0.0, min(float(img_h), float(y1)))
134
+ x2 = max(0.0, min(float(img_w), float(x2)))
135
+ y2 = max(0.0, min(float(img_h), float(y2)))
136
+ if x2 <= x1 or y2 <= y1:
137
+ return None
138
+
139
+ fh = y2 - y1
140
+ cx = (x1 + x2) * 0.5
141
+ aspect = out_w / float(out_h)
142
+
143
+ margin_top = 0.58 * fh
144
+ margin_bot = 1.08 * fh
145
+ top_ref = y1 - margin_top
146
+ bot_ref = y2 + margin_bot
147
+ ref_h = bot_ref - top_ref
148
+ ref_h = max(ref_h, fh * 2.15)
149
+ ref_h = min(float(img_h), ref_h)
150
+
151
+ crop_h = ref_h
152
+ crop_w = crop_h * aspect
153
+ if crop_w > img_w:
154
+ crop_w = float(img_w)
155
+ crop_h = crop_w / aspect
156
+ if crop_h > img_h:
157
+ crop_h = float(img_h)
158
+ crop_w = crop_h * aspect
159
+
160
+ left = cx - crop_w * 0.5
161
+ left = max(0.0, min(left, float(img_w) - crop_w))
162
+
163
+ # 头位略靠上:脸顶约在裁切框高度 30% 处
164
+ top = y1 - 0.30 * crop_h
165
+ top = max(0.0, min(top, float(img_h) - crop_h))
166
+
167
+ crop_w_i = int(round(crop_w))
168
+ crop_h_i = int(round(crop_h))
169
+ left_i = int(round(left))
170
+ top_i = int(round(top))
171
+ right_i = left_i + crop_w_i
172
+ bottom_i = top_i + crop_h_i
173
+
174
+ if right_i > img_w:
175
+ right_i = img_w
176
+ left_i = max(0, right_i - crop_w_i)
177
+ if bottom_i > img_h:
178
+ bottom_i = img_h
179
+ top_i = max(0, bottom_i - crop_h_i)
180
+
181
+ if right_i - left_i < 32 or bottom_i - top_i < 32:
182
+ return None
183
+ return left_i, top_i, right_i, bottom_i
184
+
185
+
186
+ def prepare_for_id_photo_edit(
187
+ image_ref: str,
188
+ api_key: str,
189
+ size_str: str,
190
+ *,
191
+ skip_face_crop: bool = False,
192
+ strict_face_gate: bool = False,
193
+ det_thr: float = 0.5,
194
+ detect_timeout: int = 30,
195
+ download_timeout: int = 120,
196
+ ) -> dict[str, Any]:
197
+ """
198
+ 返回:
199
+ edit_ref — 送入图改图解析器的路径或 URL/data URI
200
+ cleanup — 事后应删除的临时文件列表
201
+ face_crop — applied | skipped_disabled | skipped_no_face | failed_* | rejected_no_face
202
+ error — 可选:no_face(strict_face_gate 且零张达标人脸)
203
+ face_count — 可选:仅 rejected_no_face 时为 0;成功 applied 时可有 face_detected_count
204
+ face_detected_count — 可选:置信度达标的人脸数(applied 时≥1)
205
+ """
206
+ ref = image_ref.lstrip("@")
207
+ if skip_face_crop:
208
+ return {"edit_ref": ref, "cleanup": [], "face_crop": "skipped_disabled"}
209
+
210
+ try:
211
+ tw, th = parse_output_size(size_str)
212
+ except ValueError as e:
213
+ print(f"Warning: {e},将不进行人脸裁切。", file=sys.stderr)
214
+ return {"edit_ref": ref, "cleanup": [], "face_crop": "failed_bad_size"}
215
+
216
+ try:
217
+ local_path, material_cleanup = materialize_image(ref, api_key, download_timeout=download_timeout)
218
+ except Exception as e:
219
+ print(f"Warning: 无法落地输入以便人脸检测与裁切,改用原始输入: {e}", file=sys.stderr)
220
+ return {"edit_ref": ref, "cleanup": [], "face_crop": "failed_materialize"}
221
+
222
+ try:
223
+ api_result = detect_faces(local_path, api_key, timeout=detect_timeout)
224
+ except Exception as e:
225
+ print(f"Warning: 人脸检测接口失败,改用未裁切落地图: {e}", file=sys.stderr)
226
+ if material_cleanup:
227
+ return {"edit_ref": local_path, "cleanup": list(material_cleanup), "face_crop": "failed_detect"}
228
+ return {"edit_ref": local_path, "cleanup": [], "face_crop": "failed_detect"}
229
+
230
+ faces = api_result.get("output") or []
231
+ faces = [f for f in faces if float(f.get("det_score", 0) or 0) >= det_thr]
232
+
233
+ def _cleanup_material_only():
234
+ for p in material_cleanup:
235
+ try:
236
+ if p and os.path.isfile(p):
237
+ os.unlink(p)
238
+ except OSError:
239
+ pass
240
+
241
+ if strict_face_gate:
242
+ if len(faces) == 0:
243
+ _cleanup_material_only()
244
+ return {
245
+ "error": "no_face",
246
+ "edit_ref": ref,
247
+ "cleanup": [],
248
+ "face_crop": "rejected_no_face",
249
+ "face_count": 0,
250
+ }
251
+
252
+ if len(faces) > 1:
253
+ print(
254
+ f"Warning: 检出 {len(faces)} 张达标人脸,按检测框面积最大者裁切。",
255
+ file=sys.stderr,
256
+ )
257
+
258
+ face = get_largest_face(faces)
259
+
260
+ image = cv2.imread(local_path)
261
+ if image is None:
262
+ print("Warning: OpenCV 无法读取落地图,改用原始输入引用", file=sys.stderr)
263
+ for p in material_cleanup:
264
+ try:
265
+ if os.path.isfile(p):
266
+ os.unlink(p)
267
+ except OSError:
268
+ pass
269
+ return {"edit_ref": ref, "cleanup": [], "face_crop": "failed_read"}
270
+
271
+ ih, iw = image.shape[:2]
272
+
273
+ if not face:
274
+ print("Warning: 未检出足够置信度的人脸,整图送图改图", file=sys.stderr)
275
+ if material_cleanup:
276
+ return {"edit_ref": local_path, "cleanup": list(material_cleanup), "face_crop": "skipped_no_face"}
277
+ return {"edit_ref": local_path, "cleanup": [], "face_crop": "skipped_no_face"}
278
+
279
+ box = face.get("box") or []
280
+ if len(box) < 4:
281
+ if material_cleanup:
282
+ return {"edit_ref": local_path, "cleanup": list(material_cleanup), "face_crop": "skipped_no_face"}
283
+ return {"edit_ref": local_path, "cleanup": [], "face_crop": "skipped_no_face"}
284
+
285
+ rect = compute_id_photo_crop(iw, ih, float(box[0]), float(box[1]), float(box[2]), float(box[3]), tw, th)
286
+ if not rect:
287
+ print("Warning: 无法计算裁切框,使用整图送图改图", file=sys.stderr)
288
+ if material_cleanup:
289
+ return {"edit_ref": local_path, "cleanup": list(material_cleanup), "face_crop": "failed_crop_math"}
290
+ return {"edit_ref": local_path, "cleanup": [], "face_crop": "failed_crop_math"}
291
+
292
+ l, t, r, b = rect
293
+ cropped = image[t:b, l:r]
294
+ fd, out_path = tempfile.mkstemp(suffix=".jpg", prefix="id_photo_crop_")
295
+ os.close(fd)
296
+ ok = cv2.imwrite(out_path, cropped, [int(cv2.IMWRITE_JPEG_QUALITY), 95])
297
+ if not ok:
298
+ print("Warning: 裁切图写入失败,使用未裁切落地图", file=sys.stderr)
299
+ try:
300
+ os.unlink(out_path)
301
+ except OSError:
302
+ pass
303
+ if material_cleanup:
304
+ return {"edit_ref": local_path, "cleanup": list(material_cleanup), "face_crop": "failed_write"}
305
+ return {"edit_ref": local_path, "cleanup": [], "face_crop": "failed_write"}
306
+
307
+ cleanup_all = list(material_cleanup) + [out_path]
308
+ return {
309
+ "edit_ref": out_path,
310
+ "cleanup": cleanup_all,
311
+ "face_crop": "applied",
312
+ "face_detected_count": len(faces),
313
+ }
@@ -1,20 +1,20 @@
1
- {
2
- "name": "sophnet-image-edit",
3
- "version": "1.0.0",
4
- "types": [
5
- "builtin"
6
- ],
7
- "displayName": "",
8
- "description": "",
9
- "changelog": [
10
- {
11
- "version": "1.0.0",
12
- "date": "2026-04-09",
13
- "changes": [
14
- "初次提交"
15
- ]
16
- }
17
- ],
18
- "createdAt": "2026-04-09",
19
- "updatedAt": "2026-04-09"
20
- }
1
+ {
2
+ "name": "sophnet-image-edit",
3
+ "version": "1.0.0",
4
+ "types": [
5
+ "builtin"
6
+ ],
7
+ "displayName": "",
8
+ "description": "",
9
+ "changelog": [
10
+ {
11
+ "version": "1.0.0",
12
+ "date": "2026-04-09",
13
+ "changes": [
14
+ "初次提交"
15
+ ]
16
+ }
17
+ ],
18
+ "createdAt": "2026-04-09",
19
+ "updatedAt": "2026-04-09"
20
+ }