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.
- package/README.md +199 -187
- package/agents/ai-cs-admin/.config.json +51 -51
- package/agents/ai-cs-admin/AGENTS.md +293 -293
- package/agents/ai-cs-admin/HEARTBEAT.md +18 -18
- package/agents/ai-cs-qa/.config.json +47 -47
- package/agents/ai-cs-qa/BOOTSTRAP.md +22 -22
- package/agents/ai-cs-qa/scripts/setup_links.sh +39 -39
- package/agents/beauty/.config.json +17 -17
- package/agents/beauty/AGENTS.md +234 -234
- package/agents/beauty/BOOTSTRAP.md +55 -55
- package/agents/beauty/HEARTBEAT.md +5 -5
- package/agents/beauty/IDENTITY.md +5 -5
- package/agents/beauty/MEMORY.md +44 -44
- package/agents/beauty/SOUL.md +64 -64
- package/agents/beauty/TOOLS.md +160 -160
- package/agents/beauty/USER.md +114 -114
- package/agents/intern-admin/.config.json +60 -60
- package/agents/intern-admin/AGENTS.md +267 -267
- package/agents/intern-admin/BOOTSTRAP.md +21 -21
- package/agents/intern-admin/HEARTBEAT.md +3 -3
- package/agents/intern-admin/IDENTITY.md +6 -6
- package/agents/intern-admin/MEMORY.md +21 -21
- package/agents/intern-admin/SOUL.md +23 -23
- package/agents/intern-admin/TOOLS.md +93 -93
- package/agents/intern-admin/USER.md +16 -16
- package/agents/intern-admin/scripts/init_workspace.sh +27 -27
- package/agents/intern-qa/.config.json +46 -46
- package/agents/intern-qa/AGENTS.md +303 -303
- package/agents/intern-qa/BOOTSTRAP.md +16 -16
- package/agents/intern-qa/HEARTBEAT.md +3 -3
- package/agents/intern-qa/IDENTITY.md +6 -6
- package/agents/intern-qa/MEMORY.md +22 -22
- package/agents/intern-qa/SOUL.md +24 -24
- package/agents/intern-qa/TOOLS.md +24 -24
- package/agents/intern-qa/USER.md +27 -27
- package/agents/intern-qa/scripts/setup_links.sh +54 -54
- package/agents/parent-toddler/.config.json +37 -37
- package/agents/parent-toddler/AGENTS.md +51 -51
- package/agents/parent-toddler/BOOTSTRAP.md +55 -55
- package/agents/parent-toddler/HEARTBEAT.md +5 -5
- package/agents/parent-toddler/IDENTITY.md +5 -5
- package/agents/parent-toddler/MEMORY.md +22 -22
- package/agents/parent-toddler/SOUL.md +35 -35
- package/agents/parent-toddler/TOOLS.md +31 -31
- package/agents/parent-toddler/USER.md +44 -44
- package/agents/vip-admin/.config.json +51 -51
- package/agents/vip-admin/AGENTS.md +314 -314
- package/agents/vip-admin/BOOTSTRAP.md +21 -21
- package/agents/vip-admin/HEARTBEAT.md +19 -19
- package/agents/vip-admin/IDENTITY.md +6 -6
- package/agents/vip-admin/MEMORY.md +30 -30
- package/agents/vip-admin/SOUL.md +25 -25
- package/agents/vip-admin/TOOLS.md +108 -108
- package/agents/vip-admin/USER.md +31 -31
- package/agents/vip-qa/.config.json +58 -58
- package/agents/vip-qa/AGENTS.md +319 -319
- package/agents/vip-qa/BOOTSTRAP.md +73 -73
- package/agents/vip-qa/HEARTBEAT.md +23 -23
- package/agents/vip-qa/IDENTITY.md +7 -7
- package/agents/vip-qa/MEMORY.md +23 -23
- package/agents/vip-qa/SOUL.md +34 -34
- package/agents/vip-qa/TOOLS.md +41 -41
- package/agents/vip-qa/USER.md +16 -16
- package/agents/vip-qa/scripts/setup_links.sh +39 -39
- package/bin/sophhub.js +25 -25
- package/package.json +35 -33
- package/skills/agent-install/skill.json +34 -34
- package/skills/agent-install/src/SKILL.md +240 -240
- package/skills/agent-install/src/pyproject.toml +6 -6
- package/skills/agent-install/src/scripts/backup_agent.py +120 -120
- package/skills/agent-install/src/scripts/check_installed.py +479 -479
- package/skills/agent-install/src/scripts/common.py +568 -568
- package/skills/agent-install/src/scripts/copy_agent_files.py +59 -59
- package/skills/agent-install/src/scripts/list_agents.py +285 -285
- package/skills/agent-install/src/scripts/resolve_install_params.py +90 -90
- package/skills/agent-install/src/scripts/update_agent_md.py +76 -76
- package/skills/agent-install/src/scripts/update_openclaw.py +193 -193
- package/skills/agent-install/src/scripts/verify_download.py +148 -148
- package/skills/aippt/skill.json +20 -20
- package/skills/aippt/src/SKILL.md +235 -235
- package/skills/aippt/src/pyproject.toml +8 -8
- package/skills/aippt/src/scripts/auth.py +122 -122
- package/skills/aippt/src/scripts/ppt.py +361 -361
- package/skills/aippt/src/scripts/provider_docmee.py +299 -299
- package/skills/beauty-salon-inventory/skill.json +16 -16
- package/skills/beauty-salon-inventory/src/SKILL.md +69 -69
- package/skills/beauty-salon-inventory/src/scripts/init_salon_inventory.py +39 -39
- package/skills/beauty-salon-inventory/src/scripts/init_salon_inventory.sh +4 -4
- package/skills/beauty-salon-inventory/src/scripts/salon_inventory_cli.py +244 -244
- package/skills/beauty-salon-marketing/skill.json +10 -10
- package/skills/beauty-salon-marketing/src/SKILL.md +36 -36
- package/skills/beauty-salon-marketing/src/playbooks/beauty-salon-festival.md +19 -19
- package/skills/beauty-salon-marketing/src/playbooks/beauty-salon-segment.md +18 -18
- package/skills/beauty-salon-marketing/src/scripts/beauty_marketing_cli.py +99 -99
- package/skills/beauty-salon-marketing/src/scripts/member_segment.py +114 -114
- package/skills/beauty-salon-member-appointment/skill.json +10 -10
- package/skills/beauty-salon-member-appointment/src/SKILL.md +36 -36
- package/skills/beauty-salon-member-appointment/src/pyproject.toml +9 -9
- package/skills/beauty-salon-member-appointment/src/scripts/run_e2e_smoke.py +160 -160
- package/skills/beauty-salon-member-appointment/src/src/member_appt_cli/__init__.py +1 -1
- package/skills/beauty-salon-member-appointment/src/src/member_appt_cli/__main__.py +4 -4
- package/skills/beauty-salon-member-appointment/src/src/member_appt_cli/cli.py +921 -921
- package/skills/beauty-salon-member-appointment/src/src/member_appt_cli/db.py +30 -30
- package/skills/beauty-salon-membership/skill.json +20 -20
- package/skills/beauty-salon-membership/src/SKILL.md +67 -67
- package/skills/beauty-salon-product-service/skill.json +12 -12
- package/skills/beauty-salon-product-service/src/SKILL.md +42 -42
- package/skills/beauty-salon-product-service/src/pyproject.toml +9 -9
- package/skills/beauty-salon-product-service/src/src/product_service_cli/__init__.py +1 -1
- package/skills/beauty-salon-product-service/src/src/product_service_cli/__main__.py +4 -4
- package/skills/beauty-salon-product-service/src/src/product_service_cli/cli.py +329 -329
- package/skills/beauty-salon-product-service/src/src/product_service_cli/db.py +29 -29
- package/skills/beauty-salon-staff/skill.json +10 -10
- package/skills/beauty-salon-staff/src/SKILL.md +37 -37
- package/skills/beauty-salon-staff/src/pyproject.toml +9 -9
- package/skills/beauty-salon-staff/src/src/staff_cli/__init__.py +1 -1
- package/skills/beauty-salon-staff/src/src/staff_cli/__main__.py +4 -4
- package/skills/beauty-salon-staff/src/src/staff_cli/cli.py +479 -479
- package/skills/beauty-salon-staff/src/src/staff_cli/db.py +28 -28
- package/skills/beauty-salon-suite/skill.json +13 -13
- package/skills/beauty-salon-suite/src/SKILL.md +18 -18
- package/skills/beauty-salon-suite/src/beauty_db/__init__.py +2 -2
- package/skills/beauty-salon-suite/src/beauty_db/db.py +249 -249
- package/skills/beauty-salon-traffic/skill.json +20 -20
- package/skills/beauty-salon-traffic/src/SKILL.md +84 -84
- package/skills/bing-image-search/skill.json +20 -20
- package/skills/bing-image-search/src/SKILL.md +105 -105
- package/skills/bot-api-status/skill.json +44 -44
- package/skills/bot-api-status/src/SKILL.md +99 -99
- package/skills/bot-api-status/src/pyproject.toml +5 -5
- package/skills/bot-api-status/src/scripts/secret.py +496 -496
- package/skills/bot-secret/skill.json +35 -35
- package/skills/bot-secret/src/SKILL.md +51 -51
- package/skills/bot-secret/src/pyproject.toml +5 -5
- package/skills/bot-secret/src/scripts/secret.py +120 -120
- package/skills/cake-flower-holiday-campaign/skill.json +20 -20
- package/skills/cake-flower-holiday-campaign/src/SKILL.md +68 -68
- package/skills/cake-flower-order-sop/skill.json +20 -20
- package/skills/cake-flower-order-sop/src/SKILL.md +65 -65
- package/skills/claw-agent-get-send/skill.json +32 -32
- package/skills/claw-agent-get-send/src/SKILL.md +43 -43
- package/skills/claw-agent-get-send/src/pyproject.toml +5 -5
- package/skills/claw-agent-get-send/src/scripts/appia_claw.py +379 -379
- package/skills/compact-context/skill.json +20 -20
- package/skills/compact-context/src/SKILL.md +133 -133
- package/skills/compact-context/src/scripts/check.sh +381 -381
- package/skills/compact-context/src/scripts/set-keep-recent.mjs +1337 -1337
- package/skills/compact-context/src/scripts/setup.sh +96 -96
- package/skills/consensus/skill.json +20 -20
- package/skills/consensus/src/SKILL.md +93 -93
- package/skills/deepwiki/skill.json +20 -20
- package/skills/deepwiki/src/SKILL.md +45 -45
- package/skills/deepwiki/src/_meta.json +5 -5
- package/skills/deepwiki/src/scripts/deepwiki.js +135 -135
- package/skills/didi-ride/skill.json +20 -20
- package/skills/didi-ride/src/SKILL.md +309 -309
- package/skills/didi-ride/src/_meta.json +5 -5
- package/skills/didi-ride/src/assets/PREFERENCE.md +58 -58
- package/skills/didi-ride/src/package.json +15 -15
- package/skills/didi-ride/src/references/api_references.md +171 -171
- package/skills/didi-ride/src/references/error_handling.md +68 -68
- package/skills/didi-ride/src/references/setup.md +73 -73
- package/skills/didi-ride/src/references/workflow.md +150 -150
- package/skills/feishu-bitable/skill.json +20 -20
- package/skills/feishu-bitable/src/CHECKLIST.md +149 -149
- package/skills/feishu-bitable/src/README.md +177 -177
- package/skills/feishu-bitable/src/SKILL.md +113 -113
- package/skills/feishu-bitable/src/_meta.json +5 -5
- package/skills/feishu-bitable/src/api.js +380 -380
- package/skills/feishu-bitable/src/bin/cli.js +283 -283
- package/skills/feishu-bitable/src/description.md +142 -142
- package/skills/feishu-bitable/src/examples/create-records.json +51 -51
- package/skills/feishu-bitable/src/examples/create-table.json +63 -63
- package/skills/feishu-bitable/src/package-lock.json +324 -324
- package/skills/feishu-bitable/src/package.json +32 -32
- package/skills/feishu-bitable/src/publish-config.json +13 -13
- package/skills/feishu-bitable/src/test-simple.js +60 -60
- package/skills/feishu-bitable/src/utils.js +260 -260
- package/skills/feishu-notes-assistant-universal/skill.json +20 -20
- package/skills/feishu-notes-assistant-universal/src/README.md +55 -55
- package/skills/feishu-notes-assistant-universal/src/SKILL.md +159 -159
- package/skills/feishu-notes-assistant-universal/src/scripts/_resolve_lark_cli.py +58 -58
- package/skills/feishu-notes-assistant-universal/src/scripts/openclaw_meeting_minutes.py +462 -462
- package/skills/feishu-notes-assistant-universal/src/scripts/openclaw_notes_crud.py +547 -547
- package/skills/feishu-notes-assistant-universal/src/scripts/openclaw_notes_crud_test.py +181 -181
- package/skills/feishu-notes-assistant-universal/src/scripts/run_meeting_minutes.py +80 -80
- package/skills/feishu-notes-assistant-universal/src/scripts/run_meeting_minutes.sh +5 -5
- package/skills/feishu-notes-assistant-universal/src/scripts/run_note_crud.py +32 -32
- package/skills/feishu-notes-assistant-universal/src/scripts/run_note_crud.sh +5 -5
- package/skills/flight-booking/skill.json +36 -36
- package/skills/flight-booking/src/SKILL.md +288 -288
- package/skills/flight-booking/src/scripts/flight_booking.py +1237 -1237
- package/skills/flyai/skill.json +20 -20
- package/skills/flyai/src/SKILL.md +119 -119
- package/skills/flyai/src/references/fliggy-fast-search.md +53 -53
- package/skills/flyai/src/references/search-flight.md +89 -89
- package/skills/flyai/src/references/search-hotels.md +57 -57
- package/skills/flyai/src/references/search-poi.md +48 -48
- package/skills/google-maps/skill.json +20 -20
- package/skills/google-maps/src/SKILL.md +237 -237
- package/skills/google-maps/src/_meta.json +5 -5
- package/skills/google-maps/src/lib/map_helper.py +912 -912
- package/skills/image-classify/skill.json +42 -42
- package/skills/image-classify/src/SKILL.md +368 -368
- package/skills/image-classify/src/references/config.json +4 -4
- package/skills/image-classify/src/scripts/face_search.py +1276 -1276
- package/skills/image-description/skill.json +34 -34
- package/skills/image-description/src/SKILL.md +33 -33
- package/skills/image-description/src/pyproject.toml +8 -8
- package/skills/image-description/src/scripts/ana_image.py +112 -112
- package/skills/image-identify-world/skill.json +20 -20
- package/skills/image-identify-world/src/SKILL.md +40 -40
- package/skills/image-identify-world/src/pyproject.toml +8 -8
- package/skills/image-identify-world/src/scripts/identify_world.py +115 -115
- package/skills/insurance-policy-review/skill.json +27 -27
- package/skills/insurance-policy-review/src/SKILL.md +75 -75
- package/skills/insurance-sales-playbook/skill.json +20 -20
- package/skills/insurance-sales-playbook/src/SKILL.md +58 -58
- package/skills/inventory-management/skill.json +20 -20
- package/skills/inventory-management/src/SKILL.md +241 -241
- package/skills/inventory-management/src/scripts/inventory.py +1844 -1844
- package/skills/large-task-router/skill.json +20 -20
- package/skills/large-task-router/src/SKILL.md +79 -79
- package/skills/large-task-router/src/templates/plan.md +74 -74
- package/skills/lawding-contract-review/skill.json +20 -20
- package/skills/lawding-contract-review/src/SKILL.md +284 -284
- package/skills/lawding-contract-review/src/references/legal-language-library.md +1385 -1385
- package/skills/lawding-contract-review/src/scripts/build_reminders.py +471 -471
- package/skills/lawding-contract-review/src/scripts/register_contract_cron.py +457 -457
- package/skills/md2pdf-converter/skill.json +20 -20
- package/skills/md2pdf-converter/src/SKILL.md +244 -244
- package/skills/md2pdf-converter/src/_meta.json +5 -5
- package/skills/md2pdf-converter/src/scripts/generate_emoji_mapping.py +74 -74
- package/skills/md2pdf-converter/src/scripts/md2pdf-local.sh +291 -291
- package/skills/notes-hub-assistant/skill.json +20 -20
- package/skills/notes-hub-assistant/src/SKILL.md +233 -233
- package/skills/notes-hub-assistant/src/scripts/_resolve_lark_cli.py +48 -48
- package/skills/notes-hub-assistant/src/scripts/openclaw_meeting_minutes.py +473 -473
- package/skills/notes-hub-assistant/src/scripts/openclaw_notes_crud.py +596 -596
- package/skills/notes-hub-assistant/src/scripts/openclaw_wolai_notes_crud.py +364 -364
- package/skills/notes-hub-assistant/src/scripts/run_meeting_minutes.py +79 -79
- package/skills/notes-hub-assistant/src/scripts/run_note_crud.py +37 -37
- package/skills/notes-hub-assistant/src/scripts/run_notionbot.py +36 -36
- package/skills/notes-hub-assistant/src/scripts/run_wolai_note_crud.py +27 -27
- package/skills/schedule-reminder/skill.json +20 -20
- package/skills/schedule-reminder/src/SKILL.md +619 -619
- package/skills/schedule-reminder/src/schedule_template.md +68 -68
- package/skills/schedule-reminder/src/scripts/append_event.py +204 -204
- package/skills/schedule-reminder/src/scripts/create_reminders.sh +163 -163
- package/skills/schedule-reminder/src/scripts/daily_activate.sh +175 -175
- package/skills/schedule-reminder/src/scripts/parse_schedule.py +704 -704
- package/skills/schedule-reminder/src/scripts/setup.sh +242 -242
- package/skills/schedule-reminder/src//347/224/250/346/210/267/346/214/207/345/215/227.md +311 -311
- package/skills/sessions-analysis/skill.json +34 -34
- package/skills/sessions-analysis/src/SKILL.md +81 -81
- package/skills/sessions-analysis/src/pyproject.toml +5 -5
- package/skills/sessions-analysis/src/scripts/ana_logs.py +205 -205
- package/skills/share-skill/skill.json +20 -20
- package/skills/share-skill/src/SKILL.md +261 -261
- package/skills/share-skill/src/scripts/share_skill_to_friend.py +1031 -1031
- package/skills/skill-creator/skill.json +20 -20
- package/skills/skill-creator/src/SKILL.md +370 -370
- package/skills/skill-creator/src/license.txt +202 -202
- package/skills/skill-creator/src/scripts/init_skill.py +378 -378
- package/skills/skill-creator/src/scripts/package_skill.py +111 -111
- package/skills/skill-creator/src/scripts/quick_validate.py +101 -101
- package/skills/skillhub/skill.json +27 -27
- package/skills/skillhub/src/SKILL.md +121 -121
- package/skills/sophnet-age-appearance/skill.json +20 -20
- package/skills/sophnet-age-appearance/src/SKILL.md +83 -83
- package/skills/sophnet-age-appearance/src/pyproject.toml +10 -10
- package/skills/sophnet-age-appearance/src/scripts/age_appearance.py +395 -395
- package/skills/sophnet-age-appearance/src/scripts/age_face_crop.py +313 -313
- package/skills/sophnet-bot-client/skill.json +20 -20
- package/skills/sophnet-bot-client/src/SKILL.md +255 -255
- package/skills/sophnet-bot-client/src/pyproject.toml +13 -13
- package/skills/sophnet-bot-client/src/scripts/bot_client_proxy.py +165 -165
- package/skills/sophnet-bot-client/src/scripts/bot_client_safe.sh +29 -29
- package/skills/sophnet-bot-client/src/scripts/bot_client_setup.py +502 -502
- package/skills/sophnet-bot-client/src/tests/test_bot_client_proxy.py +255 -255
- package/skills/sophnet-bot-client/src/tests/test_bot_client_setup.py +679 -679
- package/skills/sophnet-bot-client/src/uv.lock +8 -8
- package/skills/sophnet-customer-management/skill.json +20 -20
- package/skills/sophnet-customer-management/src/SKILL.md +270 -270
- package/skills/sophnet-customer-management/src/pyproject.toml +15 -15
- package/skills/sophnet-customer-management/src/src/customer_mgmt_cli/__init__.py +2 -2
- package/skills/sophnet-customer-management/src/src/customer_mgmt_cli/__main__.py +5 -5
- package/skills/sophnet-customer-management/src/src/customer_mgmt_cli/cli.py +67 -67
- package/skills/sophnet-customer-management/src/src/customer_mgmt_cli/commands/__init__.py +2 -2
- package/skills/sophnet-customer-management/src/src/customer_mgmt_cli/commands/customer.py +60 -60
- package/skills/sophnet-customer-management/src/src/customer_mgmt_cli/commands/export_file.py +18 -18
- package/skills/sophnet-customer-management/src/src/customer_mgmt_cli/commands/import_file.py +15 -15
- package/skills/sophnet-customer-management/src/src/customer_mgmt_cli/commands/reminder.py +26 -26
- package/skills/sophnet-customer-management/src/src/customer_mgmt_cli/commands/schema.py +28 -28
- package/skills/sophnet-customer-management/src/src/customer_mgmt_cli/config.py +54 -54
- package/skills/sophnet-customer-management/src/src/customer_mgmt_core/__init__.py +2 -2
- package/skills/sophnet-customer-management/src/src/customer_mgmt_core/exporter.py +85 -85
- package/skills/sophnet-customer-management/src/src/customer_mgmt_core/models.py +84 -84
- package/skills/sophnet-customer-management/src/src/customer_mgmt_core/normalizer.py +144 -144
- package/skills/sophnet-customer-management/src/src/customer_mgmt_core/parser.py +241 -241
- package/skills/sophnet-customer-management/src/src/customer_mgmt_core/query.py +109 -109
- package/skills/sophnet-customer-management/src/src/customer_mgmt_core/reminder.py +121 -121
- package/skills/sophnet-customer-management/src/src/customer_mgmt_core/repository.py +397 -397
- package/skills/sophnet-customer-management/src/src/customer_mgmt_core/schema.py +106 -106
- package/skills/sophnet-customer-management/src/src/customer_mgmt_core/service.py +565 -565
- package/skills/sophnet-customer-management/src/uv.lock +48 -48
- package/skills/sophnet-customized-marketing/skill.json +28 -28
- package/skills/sophnet-customized-marketing/src/SKILL.md +144 -144
- package/skills/sophnet-customized-marketing/src/playbooks/campaign-planning.md +187 -187
- package/skills/sophnet-customized-marketing/src/playbooks/content-generation.md +124 -124
- package/skills/sophnet-customized-marketing/src/playbooks/marketing-calendar.md +59 -59
- package/skills/sophnet-customized-marketing/src/playbooks/multi-channel-bundle.md +94 -94
- package/skills/sophnet-customized-marketing/src/playbooks/poster-generation.md +182 -182
- package/skills/sophnet-customized-marketing/src/playbooks/style-profile-workflow.md +103 -103
- package/skills/sophnet-customized-marketing/src/pyproject.toml +8 -8
- package/skills/sophnet-customized-marketing/src/references/campaign-mechanics.md +168 -168
- package/skills/sophnet-customized-marketing/src/references/content-safety.md +26 -26
- package/skills/sophnet-customized-marketing/src/references/marketing-date-checklist.md +99 -99
- package/skills/sophnet-customized-marketing/src/references/platform-writing-guidelines.md +88 -88
- package/skills/sophnet-customized-marketing/src/references/quality-checklist.md +44 -44
- package/skills/sophnet-customized-marketing/src/scripts/generate_poster.py +572 -572
- package/skills/sophnet-customized-marketing/src/scripts/style_profile.py +215 -215
- package/skills/sophnet-dailynews/skill.json +20 -20
- package/skills/sophnet-dailynews/src/SKILL.md +179 -179
- package/skills/sophnet-dailynews/src/cache.json +150 -150
- package/skills/sophnet-dailynews/src/sources.json +230 -230
- package/skills/sophnet-docx/skill.json +20 -20
- package/skills/sophnet-docx/src/SKILL.md +463 -463
- package/skills/sophnet-docx/src/package-lock.json +208 -208
- package/skills/sophnet-docx/src/package.json +16 -16
- package/skills/sophnet-docx/src/pyproject.toml +11 -11
- package/skills/sophnet-docx/src/scripts/__init__.py +1 -1
- package/skills/sophnet-docx/src/scripts/accept_changes.py +135 -135
- package/skills/sophnet-docx/src/scripts/comment.py +318 -318
- package/skills/sophnet-docx/src/scripts/ensure_uv_env.sh +68 -68
- package/skills/sophnet-docx/src/scripts/office/helpers/merge_runs.py +199 -199
- package/skills/sophnet-docx/src/scripts/office/helpers/simplify_redlines.py +197 -197
- package/skills/sophnet-docx/src/scripts/office/pack.py +159 -159
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -1499
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -146
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -1085
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -11
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -3081
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -23
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -185
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -287
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -1676
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -28
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -144
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -174
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -25
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -18
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -59
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -56
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -195
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -582
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -25
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -4439
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -570
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -509
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -12
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -108
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -96
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -3646
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -116
- package/skills/sophnet-docx/src/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -42
- package/skills/sophnet-docx/src/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -50
- package/skills/sophnet-docx/src/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -49
- package/skills/sophnet-docx/src/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -33
- package/skills/sophnet-docx/src/scripts/office/schemas/mce/mc.xsd +75 -75
- package/skills/sophnet-docx/src/scripts/office/schemas/microsoft/wml-2010.xsd +560 -560
- package/skills/sophnet-docx/src/scripts/office/schemas/microsoft/wml-2012.xsd +67 -67
- package/skills/sophnet-docx/src/scripts/office/schemas/microsoft/wml-2018.xsd +14 -14
- package/skills/sophnet-docx/src/scripts/office/schemas/microsoft/wml-cex-2018.xsd +20 -20
- package/skills/sophnet-docx/src/scripts/office/schemas/microsoft/wml-cid-2016.xsd +13 -13
- package/skills/sophnet-docx/src/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -4
- package/skills/sophnet-docx/src/scripts/office/schemas/microsoft/wml-symex-2015.xsd +8 -8
- package/skills/sophnet-docx/src/scripts/office/soffice.py +183 -183
- package/skills/sophnet-docx/src/scripts/office/unpack.py +132 -132
- package/skills/sophnet-docx/src/scripts/office/validate.py +111 -111
- package/skills/sophnet-docx/src/scripts/office/validators/__init__.py +15 -15
- package/skills/sophnet-docx/src/scripts/office/validators/base.py +847 -847
- package/skills/sophnet-docx/src/scripts/office/validators/docx.py +446 -446
- package/skills/sophnet-docx/src/scripts/office/validators/pptx.py +275 -275
- package/skills/sophnet-docx/src/scripts/office/validators/redlining.py +247 -247
- package/skills/sophnet-docx/src/scripts/templates/comments.xml +3 -3
- package/skills/sophnet-docx/src/scripts/templates/commentsExtended.xml +3 -3
- package/skills/sophnet-docx/src/scripts/templates/commentsExtensible.xml +3 -3
- package/skills/sophnet-docx/src/scripts/templates/commentsIds.xml +3 -3
- package/skills/sophnet-docx/src/scripts/templates/people.xml +3 -3
- package/skills/sophnet-docx/src/scripts/upload_file.sh +96 -96
- package/skills/sophnet-docx/src/uv.lock +320 -320
- package/skills/sophnet-face-search/skill.json +20 -20
- package/skills/sophnet-face-search/src/SKILL.md +115 -115
- package/skills/sophnet-face-search/src/pyproject.toml +11 -11
- package/skills/sophnet-face-search/src/scripts/face_search.py +335 -335
- package/skills/sophnet-face-search/src/uv.lock +508 -508
- package/skills/sophnet-id-photo/skill.json +20 -20
- package/skills/sophnet-id-photo/src/SKILL.md +107 -107
- package/skills/sophnet-id-photo/src/pyproject.toml +10 -10
- package/skills/sophnet-id-photo/src/scripts/id_photo.py +540 -540
- package/skills/sophnet-id-photo/src/scripts/id_photo_compliance.py +215 -215
- package/skills/sophnet-id-photo/src/scripts/id_photo_face_crop.py +313 -313
- package/skills/sophnet-image-edit/skill.json +20 -20
- package/skills/sophnet-image-edit/src/SKILL.md +140 -140
- package/skills/sophnet-image-edit/src/pyproject.toml +9 -9
- package/skills/sophnet-image-edit/src/scripts/edit_and_preview.sh +68 -68
- package/skills/sophnet-image-edit/src/scripts/edit_image.py +279 -279
- package/skills/sophnet-image-edit/src/uv.lock +234 -234
- package/skills/sophnet-image-generate/skill.json +20 -20
- package/skills/sophnet-image-generate/src/SKILL.md +62 -62
- package/skills/sophnet-image-generate/src/pyproject.toml +9 -9
- package/skills/sophnet-image-generate/src/scripts/generate_image.py +156 -156
- package/skills/sophnet-image-generate/src/uv.lock +234 -234
- package/skills/sophnet-image-ocr/skill.json +20 -20
- package/skills/sophnet-image-ocr/src/SKILL.md +167 -167
- package/skills/sophnet-image-ocr/src/pyproject.toml +13 -13
- package/skills/sophnet-image-ocr/src/scripts/ocr.py +225 -225
- package/skills/sophnet-image-ocr/src/uv.lock +234 -234
- package/skills/sophnet-infinite-talk/skill.json +20 -20
- package/skills/sophnet-infinite-talk/src/SKILL.md +140 -140
- package/skills/sophnet-infinite-talk/src/pyproject.toml +9 -9
- package/skills/sophnet-infinite-talk/src/scripts/gen.py +172 -172
- package/skills/sophnet-oss/skill.json +27 -27
- package/skills/sophnet-oss/src/SKILL.md +118 -118
- package/skills/sophnet-oss/src/pyproject.toml +8 -8
- package/skills/sophnet-oss/src/scripts/upload_file.py +43 -43
- package/skills/sophnet-pdf/skill.json +20 -20
- package/skills/sophnet-pdf/src/SKILL.md +413 -413
- package/skills/sophnet-pdf/src/forms.md +297 -297
- package/skills/sophnet-pdf/src/pyproject.toml +14 -14
- package/skills/sophnet-pdf/src/reference.md +611 -611
- package/skills/sophnet-pdf/src/scripts/check_bounding_boxes.py +65 -65
- package/skills/sophnet-pdf/src/scripts/check_fillable_fields.py +11 -11
- package/skills/sophnet-pdf/src/scripts/convert_pdf_to_images.py +33 -33
- package/skills/sophnet-pdf/src/scripts/create_validation_image.py +37 -37
- package/skills/sophnet-pdf/src/scripts/enhance_tutorial.py +557 -557
- package/skills/sophnet-pdf/src/scripts/ensure_uv_env.sh +68 -68
- package/skills/sophnet-pdf/src/scripts/extract_form_field_info.py +122 -122
- package/skills/sophnet-pdf/src/scripts/extract_form_structure.py +115 -115
- package/skills/sophnet-pdf/src/scripts/extract_pdf_content.py +34 -34
- package/skills/sophnet-pdf/src/scripts/fill_fillable_fields.py +98 -98
- package/skills/sophnet-pdf/src/scripts/fill_pdf_form_with_annotations.py +107 -107
- package/skills/sophnet-pdf/src/scripts/upload_file.sh +88 -88
- package/skills/sophnet-pdf/src/uv.lock +537 -537
- package/skills/sophnet-qa-install/skill.json +27 -27
- package/skills/sophnet-qa-install/src/SKILL.md +210 -210
- package/skills/sophnet-qa-install/src/pyproject.toml +6 -6
- package/skills/sophnet-qa-install/src/scripts/backup_md.py +35 -35
- package/skills/sophnet-qa-install/src/scripts/check_installed.py +143 -143
- package/skills/sophnet-qa-install/src/scripts/update_config.py +142 -142
- package/skills/sophnet-qa-install/src/scripts/update_md.py +73 -73
- package/skills/sophnet-schedule/skill.json +20 -20
- package/skills/sophnet-schedule/src/ARCHITECTURE.md +321 -321
- package/skills/sophnet-schedule/src/IMPROVEMENTS.md +145 -145
- package/skills/sophnet-schedule/src/SKILL.md +1050 -1050
- package/skills/sophnet-schedule/src/_meta.json +6 -6
- package/skills/sophnet-schedule/src/api/models.py +245 -245
- package/skills/sophnet-schedule/src/apps/add_event.py +237 -237
- package/skills/sophnet-schedule/src/apps/check_reminders.py +112 -112
- package/skills/sophnet-schedule/src/apps/check_roc.py +246 -246
- package/skills/sophnet-schedule/src/apps/generate_daily_plan.py +342 -342
- package/skills/sophnet-schedule/src/apps/import_events.py +216 -216
- package/skills/sophnet-schedule/src/apps/monitor_calendar_changes.py +140 -140
- package/skills/sophnet-schedule/src/apps/register_tasks.py +169 -169
- package/skills/sophnet-schedule/src/apps/sync_roc_to_gcal.py +174 -174
- package/skills/sophnet-schedule/src/compat.py +66 -66
- package/skills/sophnet-schedule/src/config/reminder_rules.yaml +96 -96
- package/skills/sophnet-schedule/src/config/roc_events.yaml +44 -44
- package/skills/sophnet-schedule/src/config/settings.py +133 -133
- package/skills/sophnet-schedule/src/config/task_registry.yaml +92 -92
- package/skills/sophnet-schedule/src/docs/FRONTEND_INTEGRATION_GUIDE.md +437 -437
- package/skills/sophnet-schedule/src/gcal/client.py +374 -374
- package/skills/sophnet-schedule/src/gcal/models.py +91 -91
- package/skills/sophnet-schedule/src/requirements.txt +6 -6
- package/skills/sophnet-schedule/src/scripts/setup_gcal_token.py +85 -85
- package/skills/sophnet-schedule/src/server.py +669 -669
- package/skills/sophnet-schedule/src/services/calendar_backend.py +139 -139
- package/skills/sophnet-schedule/src/services/conflict_detector.py +96 -96
- package/skills/sophnet-schedule/src/services/datetime_utils.py +117 -117
- package/skills/sophnet-schedule/src/services/event_classifier.py +100 -100
- package/skills/sophnet-schedule/src/services/event_diff.py +160 -160
- package/skills/sophnet-schedule/src/services/google_integration.py +500 -500
- package/skills/sophnet-schedule/src/services/job_store.py +100 -100
- package/skills/sophnet-schedule/src/services/local_event_store.py +266 -266
- package/skills/sophnet-schedule/src/services/reminder_planner.py +116 -116
- package/skills/sophnet-schedule/src/services/runtime_utils.py +31 -31
- package/skills/sophnet-schedule/src/services/table_parser.py +286 -286
- package/skills/sophnet-schedule/src/services/task_builder.py +167 -167
- package/skills/sophnet-schedule/src/services/time_window.py +72 -72
- package/skills/sophnet-sticker-edit/skill.json +27 -27
- package/skills/sophnet-sticker-edit/src/SKILL.md +80 -80
- package/skills/sophnet-sticker-edit/src/pyproject.toml +9 -9
- package/skills/sophnet-sticker-edit/src/scripts/edit_sticker_image.py +403 -403
- package/skills/sophnet-stock/skill.json +20 -20
- package/skills/sophnet-stock/src/App-Plan.md +442 -442
- package/skills/sophnet-stock/src/README.md +214 -214
- package/skills/sophnet-stock/src/SKILL.md +236 -236
- package/skills/sophnet-stock/src/TODO.md +394 -394
- package/skills/sophnet-stock/src/_meta.json +5 -5
- package/skills/sophnet-stock/src/docs/ARCHITECTURE.md +408 -408
- package/skills/sophnet-stock/src/docs/CONCEPT.md +233 -233
- package/skills/sophnet-stock/src/docs/HOT_SCANNER.md +288 -288
- package/skills/sophnet-stock/src/docs/README.md +95 -95
- package/skills/sophnet-stock/src/docs/USAGE.md +465 -465
- package/skills/sophnet-stock/src/scripts/analyze_stock.py +2565 -2565
- package/skills/sophnet-stock/src/scripts/dividends.py +365 -365
- package/skills/sophnet-stock/src/scripts/hot_scanner.py +582 -582
- package/skills/sophnet-stock/src/scripts/portfolio.py +548 -548
- package/skills/sophnet-stock/src/scripts/rumor_scanner.py +342 -342
- package/skills/sophnet-stock/src/scripts/test_stock_analysis.py +409 -409
- package/skills/sophnet-stock/src/scripts/watchlist.py +336 -336
- package/skills/sophnet-training-install/skill.json +27 -27
- package/skills/sophnet-training-install/src/SKILL.md +211 -211
- package/skills/sophnet-training-install/src/pyproject.toml +6 -6
- package/skills/sophnet-training-install/src/scripts/backup_md.py +35 -35
- package/skills/sophnet-training-install/src/scripts/check_installed.py +144 -144
- package/skills/sophnet-training-install/src/scripts/update_config.py +142 -142
- package/skills/sophnet-training-install/src/scripts/update_md.py +73 -73
- package/skills/sophnet-tts/skill.json +20 -20
- package/skills/sophnet-tts/src/SKILL.md +79 -79
- package/skills/sophnet-tts/src/pyproject.toml +9 -9
- package/skills/sophnet-tts/src/scripts/gen_tts.py +130 -130
- package/skills/sophnet-video-generate/skill.json +37 -37
- package/skills/sophnet-video-generate/src/SKILL.md +117 -117
- package/skills/sophnet-video-generate/src/scripts/gen_video.py +321 -321
- package/skills/sophnet-xlsx/skill.json +20 -20
- package/skills/sophnet-xlsx/src/SKILL.md +399 -399
- package/skills/sophnet-xlsx/src/pyproject.toml +11 -11
- package/skills/sophnet-xlsx/src/scripts/ensure_uv_env.sh +68 -68
- package/skills/sophnet-xlsx/src/scripts/office/helpers/merge_runs.py +199 -199
- package/skills/sophnet-xlsx/src/scripts/office/helpers/simplify_redlines.py +197 -197
- package/skills/sophnet-xlsx/src/scripts/office/pack.py +159 -159
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -1499
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -146
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -1085
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -11
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -3081
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -23
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -185
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -287
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -1676
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -28
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -144
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -174
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -25
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -18
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -59
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -56
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -195
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -582
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -25
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -4439
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -570
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -509
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -12
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -108
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -96
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -3646
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -116
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -42
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -50
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -49
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -33
- package/skills/sophnet-xlsx/src/scripts/office/schemas/mce/mc.xsd +75 -75
- package/skills/sophnet-xlsx/src/scripts/office/schemas/microsoft/wml-2010.xsd +560 -560
- package/skills/sophnet-xlsx/src/scripts/office/schemas/microsoft/wml-2012.xsd +67 -67
- package/skills/sophnet-xlsx/src/scripts/office/schemas/microsoft/wml-2018.xsd +14 -14
- package/skills/sophnet-xlsx/src/scripts/office/schemas/microsoft/wml-cex-2018.xsd +20 -20
- package/skills/sophnet-xlsx/src/scripts/office/schemas/microsoft/wml-cid-2016.xsd +13 -13
- package/skills/sophnet-xlsx/src/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -4
- package/skills/sophnet-xlsx/src/scripts/office/schemas/microsoft/wml-symex-2015.xsd +8 -8
- package/skills/sophnet-xlsx/src/scripts/office/soffice.py +183 -183
- package/skills/sophnet-xlsx/src/scripts/office/unpack.py +132 -132
- package/skills/sophnet-xlsx/src/scripts/office/validate.py +111 -111
- package/skills/sophnet-xlsx/src/scripts/office/validators/__init__.py +15 -15
- package/skills/sophnet-xlsx/src/scripts/office/validators/base.py +847 -847
- package/skills/sophnet-xlsx/src/scripts/office/validators/docx.py +446 -446
- package/skills/sophnet-xlsx/src/scripts/office/validators/pptx.py +275 -275
- package/skills/sophnet-xlsx/src/scripts/office/validators/redlining.py +247 -247
- package/skills/sophnet-xlsx/src/scripts/recalc.py +184 -184
- package/skills/sophnet-xlsx/src/scripts/upload_file.sh +96 -96
- package/skills/sophnet-xlsx/src/uv.lock +319 -319
- package/skills/ui-ux-pro-max/skill.json +20 -20
- package/skills/ui-ux-pro-max/src/SKILL.md +377 -377
- package/skills/ui-ux-pro-max/src/data/icons.csv +101 -101
- package/skills/ui-ux-pro-max/src/data/react-performance.csv +45 -45
- package/skills/ui-ux-pro-max/src/data/stacks/astro.csv +54 -54
- package/skills/ui-ux-pro-max/src/data/stacks/jetpack-compose.csv +53 -53
- package/skills/ui-ux-pro-max/src/data/stacks/nuxt-ui.csv +51 -51
- package/skills/ui-ux-pro-max/src/data/stacks/nuxtjs.csv +59 -59
- package/skills/ui-ux-pro-max/src/data/stacks/shadcn.csv +61 -61
- package/skills/ui-ux-pro-max/src/data/typography.csv +57 -57
- package/skills/ui-ux-pro-max/src/data/ui-reasoning.csv +101 -101
- package/skills/ui-ux-pro-max/src/data/web-interface.csv +31 -31
- package/skills/ui-ux-pro-max/src/scripts/core.py +253 -253
- package/skills/ui-ux-pro-max/src/scripts/design_system.py +1067 -1067
- package/skills/video-understand/skill.json +20 -20
- package/skills/video-understand/src/SKILL.md +79 -79
- package/skills/video-understand/src/scripts/video_understand.py +204 -204
- package/skills/weather/skill.json +19 -19
- package/skills/weather/src/SKILL.md +112 -112
- package/skills/web-scraper/skill.json +20 -20
- package/skills/web-scraper/src/SKILL.md +101 -101
- package/skills/web-scraper/src/scripts/scrape.py +270 -270
- package/skills/website-builder/skill.json +20 -20
- package/skills/website-builder/src/SKILL.md +266 -266
- package/skills/website-builder/src/scripts/deploy_site.sh +46 -46
- package/skills/wechat-article-publisher/skill.json +20 -20
- package/skills/wechat-article-publisher/src/SKILL.md +60 -60
- package/skills/wechat-article-publisher/src/config.json +6 -6
- package/skills/wechat-article-publisher/src/pyproject.toml +12 -12
- package/skills/wechat-article-publisher/src/scripts/publish_wechat.py +825 -825
- package/skills/xiaohongshu/skill.json +20 -20
- package/skills/xiaohongshu/src/SKILL.md +91 -91
- package/skills/xiaohongshu/src/_meta.json +5 -5
- package/skills/xiaohongshu/src/assets/card.html +216 -216
- package/skills/xiaohongshu/src/assets/cover.html +82 -82
- package/skills/xiaohongshu/src/assets/example.md +84 -84
- package/skills/xiaohongshu/src/assets/styles.css +318 -318
- package/skills/xiaohongshu/src/scripts/render_xhs_v2.py +737 -737
- package/skills/xiaohongshu/src/scripts/sign_server.py +158 -158
- package/skills/xiaohongshu/src/scripts/stealth.min.js +6 -6
- package/skills/xiaohongshu/src/scripts/xhs_tool.py +186 -186
- package/skills/xiaohongshu/src/workflow.py +185 -185
- package/src/commands/agent.js +112 -112
- package/src/commands/download.js +101 -101
- package/src/commands/info.js +58 -58
- package/src/commands/list.js +71 -71
- package/src/utils/agents.js +36 -36
- package/src/utils/config.js +22 -22
- package/src/utils/paths.js +31 -31
- package/src/utils/versions.js +57 -57
|
@@ -1,368 +1,368 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: image-classify
|
|
3
|
-
description: 照片分类器。通过人脸识别对照片进行分类、搜索和管理。当用户说「用照片分类器查找/搜索 xxx」「对 xx 文件夹进行分类」「添加 xx 到照片分类器」「从照片分类器删除 xx」时使用。
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# 📸 照片分类器
|
|
7
|
-
|
|
8
|
-
基于人脸 embedding 相似度的照片分类系统。支持注册用户人脸、按用户搜索照片、一键全量分类、删除用户;搜索/分类结束后**生成下载链接**(`pack`)即完成结果导出。
|
|
9
|
-
|
|
10
|
-
## Processing Mode
|
|
11
|
-
|
|
12
|
-
**STRICT SERIAL PROCESSING ONLY** — 单次顺序执行,不拆分子任务、不并行。
|
|
13
|
-
|
|
14
|
-
**子会话(耗时任务)**:`search`、`quick-search`、`classify` 在**独立子会话**中执行。**子命令结束(成功或失败)后,须立即关闭并删除该子会话**,不得保留空壳会话。后续步骤——向用户展示结果表格、执行 `pack`——一律在**当前主会话**中完成。
|
|
15
|
-
|
|
16
|
-
## Prerequisites
|
|
17
|
-
|
|
18
|
-
- Python 3.10+、uv
|
|
19
|
-
- 依赖:`requests`, `opencv-python`, `numpy`, `sophnet_tools`(项目内置)
|
|
20
|
-
- 配置文件:`{baseDir}/references/config.json`
|
|
21
|
-
- 若使用 **DM 自动推送**(注册时 `--friend-id`、一键 `classify` 后推送结果),需本机存在有效 JWT:`/home/node/.openclaw/jwt.json`(与 `send_dm_message.py` 一致)
|
|
22
|
-
|
|
23
|
-
## 核心概念
|
|
24
|
-
|
|
25
|
-
- **`{baseDir}`**:本 skill 根目录,即 `skills/image-classify`,调用时替换为实际绝对路径。
|
|
26
|
-
- **配置文件**:`{baseDir}/references/config.json`,存储所有注册用户的名称、照片路径、人脸 embedding 向量,以及可选 **DM 绑定**:`friendId`(好友 userId)、`friendLabel`(可选展示名)。旧字段 `xia_you_hao` / `xia_you_label` 仍可被脚本读取。
|
|
27
|
-
- **脚本入口**:`{baseDir}/scripts/face_search.py`,通过 `uv run` 以子命令方式调用。
|
|
28
|
-
- **所有命令输出均为 JSON 格式**,方便解析结果。
|
|
29
|
-
|
|
30
|
-
## 通用调用格式
|
|
31
|
-
|
|
32
|
-
```bash
|
|
33
|
-
uv run {baseDir}/scripts/face_search.py [-c CONFIG_PATH] <command> [args...]
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
`-c` / `--config` 可选,指定配置文件路径,默认为 `references/config.json`(相对于执行目录)。建议始终传入绝对路径 `{baseDir}/references/config.json`。
|
|
37
|
-
|
|
38
|
-
## 可用命令一览
|
|
39
|
-
|
|
40
|
-
| 命令 | 用途 | 示例 |
|
|
41
|
-
|------|------|------|
|
|
42
|
-
| `check <name>` | 检查用户名是否已注册 | `check 张三` |
|
|
43
|
-
| `add <name> <image> [--friend-id ID] [--friend-label 名]` | 注册新用户;可选 `friendId` 与 `friendLabel`(括号内提示用) | `add 张三 /path/photo.jpg --friend-label 小李 --friend-id 23725` |
|
|
44
|
-
| `replace <name> <image>` | 替换用户照片(删除旧照片) | `replace 张三 /path/new.jpg` |
|
|
45
|
-
| `append <name> <image>` | 为已有用户追加一张照片 | `append 张三 /path/extra.jpg` |
|
|
46
|
-
| `rename <old> <new>` | 修改用户名 | `rename 张三 李三` |
|
|
47
|
-
| `delete <name>` | 删除用户 | `delete 张三` |
|
|
48
|
-
| `search <name> <dir>` | 在目录中搜索某用户的相似人脸 | `search 张三 /home/photos` |
|
|
49
|
-
| `quick-search <image> <dir>` | 直接用照片搜索相似人脸(不注册) | `quick-search /tmp/face.jpg /home/photos` |
|
|
50
|
-
| `classify <dir>` | 一键分类:遍历所有用户搜索全部照片 | `classify /home/photos` |
|
|
51
|
-
| `copy <target> [--name N]` | (可选)将搜索结果复制到本地文件夹 | `copy /output --name 张三` |
|
|
52
|
-
| `pack [--name N] [--timeout T]` | 压缩结果为 zip 并上传获取下载链接 | `pack --timeout 120` |
|
|
53
|
-
| `upload <file> [--timeout T]` | 上传文件获取 URL | `upload /path/file.zip` |
|
|
54
|
-
| `init-today-folder` | 创建并返回待搜索目录当天子目录 | `init-today-folder` |
|
|
55
|
-
| `upload-image <file...>` | 将一张或多张图片串行剪切到待搜索目录 `images/当天日期(YYYYMMDD)` | `upload-image /tmp/a.jpg /tmp/b.jpg` |
|
|
56
|
-
| `list-date-folders` | 列出待搜索根目录 `images` 下全部 `YYYYMMDD` 子文件夹(新→旧),供未指定目录时选择 | `list-date-folders` |
|
|
57
|
-
|
|
58
|
-
> ⚠️ 注意:如果用户发送的图片格式为 ``,需要先执行 `upload` 命令将其转换为 URL 格式后再处理。
|
|
59
|
-
|
|
60
|
-
## Usage
|
|
61
|
-
|
|
62
|
-
根据用户意图匹配以下操作流程:
|
|
63
|
-
|
|
64
|
-
### 未指定搜索目录时(`search` / `quick-search` / `classify` 共用)
|
|
65
|
-
|
|
66
|
-
待搜索根目录由脚本内 `get_images_path()` 解析(通常为仓库上级 `images`)。其下按日期命名的子目录(`YYYYMMDD`)为可选搜索范围。
|
|
67
|
-
|
|
68
|
-
若用户**未说明**搜索目录(或只说「默认目录」「最近上传的」等),**不要猜测路径**,先执行:
|
|
69
|
-
|
|
70
|
-
```bash
|
|
71
|
-
uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json list-date-folders
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
输出 JSON 字段说明:
|
|
75
|
-
- `folders`:全部合法日期文件夹,`{ "name": "20260410", "path": "/绝对路径/20260410" }`,已按日期**从新到旧**排序
|
|
76
|
-
- `preview` / `preview_n`:默认只向用户展示**最近 `preview_n` 个(默认 3 个)**即可
|
|
77
|
-
- `total`:总数;若大于 `preview_n`,用户可说「更多」「全部」「列出全部」——此时用 Markdown 列出剩余项(**只展示 `name`**,不罗列每条 `path`),再请用户回复**序号**或**日期名(YYYYMMDD)**;用户若粘贴目录路径则按路径解析
|
|
78
|
-
|
|
79
|
-
选定目录后,将解析出的**绝对路径**作为 `<dir>` 传入 `search` / `quick-search` / `classify`。
|
|
80
|
-
|
|
81
|
-
若 `folders` 为空,提示用户在 `images` 下先上传或创建日期目录(可用 `init-today-folder`、`upload-image`),或**手动提供**任意搜索目录路径。
|
|
82
|
-
|
|
83
|
-
**向用户展示候选目录时(示例模版)** — 用 Markdown 呈现,**只展示日期文件夹名**,不要把磁盘绝对路径列给用户:
|
|
84
|
-
|
|
85
|
-
- 📅📂 **最近可用的日期文件夹(任选其一)**
|
|
86
|
-
- 1️⃣ 📁 `20260410`
|
|
87
|
-
|
|
88
|
-
- 2️⃣ 📁 `20260409`
|
|
89
|
-
|
|
90
|
-
- 3️⃣ 📁 `20260408`
|
|
91
|
-
- 💬 请回复**序号**或**日期名**;需要查看更多请说「更多」。内部调用命令时仍使用 JSON 里的 `path` 字段。✨
|
|
92
|
-
|
|
93
|
-
### 1. 添加/注册用户
|
|
94
|
-
|
|
95
|
-
**触发词**:「添加 xxx 到照片分类器」「注册 xxx」「把这张照片记为 xxx」
|
|
96
|
-
|
|
97
|
-
**流程**:
|
|
98
|
-
|
|
99
|
-
1. 获取用户提供的**用户名**、**照片路径**,以及是否绑定 **DM 接收方**(均可选)。用户常以自然语言写出类似:**虾友:xxx,ID:23725**(虾友即 DM 对象;**23725** 即 `friendId`)。解析规则:**xxx** → `--friend-label`;**23725** → `--friend-id`(正整数,与 `send_dm_message.py` 的 `--user-id` / 接口 `userId` 一致)。可只填 `friendId`、不填展示名。
|
|
100
|
-
2. 检查用户名是否已存在:
|
|
101
|
-
```bash
|
|
102
|
-
uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json check "张三"
|
|
103
|
-
```
|
|
104
|
-
输出:`{"exists": true/false, "name": "张三"}`
|
|
105
|
-
|
|
106
|
-
3. **如果不存在** → 注册新用户(无虾友号):
|
|
107
|
-
```bash
|
|
108
|
-
uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json add "张三" "/path/to/photo.jpg"
|
|
109
|
-
```
|
|
110
|
-
若用户提供了 `friendId`,追加 `--friend-id <正整数>`;若有展示名,追加 `--friend-label "xxx"`(注意转义或引号,避免 shell 拆词):
|
|
111
|
-
```bash
|
|
112
|
-
uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json add "张三" "/path/to/photo.jpg" --friend-label "小李" --friend-id 23725
|
|
113
|
-
```
|
|
114
|
-
输出:`{"success": true/false, "message": "...", "name": "张三", "image_url": "https://...", "friendId": 23725, "friendLabel": "小李"}`(`friendId` / `friendLabel` 仅在实际传入时出现)
|
|
115
|
-
- `success: true` → 提示:`🎉✨ **注册成功** · xxx`,并使用返回的 `image_url` 展示照片:``;若返回含 `friendId` / `friendLabel`,可顺带一句已绑定 DM(不必冗长)
|
|
116
|
-
- `success: false` → 提示:`❌🙈 照片中未发现有效的人脸信息,注册失败!`
|
|
117
|
-
|
|
118
|
-
4. **如果已存在** → 提示用户选择操作:
|
|
119
|
-
```
|
|
120
|
-
⚡👤 用户名已存在,请选择操作:
|
|
121
|
-
1️⃣ 🔄 更新照片(替换主照片)
|
|
122
|
-
2️⃣ ✏️ 重新命名
|
|
123
|
-
3️⃣ ➕ 同时保留多张照片
|
|
124
|
-
```
|
|
125
|
-
- **更新照片**:
|
|
126
|
-
```bash
|
|
127
|
-
uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json replace "张三" "/path/to/new.jpg"
|
|
128
|
-
```
|
|
129
|
-
输出包含 `image_url` 字段。
|
|
130
|
-
- 成功:`✅🔄 **照片已更新** · xxx`,使用 `image_url` 展示照片:``
|
|
131
|
-
- 失败:`❌🙈 照片中未发现有效的人脸信息,更新失败!`
|
|
132
|
-
- **重新命名**:
|
|
133
|
-
```bash
|
|
134
|
-
uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json rename "张三" "李三"
|
|
135
|
-
```
|
|
136
|
-
- 提示:`✏️📛 **用户名已更新** · xxx → yyy`
|
|
137
|
-
- **保留多张**:
|
|
138
|
-
```bash
|
|
139
|
-
uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json append "张三" "/path/to/extra.jpg"
|
|
140
|
-
```
|
|
141
|
-
输出包含 `image_url` 字段。
|
|
142
|
-
- 成功:`✅➕ **新照片已追加** · xxx`,使用 `image_url` 展示照片:``
|
|
143
|
-
- 失败:`❌🙈 照片中未发现有效的人脸信息,添加失败!`
|
|
144
|
-
|
|
145
|
-
### 2. 搜索用户照片
|
|
146
|
-
|
|
147
|
-
**触发词**:「用照片分类器在 yy 文件夹下查找 xxx」「搜索 xxx 的照片」
|
|
148
|
-
|
|
149
|
-
**流程**:
|
|
150
|
-
|
|
151
|
-
1. 从用户表述中提取**用户名**和**搜索目录**。若**未指定搜索目录**,先按上文「未指定搜索目录时」列出最近 3 个日期文件夹供选择(支持「更多」展示全部),得到 `<dir>` 后再继续。
|
|
152
|
-
2. 检查用户名是否存在(`check` 命令),不存在则提示:`❌🔍 **未找到该用户** · 请确认姓名后重试`
|
|
153
|
-
3. 使用**子会话**执行搜索(可能耗时较长):
|
|
154
|
-
```bash
|
|
155
|
-
uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json search "张三" "<dir>"
|
|
156
|
-
```
|
|
157
|
-
(`<dir>` 为用户指定路径,或从 `list-date-folders` 选中的 `path`。)**命令返回后立刻关闭并删除该子会话。**
|
|
158
|
-
输出:
|
|
159
|
-
```json
|
|
160
|
-
{"name": "张三", "count": 3, "results": [{"image_path": "...", "face_index": 0, "similarity": 0.85}, ...]}
|
|
161
|
-
```
|
|
162
|
-
4. 将结果通知到当前会话,以表格形式展示:
|
|
163
|
-
```
|
|
164
|
-
🔎✨ **人脸搜索结果** · 👤 <用户名>
|
|
165
|
-
───────────────────────
|
|
166
|
-
```
|
|
167
|
-
| 🖼️ 照片路径 | 📊 相似度 |
|
|
168
|
-
|:----:|:----:|
|
|
169
|
-
| /path/to/photo.jpg | 0.85 |
|
|
170
|
-
5. 展示结果后按「结果导出」执行 `pack` 生成下载链接(见 §6);`pack` 返回后若含 `dm_lines`(向虾友推送**下载链接**的状态),须在链接展示之后**再**逐行展示(可与搜索结果本身区分开)。
|
|
171
|
-
|
|
172
|
-
### 3. 直接搜索(不注册)
|
|
173
|
-
|
|
174
|
-
**触发词**:「用这张照片搜索 yy 文件夹」「直接用照片查找」「不注册直接搜」
|
|
175
|
-
|
|
176
|
-
**流程**:
|
|
177
|
-
|
|
178
|
-
1. 获取用户提供的**照片路径**和**搜索目录**。若**未指定搜索目录**,先按「未指定搜索目录时」列出最近 3 个日期文件夹供选择(支持「更多」),得到 `<dir>` 后再继续。
|
|
179
|
-
2. 使用**子会话**执行搜索(先提取人脸 embedding,再匹配,可能耗时较长):
|
|
180
|
-
```bash
|
|
181
|
-
uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json quick-search "/path/to/face.jpg" "<dir>"
|
|
182
|
-
```
|
|
183
|
-
**命令返回后立刻关闭并删除该子会话。**
|
|
184
|
-
输出:
|
|
185
|
-
```json
|
|
186
|
-
{"success": true/false, "count": 3, "results": [...], "message": "..."}
|
|
187
|
-
```
|
|
188
|
-
- `success: false` → 表示照片中未检测到有效人脸,提示:`❌🙈 **未检测到人脸** · 无法搜索`
|
|
189
|
-
3. 将结果通知到当前会话,以表格形式展示:
|
|
190
|
-
```
|
|
191
|
-
🪪🖼️ **直接搜索**(未注册)· 已用查询图匹配
|
|
192
|
-
───────────────────────
|
|
193
|
-
```
|
|
194
|
-
| 🖼️ 照片路径 | 📊 相似度 |
|
|
195
|
-
|:----:|:----:|
|
|
196
|
-
| /path/to/photo.jpg | 0.85 |
|
|
197
|
-
4. 展示结果后按「结果导出」执行 `pack` 生成下载链接(见 §6);`pack` 返回后若含 `dm_lines`,须在链接展示之后**再**逐行展示。
|
|
198
|
-
|
|
199
|
-
### 4. 一键分类
|
|
200
|
-
|
|
201
|
-
**触发词**:「用照片分类器对 xx 文件夹进行分类」「一键分类」「对这些照片按人分类」
|
|
202
|
-
|
|
203
|
-
**流程**:
|
|
204
|
-
|
|
205
|
-
1. 从用户表述中提取**搜索目录**。若**未指定搜索目录**,先按「未指定搜索目录时」列出最近 3 个日期文件夹供选择(支持「更多」),得到 `<dir>` 后再继续。
|
|
206
|
-
2. 使用**子会话**执行分类(可能耗时较长):
|
|
207
|
-
```bash
|
|
208
|
-
uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json classify "<dir>"
|
|
209
|
-
```
|
|
210
|
-
**命令返回后立刻关闭并删除该子会话。**
|
|
211
|
-
输出(节选):
|
|
212
|
-
```json
|
|
213
|
-
{
|
|
214
|
-
"user_count": 2,
|
|
215
|
-
"users": {"张三": {"count": 3, "results": [...]}, "李四": {"count": 1, "results": [...]}},
|
|
216
|
-
"dm": {"张三": {"success": true, "friendId": 23725, "friendLabel": "小李"}},
|
|
217
|
-
"dm_lines": ["✅ 💌 已向虾友「小李」发送成功", "📭 「李四」暂未绑定虾友,跳过私信"]
|
|
218
|
-
}
|
|
219
|
-
```
|
|
220
|
-
- `dm`:仅当配置里**至少有一位用户**登记了 `friendId` 时出现;脚本在分类结束后**自动调用** `{baseDir}/scripts/send_dm_message.py`(`--user-id` = `friendId`),将**该用户本轮分类结果摘要**发出。失败时含 `"success": false` 与 `detail`。
|
|
221
|
-
- `dm_lines`:**只要本轮参与分类的用户数 ≥1 即出现**(与是否有人绑定 `friendId` 无关)。为**最终提示专用**短句数组,顺序与本轮 `users` 中用户顺序一致。句式固定:
|
|
222
|
-
- 已绑定且发送成功:`✅ 💌 已向虾友「xxx」发送成功` — **xxx** 优先为配置中的 `friendLabel`,否则为 `friendId` 数字字符串。
|
|
223
|
-
- 已绑定且发送失败:`❌ 💢 虾友「xxx」发送失败:<原因>`(原因取自 `dm` 中对应用户的 `detail`)。
|
|
224
|
-
- 未绑定 `friendId`:`📭 「<本地用户名>」暂未绑定虾友,跳过私信`。
|
|
225
|
-
- `user_count: 0` → 提示:`❌👥 **暂无注册用户** · 请先注册人脸后再分类`
|
|
226
|
-
3. 将结果通知到当前会话,对每个用户分别展示:
|
|
227
|
-
```
|
|
228
|
-
🗂️✨ **一键分类完成** · 共 👥 N 位注册用户参与匹配
|
|
229
|
-
───────────────────────
|
|
230
|
-
```
|
|
231
|
-
对每个有匹配结果的用户:
|
|
232
|
-
```
|
|
233
|
-
👤✅ **张三** · 📸 匹配 M 张
|
|
234
|
-
```
|
|
235
|
-
| 🖼️ 照片路径 | 📊 相似度 |
|
|
236
|
-
|:----:|:----:|
|
|
237
|
-
| /path/to/photo.jpg | 0.85 |
|
|
238
|
-
|
|
239
|
-
无匹配结果的用户:
|
|
240
|
-
```
|
|
241
|
-
👤💤 **王五** · 本轮暂无匹配
|
|
242
|
-
```
|
|
243
|
-
4. **分类摘要 DM(必须在表格之后、`pack` 之前展示)**:若 `classify` 的 JSON 含 `dm_lines`(本轮**分类结果摘要**的私信状态),在分类表格**之后**单独加一块,**逐行原样**展示。示例:
|
|
244
|
-
```
|
|
245
|
-
📬 **虾友发送状态(分类摘要)**
|
|
246
|
-
✅ 💌 已向虾友「小李」发送成功
|
|
247
|
-
📭 「李四」暂未绑定虾友,跳过私信
|
|
248
|
-
```
|
|
249
|
-
无 `dm_lines` 时(仅 `user_count: 0` 等异常)跳过本块。
|
|
250
|
-
5. 展示结果后按「结果导出」执行 `pack` 生成下载链接(见 §6)。**`pack` 成功后还会自动向对应 `friendId` 私信「打包下载链接」**;若 `pack` 的 JSON 另含 `dm_lines`(**下载链接**的私信状态),须在下载链接展示之后**再**逐行展示,可与上一步标题区分,例如「下载链接私信状态」。
|
|
251
|
-
|
|
252
|
-
### 5. 删除用户
|
|
253
|
-
|
|
254
|
-
**触发词**:「删除照片分类器中 xxx 的信息」「把 xxx 从照片分类器移除」
|
|
255
|
-
|
|
256
|
-
**流程**:
|
|
257
|
-
|
|
258
|
-
1. 从用户表述中提取**用户名**
|
|
259
|
-
2. 检查用户名是否存在(`check` 命令),不存在则提示:`❌🔍 **未找到该用户** · 请确认姓名后重试`
|
|
260
|
-
3. 提示确认:`⚠️🗑️ **确认删除用户 xxx?** · 此操作不可撤销`
|
|
261
|
-
- 用户确认 →
|
|
262
|
-
```bash
|
|
263
|
-
uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json delete "张三"
|
|
264
|
-
```
|
|
265
|
-
提示:`🗑️✨ **用户已删除** · xxx`
|
|
266
|
-
- 用户取消 → 提示:`↩️👋 **已取消删除**`
|
|
267
|
-
|
|
268
|
-
### 6. 结果导出(搜索/分类完成后)
|
|
269
|
-
|
|
270
|
-
搜索或分类完成后,结果已保存在 `config.json` 中。展示匹配结果表格(分类场景下若已有「分类摘要」`dm_lines`,须先展示完毕)后,**不要先弹出与导出无关的菜单**,直接执行 **`pack`** 生成下载链接(压缩包可能较大,超时默认 120 秒)。
|
|
271
|
-
|
|
272
|
-
**`pack` 成功后,脚本会自动调用** `{baseDir}/scripts/send_dm_message.py`,向**已绑定 `friendId` 的注册用户**私信发送**对应用户的打包下载链接**;正文模板为:先提示「「用户名」的照片已为您送达」,再附 URL,并提醒 **24 小时内下载**、逾期链接可能失效。无 `friendId` 的用户条目会体现在返回的 `dm_lines` 里(`📭 「xxx」暂未绑定虾友,跳过私信`)。**仅 `quick-search` 结果、无注册用户名时**,无法绑定虾友,不会发链接私信。
|
|
273
|
-
|
|
274
|
-
- **单用户 `search`**(指定 `--name`):
|
|
275
|
-
```bash
|
|
276
|
-
uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json pack --name "张三" --timeout 120
|
|
277
|
-
```
|
|
278
|
-
输出(节选):`{"success": true, "url": "https://...", "zip_path": "/tmp/.../search_results.zip", "dm": {...}, "dm_lines": [...]}`(有 `friendId` 时含 `dm` / `dm_lines`)
|
|
279
|
-
成功提示:`📦🔗 **下载链接已就绪** ✨` → `<url>` → 若有 `dm_lines`,再展示「下载链接私信状态」块。
|
|
280
|
-
|
|
281
|
-
- **`quick-search`(直接搜索)**:结果存于 `quick_search_result`,执行 **不带 `--name`** 的 `pack`(与仅含直接搜索结果时一致):
|
|
282
|
-
```bash
|
|
283
|
-
uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json pack --timeout 120
|
|
284
|
-
```
|
|
285
|
-
成功提示:`📦🔗 **下载链接已就绪** ✨` → `<url>`(通常**无**虾友私信,因无注册用户上下文)
|
|
286
|
-
|
|
287
|
-
- **一键 `classify`**(不指定 `--name`,**每位用户单独打包**):
|
|
288
|
-
```bash
|
|
289
|
-
uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json pack --timeout 120
|
|
290
|
-
```
|
|
291
|
-
输出示例(节选):
|
|
292
|
-
```json
|
|
293
|
-
{
|
|
294
|
-
"success": true,
|
|
295
|
-
"user_urls": {"张三": "https://...", "李四": "https://..."},
|
|
296
|
-
"errors": null,
|
|
297
|
-
"dm": {"张三": {"success": true, "friendId": 23725, "friendLabel": "小李", "url": "https://..."}},
|
|
298
|
-
"dm_lines": ["✅ 💌 已向虾友「小李」发送成功", "📭 「李四」暂未绑定虾友,跳过私信"]
|
|
299
|
-
}
|
|
300
|
-
```
|
|
301
|
-
成功提示:先逐用户展示链接,例如:
|
|
302
|
-
```
|
|
303
|
-
📦✨ **各用户独立下载包**
|
|
304
|
-
───────────────────────
|
|
305
|
-
👤 张三 📎 <url>
|
|
306
|
-
👤 李四 📎 <url>
|
|
307
|
-
```
|
|
308
|
-
再展示 `dm_lines`(下载链接私信状态)。
|
|
309
|
-
部分失败:列出已成功链接,并对失败用户提示:`⚠️❌ **<用户名>** · 下载包生成失败:<原因>`;`dm_lines` 中亦会有对应失败说明。全部失败:`❌📦 下载链接全部失败`。
|
|
310
|
-
|
|
311
|
-
`pack` 完成后,**结果导出即结束**。若用户另行要求把文件复制到本地目录,可再使用命令表中的 `copy`(非本 skill 默认流程)。
|
|
312
|
-
|
|
313
|
-
### 7. 上传图片到待搜索目录
|
|
314
|
-
|
|
315
|
-
**触发词**:「上传这张图片到待搜索目录」「上传这些图片到待搜索目录」「上传这些照片」「把图片放到今天目录供搜索」「把图片移到待搜索目录」
|
|
316
|
-
|
|
317
|
-
**流程**:
|
|
318
|
-
|
|
319
|
-
1. 获取用户提供的**图片路径**(支持单张或多张)
|
|
320
|
-
2. 直接执行:
|
|
321
|
-
```bash
|
|
322
|
-
uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json upload-image "/path/to/a.jpg" "/path/to/b.jpg"
|
|
323
|
-
```
|
|
324
|
-
3. 单张时输出:`{"success": true/false, "folder_path": "/abs/path/to/images/YYYYMMDD", "file_path": "/abs/path/to/images/YYYYMMDD/a.jpg", "failed": []}`
|
|
325
|
-
4. 多张时输出:`{"success": true/false, "folder_path": "/abs/path/to/images/YYYYMMDD", "uploaded": [...], "failed": [...]}`
|
|
326
|
-
5. 成功后提示:`✅📤 **已放入待搜索目录** → <folder_path> ✨`;如果有失败文件,提示:`⚠️ 部分失败:` 并列出项。
|
|
327
|
-
|
|
328
|
-
## Example Workflow
|
|
329
|
-
|
|
330
|
-
- 用户:「把这张照片添加为张三」
|
|
331
|
-
1. `uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json check "张三"`
|
|
332
|
-
2. 不存在 → `uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json add "张三" "/path/to/photo.jpg"`
|
|
333
|
-
3. 提示:`🎉✨ **注册成功** · 张三`
|
|
334
|
-
|
|
335
|
-
- 用户:「用照片分类器在 /home/photos 下查找张三」
|
|
336
|
-
1. `uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json check "张三"` → 存在
|
|
337
|
-
2. 子会话执行 `uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json search "张三" "/home/photos"`
|
|
338
|
-
3. 展示结果表格 → `pack --name "张三" --timeout 120` 生成下载链接(见 §6)→ 若有 `dm_lines`,展示下载链接私信状态
|
|
339
|
-
|
|
340
|
-
- 用户:「用这张照片在 /home/photos 里找找有没有类似的」
|
|
341
|
-
1. 子会话执行 `uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json quick-search "/tmp/face.jpg" "/home/photos"`
|
|
342
|
-
2. 成功 → 展示表格 → `pack --timeout 120`(不带 `--name`);失败 → 提示未检测到有效人脸
|
|
343
|
-
|
|
344
|
-
- 用户:「用照片分类器对 /home/album 进行分类」
|
|
345
|
-
1. 子会话执行 `uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json classify "/home/album"`
|
|
346
|
-
2. 展示各用户结果(及分类摘要 `dm_lines` 若有)→ `pack --timeout 120`(多用户各一链接,见 §6)→ 展示链接及 **`pack` 返回的 `dm_lines`**(下载链接私信状态)
|
|
347
|
-
|
|
348
|
-
- 用户:「删除照片分类器中李四的信息」
|
|
349
|
-
1. `uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json check "李四"` → 存在
|
|
350
|
-
2. 提示确认 → 用户确认 → `uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json delete "李四"`
|
|
351
|
-
3. 提示:`🗑️✨ **用户已删除** · 李四`
|
|
352
|
-
|
|
353
|
-
- 用户:「把这些图片放到待搜索目录」
|
|
354
|
-
1. `uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json upload-image "/tmp/a.jpg" "/tmp/b.jpg"`
|
|
355
|
-
2. 全部成功后提示:`✅📤 **已放入待搜索目录** → <folder_path> ✨`
|
|
356
|
-
|
|
357
|
-
## Notes
|
|
358
|
-
|
|
359
|
-
- 建议始终通过 `-c` 传入 `{baseDir}/references/config.json` 的绝对路径,避免相对路径导致找不到配置文件。
|
|
360
|
-
- `search`、`quick-search` 和 `classify` 可能耗时较长(取决于搜索目录中的图片数量),应在**子会话**中执行;**结束后立即关闭并删除该子会话**,再将结果展示与 `pack` 放在**主会话**中完成。
|
|
361
|
-
- `images/` 目录用于存放待搜索图片;`upload-image` 内部会创建当天目录并串行逐张处理图片。
|
|
362
|
-
- 搜索过程中会在图片所在目录下创建 `.embedding` 隐藏目录缓存 embedding 结果,后续搜索同一目录会自动跳过已处理的图片。
|
|
363
|
-
- `pack` 与 `copy` 均依赖 `config.json` 中保存的搜索结果(`search_result` 或 `quick_search_result` 等),须先执行 `search`、`classify` 或 `quick-search`。默认流程只需 **`pack`**;`copy` 为可选,由用户另行提出时再执行。
|
|
364
|
-
- **`classify`** 会向 `friendId` 发**分类结果摘要**;**`pack`** 会向 `friendId` 发**打包下载链接**(两次私信、用途不同);若只需其一,可后续再改脚本或配置(当前实现为两者都发)。
|
|
365
|
-
- `pack` 的压缩文件存放在系统临时目录中,上传完成后可忽略清理。上传超时默认 120 秒,文件特别大时可通过 `--timeout` 增大。
|
|
366
|
-
- `config.json` 中的 `query_threshold`(默认 0.7)控制人脸检测置信度阈值,`search_similarity_threshold`(默认 0.3)控制搜索匹配的最低相似度。
|
|
367
|
-
- `{baseDir}` 指本 skill 根目录(如 `skills/image-classify`),调用时替换为实际绝对路径。
|
|
368
|
-
- `friendId`(虾友号)与可选 `friendLabel` 写在用户条目下;**注册时**通过 `add ... --friend-id` / `--friend-label` 写入。后续若需修改可编辑 `config.json`(本 skill 未单独提供改绑子命令)。旧键名仍兼容读取。
|
|
1
|
+
---
|
|
2
|
+
name: image-classify
|
|
3
|
+
description: 照片分类器。通过人脸识别对照片进行分类、搜索和管理。当用户说「用照片分类器查找/搜索 xxx」「对 xx 文件夹进行分类」「添加 xx 到照片分类器」「从照片分类器删除 xx」时使用。
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# 📸 照片分类器
|
|
7
|
+
|
|
8
|
+
基于人脸 embedding 相似度的照片分类系统。支持注册用户人脸、按用户搜索照片、一键全量分类、删除用户;搜索/分类结束后**生成下载链接**(`pack`)即完成结果导出。
|
|
9
|
+
|
|
10
|
+
## Processing Mode
|
|
11
|
+
|
|
12
|
+
**STRICT SERIAL PROCESSING ONLY** — 单次顺序执行,不拆分子任务、不并行。
|
|
13
|
+
|
|
14
|
+
**子会话(耗时任务)**:`search`、`quick-search`、`classify` 在**独立子会话**中执行。**子命令结束(成功或失败)后,须立即关闭并删除该子会话**,不得保留空壳会话。后续步骤——向用户展示结果表格、执行 `pack`——一律在**当前主会话**中完成。
|
|
15
|
+
|
|
16
|
+
## Prerequisites
|
|
17
|
+
|
|
18
|
+
- Python 3.10+、uv
|
|
19
|
+
- 依赖:`requests`, `opencv-python`, `numpy`, `sophnet_tools`(项目内置)
|
|
20
|
+
- 配置文件:`{baseDir}/references/config.json`
|
|
21
|
+
- 若使用 **DM 自动推送**(注册时 `--friend-id`、一键 `classify` 后推送结果),需本机存在有效 JWT:`/home/node/.openclaw/jwt.json`(与 `send_dm_message.py` 一致)
|
|
22
|
+
|
|
23
|
+
## 核心概念
|
|
24
|
+
|
|
25
|
+
- **`{baseDir}`**:本 skill 根目录,即 `skills/image-classify`,调用时替换为实际绝对路径。
|
|
26
|
+
- **配置文件**:`{baseDir}/references/config.json`,存储所有注册用户的名称、照片路径、人脸 embedding 向量,以及可选 **DM 绑定**:`friendId`(好友 userId)、`friendLabel`(可选展示名)。旧字段 `xia_you_hao` / `xia_you_label` 仍可被脚本读取。
|
|
27
|
+
- **脚本入口**:`{baseDir}/scripts/face_search.py`,通过 `uv run` 以子命令方式调用。
|
|
28
|
+
- **所有命令输出均为 JSON 格式**,方便解析结果。
|
|
29
|
+
|
|
30
|
+
## 通用调用格式
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
uv run {baseDir}/scripts/face_search.py [-c CONFIG_PATH] <command> [args...]
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
`-c` / `--config` 可选,指定配置文件路径,默认为 `references/config.json`(相对于执行目录)。建议始终传入绝对路径 `{baseDir}/references/config.json`。
|
|
37
|
+
|
|
38
|
+
## 可用命令一览
|
|
39
|
+
|
|
40
|
+
| 命令 | 用途 | 示例 |
|
|
41
|
+
|------|------|------|
|
|
42
|
+
| `check <name>` | 检查用户名是否已注册 | `check 张三` |
|
|
43
|
+
| `add <name> <image> [--friend-id ID] [--friend-label 名]` | 注册新用户;可选 `friendId` 与 `friendLabel`(括号内提示用) | `add 张三 /path/photo.jpg --friend-label 小李 --friend-id 23725` |
|
|
44
|
+
| `replace <name> <image>` | 替换用户照片(删除旧照片) | `replace 张三 /path/new.jpg` |
|
|
45
|
+
| `append <name> <image>` | 为已有用户追加一张照片 | `append 张三 /path/extra.jpg` |
|
|
46
|
+
| `rename <old> <new>` | 修改用户名 | `rename 张三 李三` |
|
|
47
|
+
| `delete <name>` | 删除用户 | `delete 张三` |
|
|
48
|
+
| `search <name> <dir>` | 在目录中搜索某用户的相似人脸 | `search 张三 /home/photos` |
|
|
49
|
+
| `quick-search <image> <dir>` | 直接用照片搜索相似人脸(不注册) | `quick-search /tmp/face.jpg /home/photos` |
|
|
50
|
+
| `classify <dir>` | 一键分类:遍历所有用户搜索全部照片 | `classify /home/photos` |
|
|
51
|
+
| `copy <target> [--name N]` | (可选)将搜索结果复制到本地文件夹 | `copy /output --name 张三` |
|
|
52
|
+
| `pack [--name N] [--timeout T]` | 压缩结果为 zip 并上传获取下载链接 | `pack --timeout 120` |
|
|
53
|
+
| `upload <file> [--timeout T]` | 上传文件获取 URL | `upload /path/file.zip` |
|
|
54
|
+
| `init-today-folder` | 创建并返回待搜索目录当天子目录 | `init-today-folder` |
|
|
55
|
+
| `upload-image <file...>` | 将一张或多张图片串行剪切到待搜索目录 `images/当天日期(YYYYMMDD)` | `upload-image /tmp/a.jpg /tmp/b.jpg` |
|
|
56
|
+
| `list-date-folders` | 列出待搜索根目录 `images` 下全部 `YYYYMMDD` 子文件夹(新→旧),供未指定目录时选择 | `list-date-folders` |
|
|
57
|
+
|
|
58
|
+
> ⚠️ 注意:如果用户发送的图片格式为 ``,需要先执行 `upload` 命令将其转换为 URL 格式后再处理。
|
|
59
|
+
|
|
60
|
+
## Usage
|
|
61
|
+
|
|
62
|
+
根据用户意图匹配以下操作流程:
|
|
63
|
+
|
|
64
|
+
### 未指定搜索目录时(`search` / `quick-search` / `classify` 共用)
|
|
65
|
+
|
|
66
|
+
待搜索根目录由脚本内 `get_images_path()` 解析(通常为仓库上级 `images`)。其下按日期命名的子目录(`YYYYMMDD`)为可选搜索范围。
|
|
67
|
+
|
|
68
|
+
若用户**未说明**搜索目录(或只说「默认目录」「最近上传的」等),**不要猜测路径**,先执行:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json list-date-folders
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
输出 JSON 字段说明:
|
|
75
|
+
- `folders`:全部合法日期文件夹,`{ "name": "20260410", "path": "/绝对路径/20260410" }`,已按日期**从新到旧**排序
|
|
76
|
+
- `preview` / `preview_n`:默认只向用户展示**最近 `preview_n` 个(默认 3 个)**即可
|
|
77
|
+
- `total`:总数;若大于 `preview_n`,用户可说「更多」「全部」「列出全部」——此时用 Markdown 列出剩余项(**只展示 `name`**,不罗列每条 `path`),再请用户回复**序号**或**日期名(YYYYMMDD)**;用户若粘贴目录路径则按路径解析
|
|
78
|
+
|
|
79
|
+
选定目录后,将解析出的**绝对路径**作为 `<dir>` 传入 `search` / `quick-search` / `classify`。
|
|
80
|
+
|
|
81
|
+
若 `folders` 为空,提示用户在 `images` 下先上传或创建日期目录(可用 `init-today-folder`、`upload-image`),或**手动提供**任意搜索目录路径。
|
|
82
|
+
|
|
83
|
+
**向用户展示候选目录时(示例模版)** — 用 Markdown 呈现,**只展示日期文件夹名**,不要把磁盘绝对路径列给用户:
|
|
84
|
+
|
|
85
|
+
- 📅📂 **最近可用的日期文件夹(任选其一)**
|
|
86
|
+
- 1️⃣ 📁 `20260410`
|
|
87
|
+
|
|
88
|
+
- 2️⃣ 📁 `20260409`
|
|
89
|
+
|
|
90
|
+
- 3️⃣ 📁 `20260408`
|
|
91
|
+
- 💬 请回复**序号**或**日期名**;需要查看更多请说「更多」。内部调用命令时仍使用 JSON 里的 `path` 字段。✨
|
|
92
|
+
|
|
93
|
+
### 1. 添加/注册用户
|
|
94
|
+
|
|
95
|
+
**触发词**:「添加 xxx 到照片分类器」「注册 xxx」「把这张照片记为 xxx」
|
|
96
|
+
|
|
97
|
+
**流程**:
|
|
98
|
+
|
|
99
|
+
1. 获取用户提供的**用户名**、**照片路径**,以及是否绑定 **DM 接收方**(均可选)。用户常以自然语言写出类似:**虾友:xxx,ID:23725**(虾友即 DM 对象;**23725** 即 `friendId`)。解析规则:**xxx** → `--friend-label`;**23725** → `--friend-id`(正整数,与 `send_dm_message.py` 的 `--user-id` / 接口 `userId` 一致)。可只填 `friendId`、不填展示名。
|
|
100
|
+
2. 检查用户名是否已存在:
|
|
101
|
+
```bash
|
|
102
|
+
uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json check "张三"
|
|
103
|
+
```
|
|
104
|
+
输出:`{"exists": true/false, "name": "张三"}`
|
|
105
|
+
|
|
106
|
+
3. **如果不存在** → 注册新用户(无虾友号):
|
|
107
|
+
```bash
|
|
108
|
+
uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json add "张三" "/path/to/photo.jpg"
|
|
109
|
+
```
|
|
110
|
+
若用户提供了 `friendId`,追加 `--friend-id <正整数>`;若有展示名,追加 `--friend-label "xxx"`(注意转义或引号,避免 shell 拆词):
|
|
111
|
+
```bash
|
|
112
|
+
uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json add "张三" "/path/to/photo.jpg" --friend-label "小李" --friend-id 23725
|
|
113
|
+
```
|
|
114
|
+
输出:`{"success": true/false, "message": "...", "name": "张三", "image_url": "https://...", "friendId": 23725, "friendLabel": "小李"}`(`friendId` / `friendLabel` 仅在实际传入时出现)
|
|
115
|
+
- `success: true` → 提示:`🎉✨ **注册成功** · xxx`,并使用返回的 `image_url` 展示照片:``;若返回含 `friendId` / `friendLabel`,可顺带一句已绑定 DM(不必冗长)
|
|
116
|
+
- `success: false` → 提示:`❌🙈 照片中未发现有效的人脸信息,注册失败!`
|
|
117
|
+
|
|
118
|
+
4. **如果已存在** → 提示用户选择操作:
|
|
119
|
+
```
|
|
120
|
+
⚡👤 用户名已存在,请选择操作:
|
|
121
|
+
1️⃣ 🔄 更新照片(替换主照片)
|
|
122
|
+
2️⃣ ✏️ 重新命名
|
|
123
|
+
3️⃣ ➕ 同时保留多张照片
|
|
124
|
+
```
|
|
125
|
+
- **更新照片**:
|
|
126
|
+
```bash
|
|
127
|
+
uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json replace "张三" "/path/to/new.jpg"
|
|
128
|
+
```
|
|
129
|
+
输出包含 `image_url` 字段。
|
|
130
|
+
- 成功:`✅🔄 **照片已更新** · xxx`,使用 `image_url` 展示照片:``
|
|
131
|
+
- 失败:`❌🙈 照片中未发现有效的人脸信息,更新失败!`
|
|
132
|
+
- **重新命名**:
|
|
133
|
+
```bash
|
|
134
|
+
uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json rename "张三" "李三"
|
|
135
|
+
```
|
|
136
|
+
- 提示:`✏️📛 **用户名已更新** · xxx → yyy`
|
|
137
|
+
- **保留多张**:
|
|
138
|
+
```bash
|
|
139
|
+
uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json append "张三" "/path/to/extra.jpg"
|
|
140
|
+
```
|
|
141
|
+
输出包含 `image_url` 字段。
|
|
142
|
+
- 成功:`✅➕ **新照片已追加** · xxx`,使用 `image_url` 展示照片:``
|
|
143
|
+
- 失败:`❌🙈 照片中未发现有效的人脸信息,添加失败!`
|
|
144
|
+
|
|
145
|
+
### 2. 搜索用户照片
|
|
146
|
+
|
|
147
|
+
**触发词**:「用照片分类器在 yy 文件夹下查找 xxx」「搜索 xxx 的照片」
|
|
148
|
+
|
|
149
|
+
**流程**:
|
|
150
|
+
|
|
151
|
+
1. 从用户表述中提取**用户名**和**搜索目录**。若**未指定搜索目录**,先按上文「未指定搜索目录时」列出最近 3 个日期文件夹供选择(支持「更多」展示全部),得到 `<dir>` 后再继续。
|
|
152
|
+
2. 检查用户名是否存在(`check` 命令),不存在则提示:`❌🔍 **未找到该用户** · 请确认姓名后重试`
|
|
153
|
+
3. 使用**子会话**执行搜索(可能耗时较长):
|
|
154
|
+
```bash
|
|
155
|
+
uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json search "张三" "<dir>"
|
|
156
|
+
```
|
|
157
|
+
(`<dir>` 为用户指定路径,或从 `list-date-folders` 选中的 `path`。)**命令返回后立刻关闭并删除该子会话。**
|
|
158
|
+
输出:
|
|
159
|
+
```json
|
|
160
|
+
{"name": "张三", "count": 3, "results": [{"image_path": "...", "face_index": 0, "similarity": 0.85}, ...]}
|
|
161
|
+
```
|
|
162
|
+
4. 将结果通知到当前会话,以表格形式展示:
|
|
163
|
+
```
|
|
164
|
+
🔎✨ **人脸搜索结果** · 👤 <用户名>
|
|
165
|
+
───────────────────────
|
|
166
|
+
```
|
|
167
|
+
| 🖼️ 照片路径 | 📊 相似度 |
|
|
168
|
+
|:----:|:----:|
|
|
169
|
+
| /path/to/photo.jpg | 0.85 |
|
|
170
|
+
5. 展示结果后按「结果导出」执行 `pack` 生成下载链接(见 §6);`pack` 返回后若含 `dm_lines`(向虾友推送**下载链接**的状态),须在链接展示之后**再**逐行展示(可与搜索结果本身区分开)。
|
|
171
|
+
|
|
172
|
+
### 3. 直接搜索(不注册)
|
|
173
|
+
|
|
174
|
+
**触发词**:「用这张照片搜索 yy 文件夹」「直接用照片查找」「不注册直接搜」
|
|
175
|
+
|
|
176
|
+
**流程**:
|
|
177
|
+
|
|
178
|
+
1. 获取用户提供的**照片路径**和**搜索目录**。若**未指定搜索目录**,先按「未指定搜索目录时」列出最近 3 个日期文件夹供选择(支持「更多」),得到 `<dir>` 后再继续。
|
|
179
|
+
2. 使用**子会话**执行搜索(先提取人脸 embedding,再匹配,可能耗时较长):
|
|
180
|
+
```bash
|
|
181
|
+
uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json quick-search "/path/to/face.jpg" "<dir>"
|
|
182
|
+
```
|
|
183
|
+
**命令返回后立刻关闭并删除该子会话。**
|
|
184
|
+
输出:
|
|
185
|
+
```json
|
|
186
|
+
{"success": true/false, "count": 3, "results": [...], "message": "..."}
|
|
187
|
+
```
|
|
188
|
+
- `success: false` → 表示照片中未检测到有效人脸,提示:`❌🙈 **未检测到人脸** · 无法搜索`
|
|
189
|
+
3. 将结果通知到当前会话,以表格形式展示:
|
|
190
|
+
```
|
|
191
|
+
🪪🖼️ **直接搜索**(未注册)· 已用查询图匹配
|
|
192
|
+
───────────────────────
|
|
193
|
+
```
|
|
194
|
+
| 🖼️ 照片路径 | 📊 相似度 |
|
|
195
|
+
|:----:|:----:|
|
|
196
|
+
| /path/to/photo.jpg | 0.85 |
|
|
197
|
+
4. 展示结果后按「结果导出」执行 `pack` 生成下载链接(见 §6);`pack` 返回后若含 `dm_lines`,须在链接展示之后**再**逐行展示。
|
|
198
|
+
|
|
199
|
+
### 4. 一键分类
|
|
200
|
+
|
|
201
|
+
**触发词**:「用照片分类器对 xx 文件夹进行分类」「一键分类」「对这些照片按人分类」
|
|
202
|
+
|
|
203
|
+
**流程**:
|
|
204
|
+
|
|
205
|
+
1. 从用户表述中提取**搜索目录**。若**未指定搜索目录**,先按「未指定搜索目录时」列出最近 3 个日期文件夹供选择(支持「更多」),得到 `<dir>` 后再继续。
|
|
206
|
+
2. 使用**子会话**执行分类(可能耗时较长):
|
|
207
|
+
```bash
|
|
208
|
+
uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json classify "<dir>"
|
|
209
|
+
```
|
|
210
|
+
**命令返回后立刻关闭并删除该子会话。**
|
|
211
|
+
输出(节选):
|
|
212
|
+
```json
|
|
213
|
+
{
|
|
214
|
+
"user_count": 2,
|
|
215
|
+
"users": {"张三": {"count": 3, "results": [...]}, "李四": {"count": 1, "results": [...]}},
|
|
216
|
+
"dm": {"张三": {"success": true, "friendId": 23725, "friendLabel": "小李"}},
|
|
217
|
+
"dm_lines": ["✅ 💌 已向虾友「小李」发送成功", "📭 「李四」暂未绑定虾友,跳过私信"]
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
- `dm`:仅当配置里**至少有一位用户**登记了 `friendId` 时出现;脚本在分类结束后**自动调用** `{baseDir}/scripts/send_dm_message.py`(`--user-id` = `friendId`),将**该用户本轮分类结果摘要**发出。失败时含 `"success": false` 与 `detail`。
|
|
221
|
+
- `dm_lines`:**只要本轮参与分类的用户数 ≥1 即出现**(与是否有人绑定 `friendId` 无关)。为**最终提示专用**短句数组,顺序与本轮 `users` 中用户顺序一致。句式固定:
|
|
222
|
+
- 已绑定且发送成功:`✅ 💌 已向虾友「xxx」发送成功` — **xxx** 优先为配置中的 `friendLabel`,否则为 `friendId` 数字字符串。
|
|
223
|
+
- 已绑定且发送失败:`❌ 💢 虾友「xxx」发送失败:<原因>`(原因取自 `dm` 中对应用户的 `detail`)。
|
|
224
|
+
- 未绑定 `friendId`:`📭 「<本地用户名>」暂未绑定虾友,跳过私信`。
|
|
225
|
+
- `user_count: 0` → 提示:`❌👥 **暂无注册用户** · 请先注册人脸后再分类`
|
|
226
|
+
3. 将结果通知到当前会话,对每个用户分别展示:
|
|
227
|
+
```
|
|
228
|
+
🗂️✨ **一键分类完成** · 共 👥 N 位注册用户参与匹配
|
|
229
|
+
───────────────────────
|
|
230
|
+
```
|
|
231
|
+
对每个有匹配结果的用户:
|
|
232
|
+
```
|
|
233
|
+
👤✅ **张三** · 📸 匹配 M 张
|
|
234
|
+
```
|
|
235
|
+
| 🖼️ 照片路径 | 📊 相似度 |
|
|
236
|
+
|:----:|:----:|
|
|
237
|
+
| /path/to/photo.jpg | 0.85 |
|
|
238
|
+
|
|
239
|
+
无匹配结果的用户:
|
|
240
|
+
```
|
|
241
|
+
👤💤 **王五** · 本轮暂无匹配
|
|
242
|
+
```
|
|
243
|
+
4. **分类摘要 DM(必须在表格之后、`pack` 之前展示)**:若 `classify` 的 JSON 含 `dm_lines`(本轮**分类结果摘要**的私信状态),在分类表格**之后**单独加一块,**逐行原样**展示。示例:
|
|
244
|
+
```
|
|
245
|
+
📬 **虾友发送状态(分类摘要)**
|
|
246
|
+
✅ 💌 已向虾友「小李」发送成功
|
|
247
|
+
📭 「李四」暂未绑定虾友,跳过私信
|
|
248
|
+
```
|
|
249
|
+
无 `dm_lines` 时(仅 `user_count: 0` 等异常)跳过本块。
|
|
250
|
+
5. 展示结果后按「结果导出」执行 `pack` 生成下载链接(见 §6)。**`pack` 成功后还会自动向对应 `friendId` 私信「打包下载链接」**;若 `pack` 的 JSON 另含 `dm_lines`(**下载链接**的私信状态),须在下载链接展示之后**再**逐行展示,可与上一步标题区分,例如「下载链接私信状态」。
|
|
251
|
+
|
|
252
|
+
### 5. 删除用户
|
|
253
|
+
|
|
254
|
+
**触发词**:「删除照片分类器中 xxx 的信息」「把 xxx 从照片分类器移除」
|
|
255
|
+
|
|
256
|
+
**流程**:
|
|
257
|
+
|
|
258
|
+
1. 从用户表述中提取**用户名**
|
|
259
|
+
2. 检查用户名是否存在(`check` 命令),不存在则提示:`❌🔍 **未找到该用户** · 请确认姓名后重试`
|
|
260
|
+
3. 提示确认:`⚠️🗑️ **确认删除用户 xxx?** · 此操作不可撤销`
|
|
261
|
+
- 用户确认 →
|
|
262
|
+
```bash
|
|
263
|
+
uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json delete "张三"
|
|
264
|
+
```
|
|
265
|
+
提示:`🗑️✨ **用户已删除** · xxx`
|
|
266
|
+
- 用户取消 → 提示:`↩️👋 **已取消删除**`
|
|
267
|
+
|
|
268
|
+
### 6. 结果导出(搜索/分类完成后)
|
|
269
|
+
|
|
270
|
+
搜索或分类完成后,结果已保存在 `config.json` 中。展示匹配结果表格(分类场景下若已有「分类摘要」`dm_lines`,须先展示完毕)后,**不要先弹出与导出无关的菜单**,直接执行 **`pack`** 生成下载链接(压缩包可能较大,超时默认 120 秒)。
|
|
271
|
+
|
|
272
|
+
**`pack` 成功后,脚本会自动调用** `{baseDir}/scripts/send_dm_message.py`,向**已绑定 `friendId` 的注册用户**私信发送**对应用户的打包下载链接**;正文模板为:先提示「「用户名」的照片已为您送达」,再附 URL,并提醒 **24 小时内下载**、逾期链接可能失效。无 `friendId` 的用户条目会体现在返回的 `dm_lines` 里(`📭 「xxx」暂未绑定虾友,跳过私信`)。**仅 `quick-search` 结果、无注册用户名时**,无法绑定虾友,不会发链接私信。
|
|
273
|
+
|
|
274
|
+
- **单用户 `search`**(指定 `--name`):
|
|
275
|
+
```bash
|
|
276
|
+
uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json pack --name "张三" --timeout 120
|
|
277
|
+
```
|
|
278
|
+
输出(节选):`{"success": true, "url": "https://...", "zip_path": "/tmp/.../search_results.zip", "dm": {...}, "dm_lines": [...]}`(有 `friendId` 时含 `dm` / `dm_lines`)
|
|
279
|
+
成功提示:`📦🔗 **下载链接已就绪** ✨` → `<url>` → 若有 `dm_lines`,再展示「下载链接私信状态」块。
|
|
280
|
+
|
|
281
|
+
- **`quick-search`(直接搜索)**:结果存于 `quick_search_result`,执行 **不带 `--name`** 的 `pack`(与仅含直接搜索结果时一致):
|
|
282
|
+
```bash
|
|
283
|
+
uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json pack --timeout 120
|
|
284
|
+
```
|
|
285
|
+
成功提示:`📦🔗 **下载链接已就绪** ✨` → `<url>`(通常**无**虾友私信,因无注册用户上下文)
|
|
286
|
+
|
|
287
|
+
- **一键 `classify`**(不指定 `--name`,**每位用户单独打包**):
|
|
288
|
+
```bash
|
|
289
|
+
uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json pack --timeout 120
|
|
290
|
+
```
|
|
291
|
+
输出示例(节选):
|
|
292
|
+
```json
|
|
293
|
+
{
|
|
294
|
+
"success": true,
|
|
295
|
+
"user_urls": {"张三": "https://...", "李四": "https://..."},
|
|
296
|
+
"errors": null,
|
|
297
|
+
"dm": {"张三": {"success": true, "friendId": 23725, "friendLabel": "小李", "url": "https://..."}},
|
|
298
|
+
"dm_lines": ["✅ 💌 已向虾友「小李」发送成功", "📭 「李四」暂未绑定虾友,跳过私信"]
|
|
299
|
+
}
|
|
300
|
+
```
|
|
301
|
+
成功提示:先逐用户展示链接,例如:
|
|
302
|
+
```
|
|
303
|
+
📦✨ **各用户独立下载包**
|
|
304
|
+
───────────────────────
|
|
305
|
+
👤 张三 📎 <url>
|
|
306
|
+
👤 李四 📎 <url>
|
|
307
|
+
```
|
|
308
|
+
再展示 `dm_lines`(下载链接私信状态)。
|
|
309
|
+
部分失败:列出已成功链接,并对失败用户提示:`⚠️❌ **<用户名>** · 下载包生成失败:<原因>`;`dm_lines` 中亦会有对应失败说明。全部失败:`❌📦 下载链接全部失败`。
|
|
310
|
+
|
|
311
|
+
`pack` 完成后,**结果导出即结束**。若用户另行要求把文件复制到本地目录,可再使用命令表中的 `copy`(非本 skill 默认流程)。
|
|
312
|
+
|
|
313
|
+
### 7. 上传图片到待搜索目录
|
|
314
|
+
|
|
315
|
+
**触发词**:「上传这张图片到待搜索目录」「上传这些图片到待搜索目录」「上传这些照片」「把图片放到今天目录供搜索」「把图片移到待搜索目录」
|
|
316
|
+
|
|
317
|
+
**流程**:
|
|
318
|
+
|
|
319
|
+
1. 获取用户提供的**图片路径**(支持单张或多张)
|
|
320
|
+
2. 直接执行:
|
|
321
|
+
```bash
|
|
322
|
+
uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json upload-image "/path/to/a.jpg" "/path/to/b.jpg"
|
|
323
|
+
```
|
|
324
|
+
3. 单张时输出:`{"success": true/false, "folder_path": "/abs/path/to/images/YYYYMMDD", "file_path": "/abs/path/to/images/YYYYMMDD/a.jpg", "failed": []}`
|
|
325
|
+
4. 多张时输出:`{"success": true/false, "folder_path": "/abs/path/to/images/YYYYMMDD", "uploaded": [...], "failed": [...]}`
|
|
326
|
+
5. 成功后提示:`✅📤 **已放入待搜索目录** → <folder_path> ✨`;如果有失败文件,提示:`⚠️ 部分失败:` 并列出项。
|
|
327
|
+
|
|
328
|
+
## Example Workflow
|
|
329
|
+
|
|
330
|
+
- 用户:「把这张照片添加为张三」
|
|
331
|
+
1. `uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json check "张三"`
|
|
332
|
+
2. 不存在 → `uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json add "张三" "/path/to/photo.jpg"`
|
|
333
|
+
3. 提示:`🎉✨ **注册成功** · 张三`
|
|
334
|
+
|
|
335
|
+
- 用户:「用照片分类器在 /home/photos 下查找张三」
|
|
336
|
+
1. `uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json check "张三"` → 存在
|
|
337
|
+
2. 子会话执行 `uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json search "张三" "/home/photos"`
|
|
338
|
+
3. 展示结果表格 → `pack --name "张三" --timeout 120` 生成下载链接(见 §6)→ 若有 `dm_lines`,展示下载链接私信状态
|
|
339
|
+
|
|
340
|
+
- 用户:「用这张照片在 /home/photos 里找找有没有类似的」
|
|
341
|
+
1. 子会话执行 `uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json quick-search "/tmp/face.jpg" "/home/photos"`
|
|
342
|
+
2. 成功 → 展示表格 → `pack --timeout 120`(不带 `--name`);失败 → 提示未检测到有效人脸
|
|
343
|
+
|
|
344
|
+
- 用户:「用照片分类器对 /home/album 进行分类」
|
|
345
|
+
1. 子会话执行 `uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json classify "/home/album"`
|
|
346
|
+
2. 展示各用户结果(及分类摘要 `dm_lines` 若有)→ `pack --timeout 120`(多用户各一链接,见 §6)→ 展示链接及 **`pack` 返回的 `dm_lines`**(下载链接私信状态)
|
|
347
|
+
|
|
348
|
+
- 用户:「删除照片分类器中李四的信息」
|
|
349
|
+
1. `uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json check "李四"` → 存在
|
|
350
|
+
2. 提示确认 → 用户确认 → `uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json delete "李四"`
|
|
351
|
+
3. 提示:`🗑️✨ **用户已删除** · 李四`
|
|
352
|
+
|
|
353
|
+
- 用户:「把这些图片放到待搜索目录」
|
|
354
|
+
1. `uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json upload-image "/tmp/a.jpg" "/tmp/b.jpg"`
|
|
355
|
+
2. 全部成功后提示:`✅📤 **已放入待搜索目录** → <folder_path> ✨`
|
|
356
|
+
|
|
357
|
+
## Notes
|
|
358
|
+
|
|
359
|
+
- 建议始终通过 `-c` 传入 `{baseDir}/references/config.json` 的绝对路径,避免相对路径导致找不到配置文件。
|
|
360
|
+
- `search`、`quick-search` 和 `classify` 可能耗时较长(取决于搜索目录中的图片数量),应在**子会话**中执行;**结束后立即关闭并删除该子会话**,再将结果展示与 `pack` 放在**主会话**中完成。
|
|
361
|
+
- `images/` 目录用于存放待搜索图片;`upload-image` 内部会创建当天目录并串行逐张处理图片。
|
|
362
|
+
- 搜索过程中会在图片所在目录下创建 `.embedding` 隐藏目录缓存 embedding 结果,后续搜索同一目录会自动跳过已处理的图片。
|
|
363
|
+
- `pack` 与 `copy` 均依赖 `config.json` 中保存的搜索结果(`search_result` 或 `quick_search_result` 等),须先执行 `search`、`classify` 或 `quick-search`。默认流程只需 **`pack`**;`copy` 为可选,由用户另行提出时再执行。
|
|
364
|
+
- **`classify`** 会向 `friendId` 发**分类结果摘要**;**`pack`** 会向 `friendId` 发**打包下载链接**(两次私信、用途不同);若只需其一,可后续再改脚本或配置(当前实现为两者都发)。
|
|
365
|
+
- `pack` 的压缩文件存放在系统临时目录中,上传完成后可忽略清理。上传超时默认 120 秒,文件特别大时可通过 `--timeout` 增大。
|
|
366
|
+
- `config.json` 中的 `query_threshold`(默认 0.7)控制人脸检测置信度阈值,`search_similarity_threshold`(默认 0.3)控制搜索匹配的最低相似度。
|
|
367
|
+
- `{baseDir}` 指本 skill 根目录(如 `skills/image-classify`),调用时替换为实际绝对路径。
|
|
368
|
+
- `friendId`(虾友号)与可选 `friendLabel` 写在用户条目下;**注册时**通过 `add ... --friend-id` / `--friend-label` 写入。后续若需修改可编辑 `config.json`(本 skill 未单独提供改绑子命令)。旧键名仍兼容读取。
|