sophhub 0.1.4 → 0.2.0

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 (196) hide show
  1. package/README.md +29 -0
  2. package/bin/sophhub.js +2 -0
  3. package/package.json +1 -1
  4. package/skills/aippt/skill.json +20 -0
  5. package/skills/didi-ride/skill.json +20 -0
  6. package/skills/flight-booking/skill.json +20 -0
  7. package/skills/flyai/skill.json +20 -0
  8. package/skills/image-classify/skill.json +42 -0
  9. package/skills/image-classify/src/SKILL.md +375 -0
  10. package/skills/image-classify/src/references/config.json +4 -0
  11. package/skills/image-classify/src/scripts/face_search.py +891 -0
  12. package/skills/inventory-management/skill.json +20 -0
  13. package/skills/lawding-contract-review/skill.json +20 -0
  14. package/skills/schedule-reminder/skill.json +20 -0
  15. package/skills/skill-creator/skill.json +20 -0
  16. package/skills/skillhub/skill.json +20 -0
  17. package/skills/{builtin/skillhub → skillhub/src}/SKILL.md +2 -2
  18. package/skills/sophnet-customer-management/skill.json +20 -0
  19. package/skills/sophnet-customized-marketing/skill.json +28 -0
  20. package/skills/{builtin/sophnet-customized-marketing → sophnet-customized-marketing/src}/SKILL.md +2 -2
  21. package/skills/sophnet-face-search/skill.json +20 -0
  22. package/skills/sophnet-image-edit/skill.json +20 -0
  23. package/skills/sophnet-image-generate/skill.json +20 -0
  24. package/skills/sophnet-image-ocr/skill.json +20 -0
  25. package/skills/sophnet-infinite-talk/skill.json +20 -0
  26. package/skills/sophnet-oss/skill.json +20 -0
  27. package/skills/sophnet-qa-install/skill.json +20 -0
  28. package/skills/sophnet-training-install/skill.json +20 -0
  29. package/skills/sophnet-tts/skill.json +20 -0
  30. package/skills/sophnet-video-generate/skill.json +20 -0
  31. package/skills/ui-ux-pro-max/skill.json +20 -0
  32. package/skills/ui-ux-pro-max/src/SKILL.md +377 -0
  33. package/skills/ui-ux-pro-max/src/data/charts.csv +26 -0
  34. package/skills/ui-ux-pro-max/src/data/colors.csv +97 -0
  35. package/skills/ui-ux-pro-max/src/data/icons.csv +101 -0
  36. package/skills/ui-ux-pro-max/src/data/landing.csv +31 -0
  37. package/skills/ui-ux-pro-max/src/data/products.csv +97 -0
  38. package/skills/ui-ux-pro-max/src/data/react-performance.csv +45 -0
  39. package/skills/ui-ux-pro-max/src/data/stacks/astro.csv +54 -0
  40. package/skills/ui-ux-pro-max/src/data/stacks/flutter.csv +53 -0
  41. package/skills/ui-ux-pro-max/src/data/stacks/html-tailwind.csv +56 -0
  42. package/skills/ui-ux-pro-max/src/data/stacks/jetpack-compose.csv +53 -0
  43. package/skills/ui-ux-pro-max/src/data/stacks/nextjs.csv +53 -0
  44. package/skills/ui-ux-pro-max/src/data/stacks/nuxt-ui.csv +51 -0
  45. package/skills/ui-ux-pro-max/src/data/stacks/nuxtjs.csv +59 -0
  46. package/skills/ui-ux-pro-max/src/data/stacks/react-native.csv +52 -0
  47. package/skills/ui-ux-pro-max/src/data/stacks/react.csv +54 -0
  48. package/skills/ui-ux-pro-max/src/data/stacks/shadcn.csv +61 -0
  49. package/skills/ui-ux-pro-max/src/data/stacks/svelte.csv +54 -0
  50. package/skills/ui-ux-pro-max/src/data/stacks/swiftui.csv +51 -0
  51. package/skills/ui-ux-pro-max/src/data/stacks/vue.csv +50 -0
  52. package/skills/ui-ux-pro-max/src/data/styles.csv +68 -0
  53. package/skills/ui-ux-pro-max/src/data/typography.csv +58 -0
  54. package/skills/ui-ux-pro-max/src/data/ui-reasoning.csv +101 -0
  55. package/skills/ui-ux-pro-max/src/data/ux-guidelines.csv +100 -0
  56. package/skills/ui-ux-pro-max/src/data/web-interface.csv +31 -0
  57. package/skills/ui-ux-pro-max/src/scripts/core.py +253 -0
  58. package/skills/ui-ux-pro-max/src/scripts/design_system.py +1067 -0
  59. package/skills/ui-ux-pro-max/src/scripts/search.py +114 -0
  60. package/skills/video-understand/skill.json +20 -0
  61. package/skills/weather/skill.json +20 -0
  62. package/skills/web-scraper/skill.json +20 -0
  63. package/skills/website-builder/skill.json +20 -0
  64. package/src/commands/download.js +4 -8
  65. package/src/commands/info.js +58 -0
  66. package/src/commands/list.js +6 -13
  67. package/src/utils/paths.js +4 -4
  68. package/src/utils/versions.js +49 -27
  69. package/skills/VERSIONS.md +0 -29
  70. /package/skills/{store/aippt → aippt/src}/SKILL.md +0 -0
  71. /package/skills/{store/aippt → aippt/src}/pyproject.toml +0 -0
  72. /package/skills/{store/aippt → aippt/src}/scripts/auth.py +0 -0
  73. /package/skills/{store/aippt → aippt/src}/scripts/ppt.py +0 -0
  74. /package/skills/{store/aippt → aippt/src}/scripts/provider_docmee.py +0 -0
  75. /package/skills/{store/didi-ride → didi-ride/src}/SKILL.md +0 -0
  76. /package/skills/{store/didi-ride → didi-ride/src}/_meta.json +0 -0
  77. /package/skills/{store/didi-ride → didi-ride/src}/assets/PREFERENCE.md +0 -0
  78. /package/skills/{store/didi-ride → didi-ride/src}/package.json +0 -0
  79. /package/skills/{store/didi-ride → didi-ride/src}/references/api_references.md +0 -0
  80. /package/skills/{store/didi-ride → didi-ride/src}/references/error_handling.md +0 -0
  81. /package/skills/{store/didi-ride → didi-ride/src}/references/setup.md +0 -0
  82. /package/skills/{store/didi-ride → didi-ride/src}/references/workflow.md +0 -0
  83. /package/skills/{builtin/flight-booking → flight-booking/src}/SKILL.md +0 -0
  84. /package/skills/{builtin/flight-booking → flight-booking/src}/scripts/flight_booking.py +0 -0
  85. /package/skills/{store/flyai → flyai/src}/SKILL.md +0 -0
  86. /package/skills/{store/flyai → flyai/src}/references/fliggy-fast-search.md +0 -0
  87. /package/skills/{store/flyai → flyai/src}/references/search-flight.md +0 -0
  88. /package/skills/{store/flyai → flyai/src}/references/search-hotels.md +0 -0
  89. /package/skills/{store/flyai → flyai/src}/references/search-poi.md +0 -0
  90. /package/skills/{builtin/inventory-management → inventory-management/src}/SKILL.md +0 -0
  91. /package/skills/{builtin/inventory-management → inventory-management/src}/scripts/inventory.py +0 -0
  92. /package/skills/{store/lawding-contract-review → lawding-contract-review/src}/SKILL.md +0 -0
  93. /package/skills/{store/lawding-contract-review → lawding-contract-review/src}/references/contract-types.md +0 -0
  94. /package/skills/{store/lawding-contract-review → lawding-contract-review/src}/references/jurisdiction-review-rules.md +0 -0
  95. /package/skills/{store/lawding-contract-review → lawding-contract-review/src}/references/legal-language-library.md +0 -0
  96. /package/skills/{store/lawding-contract-review → lawding-contract-review/src}/references/review-methodology.md +0 -0
  97. /package/skills/{store/lawding-contract-review → lawding-contract-review/src}/references/risk-templates.md +0 -0
  98. /package/skills/{store/lawding-contract-review → lawding-contract-review/src}/scripts/build_reminders.py +0 -0
  99. /package/skills/{store/lawding-contract-review → lawding-contract-review/src}/scripts/register_contract_cron.py +0 -0
  100. /package/skills/{builtin/schedule-reminder → schedule-reminder/src}/SKILL.md +0 -0
  101. /package/skills/{builtin/schedule-reminder → schedule-reminder/src}/schedule_template.md +0 -0
  102. /package/skills/{builtin/schedule-reminder → schedule-reminder/src}/scripts/append_event.py +0 -0
  103. /package/skills/{builtin/schedule-reminder → schedule-reminder/src}/scripts/create_reminders.sh +0 -0
  104. /package/skills/{builtin/schedule-reminder → schedule-reminder/src}/scripts/daily_activate.sh +0 -0
  105. /package/skills/{builtin/schedule-reminder → schedule-reminder/src}/scripts/parse_schedule.py +0 -0
  106. /package/skills/{builtin/schedule-reminder → schedule-reminder/src}/scripts/setup.sh +0 -0
  107. /package/skills/{builtin/schedule-reminder → schedule-reminder/src}//347/224/250/346/210/267/346/214/207/345/215/227.md" +0 -0
  108. /package/skills/{builtin/skill-creator → skill-creator/src}/SKILL.md +0 -0
  109. /package/skills/{builtin/skill-creator → skill-creator/src}/license.txt +0 -0
  110. /package/skills/{builtin/skill-creator → skill-creator/src}/scripts/init_skill.py +0 -0
  111. /package/skills/{builtin/skill-creator → skill-creator/src}/scripts/package_skill.py +0 -0
  112. /package/skills/{builtin/skill-creator → skill-creator/src}/scripts/quick_validate.py +0 -0
  113. /package/skills/{builtin/sophnet-customer-management → sophnet-customer-management/src}/SKILL.md +0 -0
  114. /package/skills/{builtin/sophnet-customer-management → sophnet-customer-management/src}/pyproject.toml +0 -0
  115. /package/skills/{builtin/sophnet-customer-management → sophnet-customer-management/src}/src/customer_mgmt_cli/__init__.py +0 -0
  116. /package/skills/{builtin/sophnet-customer-management → sophnet-customer-management/src}/src/customer_mgmt_cli/__main__.py +0 -0
  117. /package/skills/{builtin/sophnet-customer-management → sophnet-customer-management/src}/src/customer_mgmt_cli/cli.py +0 -0
  118. /package/skills/{builtin/sophnet-customer-management → sophnet-customer-management/src}/src/customer_mgmt_cli/commands/__init__.py +0 -0
  119. /package/skills/{builtin/sophnet-customer-management → sophnet-customer-management/src}/src/customer_mgmt_cli/commands/customer.py +0 -0
  120. /package/skills/{builtin/sophnet-customer-management → sophnet-customer-management/src}/src/customer_mgmt_cli/commands/export_file.py +0 -0
  121. /package/skills/{builtin/sophnet-customer-management → sophnet-customer-management/src}/src/customer_mgmt_cli/commands/import_file.py +0 -0
  122. /package/skills/{builtin/sophnet-customer-management → sophnet-customer-management/src}/src/customer_mgmt_cli/commands/reminder.py +0 -0
  123. /package/skills/{builtin/sophnet-customer-management → sophnet-customer-management/src}/src/customer_mgmt_cli/commands/schema.py +0 -0
  124. /package/skills/{builtin/sophnet-customer-management → sophnet-customer-management/src}/src/customer_mgmt_cli/config.py +0 -0
  125. /package/skills/{builtin/sophnet-customer-management → sophnet-customer-management/src}/src/customer_mgmt_core/__init__.py +0 -0
  126. /package/skills/{builtin/sophnet-customer-management → sophnet-customer-management/src}/src/customer_mgmt_core/exporter.py +0 -0
  127. /package/skills/{builtin/sophnet-customer-management → sophnet-customer-management/src}/src/customer_mgmt_core/models.py +0 -0
  128. /package/skills/{builtin/sophnet-customer-management → sophnet-customer-management/src}/src/customer_mgmt_core/normalizer.py +0 -0
  129. /package/skills/{builtin/sophnet-customer-management → sophnet-customer-management/src}/src/customer_mgmt_core/parser.py +0 -0
  130. /package/skills/{builtin/sophnet-customer-management → sophnet-customer-management/src}/src/customer_mgmt_core/query.py +0 -0
  131. /package/skills/{builtin/sophnet-customer-management → sophnet-customer-management/src}/src/customer_mgmt_core/reminder.py +0 -0
  132. /package/skills/{builtin/sophnet-customer-management → sophnet-customer-management/src}/src/customer_mgmt_core/repository.py +0 -0
  133. /package/skills/{builtin/sophnet-customer-management → sophnet-customer-management/src}/src/customer_mgmt_core/schema.py +0 -0
  134. /package/skills/{builtin/sophnet-customer-management → sophnet-customer-management/src}/src/customer_mgmt_core/service.py +0 -0
  135. /package/skills/{builtin/sophnet-customer-management → sophnet-customer-management/src}/uv.lock +0 -0
  136. /package/skills/{builtin/sophnet-customized-marketing → sophnet-customized-marketing/src}/playbooks/campaign-planning.md +0 -0
  137. /package/skills/{builtin/sophnet-customized-marketing → sophnet-customized-marketing/src}/playbooks/content-generation.md +0 -0
  138. /package/skills/{builtin/sophnet-customized-marketing → sophnet-customized-marketing/src}/playbooks/marketing-calendar.md +0 -0
  139. /package/skills/{builtin/sophnet-customized-marketing → sophnet-customized-marketing/src}/playbooks/multi-channel-bundle.md +0 -0
  140. /package/skills/{builtin/sophnet-customized-marketing → sophnet-customized-marketing/src}/playbooks/poster-generation.md +0 -0
  141. /package/skills/{builtin/sophnet-customized-marketing → sophnet-customized-marketing/src}/playbooks/style-profile-workflow.md +0 -0
  142. /package/skills/{builtin/sophnet-customized-marketing → sophnet-customized-marketing/src}/pyproject.toml +0 -0
  143. /package/skills/{builtin/sophnet-customized-marketing → sophnet-customized-marketing/src}/references/campaign-mechanics.md +0 -0
  144. /package/skills/{builtin/sophnet-customized-marketing → sophnet-customized-marketing/src}/references/content-safety.md +0 -0
  145. /package/skills/{builtin/sophnet-customized-marketing → sophnet-customized-marketing/src}/references/marketing-date-checklist.md +0 -0
  146. /package/skills/{builtin/sophnet-customized-marketing → sophnet-customized-marketing/src}/references/platform-writing-guidelines.md +0 -0
  147. /package/skills/{builtin/sophnet-customized-marketing → sophnet-customized-marketing/src}/references/quality-checklist.md +0 -0
  148. /package/skills/{builtin/sophnet-customized-marketing → sophnet-customized-marketing/src}/scripts/generate_poster.py +0 -0
  149. /package/skills/{builtin/sophnet-customized-marketing → sophnet-customized-marketing/src}/scripts/style_profile.py +0 -0
  150. /package/skills/{builtin/sophnet-face-search → sophnet-face-search/src}/SKILL.md +0 -0
  151. /package/skills/{builtin/sophnet-face-search → sophnet-face-search/src}/pyproject.toml +0 -0
  152. /package/skills/{builtin/sophnet-face-search → sophnet-face-search/src}/scripts/face_search.py +0 -0
  153. /package/skills/{builtin/sophnet-face-search → sophnet-face-search/src}/uv.lock +0 -0
  154. /package/skills/{builtin/sophnet-image-edit → sophnet-image-edit/src}/SKILL.md +0 -0
  155. /package/skills/{builtin/sophnet-image-edit → sophnet-image-edit/src}/pyproject.toml +0 -0
  156. /package/skills/{builtin/sophnet-image-edit → sophnet-image-edit/src}/scripts/edit_and_preview.sh +0 -0
  157. /package/skills/{builtin/sophnet-image-edit → sophnet-image-edit/src}/scripts/edit_image.py +0 -0
  158. /package/skills/{builtin/sophnet-image-edit → sophnet-image-edit/src}/uv.lock +0 -0
  159. /package/skills/{builtin/sophnet-image-generate → sophnet-image-generate/src}/SKILL.md +0 -0
  160. /package/skills/{builtin/sophnet-image-generate → sophnet-image-generate/src}/pyproject.toml +0 -0
  161. /package/skills/{builtin/sophnet-image-generate → sophnet-image-generate/src}/scripts/generate_image.py +0 -0
  162. /package/skills/{builtin/sophnet-image-generate → sophnet-image-generate/src}/uv.lock +0 -0
  163. /package/skills/{builtin/sophnet-image-ocr → sophnet-image-ocr/src}/SKILL.md +0 -0
  164. /package/skills/{builtin/sophnet-image-ocr → sophnet-image-ocr/src}/pyproject.toml +0 -0
  165. /package/skills/{builtin/sophnet-image-ocr → sophnet-image-ocr/src}/scripts/ocr.py +0 -0
  166. /package/skills/{builtin/sophnet-image-ocr → sophnet-image-ocr/src}/uv.lock +0 -0
  167. /package/skills/{builtin/sophnet-infinite-talk → sophnet-infinite-talk/src}/SKILL.md +0 -0
  168. /package/skills/{builtin/sophnet-infinite-talk → sophnet-infinite-talk/src}/pyproject.toml +0 -0
  169. /package/skills/{builtin/sophnet-infinite-talk → sophnet-infinite-talk/src}/scripts/gen.py +0 -0
  170. /package/skills/{builtin/sophnet-oss → sophnet-oss/src}/SKILL.md +0 -0
  171. /package/skills/{builtin/sophnet-oss → sophnet-oss/src}/pyproject.toml +0 -0
  172. /package/skills/{builtin/sophnet-oss → sophnet-oss/src}/scripts/upload_file.py +0 -0
  173. /package/skills/{builtin/sophnet-qa-install → sophnet-qa-install/src}/SKILL.md +0 -0
  174. /package/skills/{builtin/sophnet-qa-install → sophnet-qa-install/src}/pyproject.toml +0 -0
  175. /package/skills/{builtin/sophnet-qa-install → sophnet-qa-install/src}/scripts/backup_md.py +0 -0
  176. /package/skills/{builtin/sophnet-qa-install → sophnet-qa-install/src}/scripts/check_installed.py +0 -0
  177. /package/skills/{builtin/sophnet-qa-install → sophnet-qa-install/src}/scripts/update_config.py +0 -0
  178. /package/skills/{builtin/sophnet-qa-install → sophnet-qa-install/src}/scripts/update_md.py +0 -0
  179. /package/skills/{builtin/sophnet-training-install → sophnet-training-install/src}/SKILL.md +0 -0
  180. /package/skills/{builtin/sophnet-training-install → sophnet-training-install/src}/pyproject.toml +0 -0
  181. /package/skills/{builtin/sophnet-training-install → sophnet-training-install/src}/scripts/backup_md.py +0 -0
  182. /package/skills/{builtin/sophnet-training-install → sophnet-training-install/src}/scripts/check_installed.py +0 -0
  183. /package/skills/{builtin/sophnet-training-install → sophnet-training-install/src}/scripts/update_config.py +0 -0
  184. /package/skills/{builtin/sophnet-training-install → sophnet-training-install/src}/scripts/update_md.py +0 -0
  185. /package/skills/{builtin/sophnet-tts → sophnet-tts/src}/SKILL.md +0 -0
  186. /package/skills/{builtin/sophnet-tts → sophnet-tts/src}/pyproject.toml +0 -0
  187. /package/skills/{builtin/sophnet-tts → sophnet-tts/src}/scripts/gen_tts.py +0 -0
  188. /package/skills/{builtin/sophnet-video-generate → sophnet-video-generate/src}/SKILL.md +0 -0
  189. /package/skills/{builtin/sophnet-video-generate → sophnet-video-generate/src}/scripts/gen_video.py +0 -0
  190. /package/skills/{builtin/video-understand → video-understand/src}/SKILL.md +0 -0
  191. /package/skills/{builtin/video-understand → video-understand/src}/scripts/video_understand.py +0 -0
  192. /package/skills/{builtin/weather → weather/src}/SKILL.md +0 -0
  193. /package/skills/{builtin/web-scraper → web-scraper/src}/SKILL.md +0 -0
  194. /package/skills/{builtin/web-scraper → web-scraper/src}/scripts/scrape.py +0 -0
  195. /package/skills/{builtin/website-builder → website-builder/src}/SKILL.md +0 -0
  196. /package/skills/{builtin/website-builder → website-builder/src}/scripts/deploy_site.sh +0 -0
package/README.md CHANGED
@@ -59,6 +59,34 @@ sophhub download --type builtin -o ./skills
59
59
  sophhub download --type store -o ./skills
60
60
  ```
61
61
 
62
+ ### 查看 Skill 详细信息
63
+
64
+ 查看某个 Skill 的完整元数据(版本、类型、描述、changelog 等):
65
+
66
+ ```bash
67
+ sophhub info flight-booking
68
+ ```
69
+
70
+ 输出示例:
71
+
72
+ ```
73
+ Skill: flight-booking
74
+ Version: 1.1.0
75
+ Types: builtin
76
+ Created: 2026-04-09
77
+ Updated: 2026-04-09
78
+
79
+ Changelog:
80
+ v1.1.0 (2026-04-09)
81
+ - 初次提交
82
+ ```
83
+
84
+ 以 JSON 格式输出完整 `skill.json` 内容:
85
+
86
+ ```bash
87
+ sophhub info aippt --json
88
+ ```
89
+
62
90
  ### 查看版本
63
91
 
64
92
  ```bash
@@ -71,6 +99,7 @@ sophhub --version
71
99
  sophhub --help
72
100
  sophhub list --help
73
101
  sophhub download --help
102
+ sophhub info --help
74
103
  ```
75
104
 
76
105
  ## 配置
package/bin/sophhub.js CHANGED
@@ -4,6 +4,7 @@ import { createRequire } from 'node:module';
4
4
  import { Command } from 'commander';
5
5
  import { registerListCommand } from '../src/commands/list.js';
6
6
  import { registerDownloadCommand } from '../src/commands/download.js';
7
+ import { registerInfoCommand } from '../src/commands/info.js';
7
8
 
8
9
  const require = createRequire(import.meta.url);
9
10
  const pkg = require('../package.json');
@@ -17,5 +18,6 @@ program
17
18
 
18
19
  registerListCommand(program);
19
20
  registerDownloadCommand(program);
21
+ registerInfoCommand(program);
20
22
 
21
23
  program.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sophhub",
3
- "version": "0.1.4",
3
+ "version": "0.2.0",
4
4
  "description": "SophHub CLI - Manage and download AI Agent skills",
5
5
  "type": "module",
6
6
  "bin": {
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "aippt",
3
+ "version": "1.0.0",
4
+ "types": [
5
+ "store"
6
+ ],
7
+ "displayName": "AI PPT 生成",
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
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "didi-ride",
3
+ "version": "1.0.0",
4
+ "types": [
5
+ "store"
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
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "flight-booking",
3
+ "version": "1.1.0",
4
+ "types": [
5
+ "builtin"
6
+ ],
7
+ "displayName": "国内机票预定",
8
+ "description": "",
9
+ "changelog": [
10
+ {
11
+ "changes": [
12
+ "初次提交"
13
+ ],
14
+ "date": "2026-04-09",
15
+ "version": "1.1.0"
16
+ }
17
+ ],
18
+ "createdAt": "2026-04-09",
19
+ "updatedAt": "2026-04-09"
20
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "flyai",
3
+ "version": "1.0.10",
4
+ "types": [
5
+ "store"
6
+ ],
7
+ "displayName": "飞猪旅行",
8
+ "description": "机票、酒店、景点门票、旅行搜索与预订",
9
+ "changelog": [
10
+ {
11
+ "version": "1.0.10",
12
+ "date": "2026-04-09",
13
+ "changes": [
14
+ "初次提交"
15
+ ]
16
+ }
17
+ ],
18
+ "createdAt": "2026-04-09",
19
+ "updatedAt": "2026-04-09"
20
+ }
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "image-classify",
3
+ "version": "1.0.3",
4
+ "types": [
5
+ "store"
6
+ ],
7
+ "displayName": "照片分类器",
8
+ "description": "通过人脸识别对照片进行分类、搜索和管理",
9
+ "changelog": [
10
+ {
11
+ "changes": [
12
+ "脚本内 pathlib 全部改为 os.path(递归列举图片、复制与打包等路径处理);list_images_pathlib 重命名为 list_images_recursive"
13
+ ],
14
+ "date": "2026-04-10",
15
+ "version": "1.0.3"
16
+ },
17
+ {
18
+ "changes": [
19
+ "配置文件读写统一使用 UTF-8 编码(open 显式指定 encoding)"
20
+ ],
21
+ "date": "2026-04-10",
22
+ "version": "1.0.2"
23
+ },
24
+ {
25
+ "changes": [
26
+ "1.添加了上传图片的支持",
27
+ "2.添加默认的工作路径"
28
+ ],
29
+ "date": "2026-04-10",
30
+ "version": "1.0.1"
31
+ },
32
+ {
33
+ "changes": [
34
+ "初次提交"
35
+ ],
36
+ "date": "2026-04-10",
37
+ "version": "1.0.0"
38
+ }
39
+ ],
40
+ "createdAt": "2026-04-10",
41
+ "updatedAt": "2026-04-10"
42
+ }
@@ -0,0 +1,375 @@
1
+ ---
2
+ name: image-classify
3
+ description: 照片分类器。通过人脸识别对照片进行分类、搜索和管理。当用户说「用照片分类器查找/搜索 xxx」「对 xx 文件夹进行分类」「添加 xx 到照片分类器」「从照片分类器删除 xx」时使用。
4
+ ---
5
+
6
+ # 📸 照片分类器
7
+
8
+ 基于人脸 embedding 相似度的照片分类系统。支持注册用户人脸、按用户搜索照片、一键全量分类、删除用户;搜索/分类结束后**先自动生成下载链接**,再**询问是否复制到指定文件夹**。
9
+
10
+ ## Processing Mode
11
+
12
+ **STRICT SERIAL PROCESSING ONLY** — 单次顺序执行,不拆分子任务、不并行。
13
+
14
+ **子会话(耗时任务)**:`search`、`quick-search`、`classify` 在**独立子会话**中执行。**子命令结束(成功或失败)后,须立即关闭并删除该子会话**,不得保留空壳会话。后续步骤——向用户展示结果表格、执行 `pack`、询问是否 `copy`——一律在**当前主会话**中完成。
15
+
16
+ ## Prerequisites
17
+
18
+ - Python 3.10+、uv
19
+ - 依赖:`requests`, `opencv-python`, `numpy`, `sophnet_tools`(项目内置)
20
+ - 配置文件:`{baseDir}/references/config.json`
21
+
22
+ ## 核心概念
23
+
24
+ - **`{baseDir}`**:本 skill 根目录,即 `skills/image-classify`,调用时替换为实际绝对路径。
25
+ - **配置文件**:`{baseDir}/references/config.json`,存储所有注册用户的名称、照片路径及人脸 embedding 向量。
26
+ - **脚本入口**:`{baseDir}/scripts/face_search.py`,通过 `uv run` 以子命令方式调用。
27
+ - **所有命令输出均为 JSON 格式**,方便解析结果。
28
+
29
+ ## 通用调用格式
30
+
31
+ ```bash
32
+ uv run {baseDir}/scripts/face_search.py [-c CONFIG_PATH] <command> [args...]
33
+ ```
34
+
35
+ `-c` / `--config` 可选,指定配置文件路径,默认为 `references/config.json`(相对于执行目录)。建议始终传入绝对路径 `{baseDir}/references/config.json`。
36
+
37
+ ## 可用命令一览
38
+
39
+ | 命令 | 用途 | 示例 |
40
+ |------|------|------|
41
+ | `check <name>` | 检查用户名是否已注册 | `check 张三` |
42
+ | `add <name> <image>` | 注册新用户 | `add 张三 /path/photo.jpg` |
43
+ | `replace <name> <image>` | 替换用户照片(删除旧照片) | `replace 张三 /path/new.jpg` |
44
+ | `append <name> <image>` | 为已有用户追加一张照片 | `append 张三 /path/extra.jpg` |
45
+ | `rename <old> <new>` | 修改用户名 | `rename 张三 李三` |
46
+ | `delete <name>` | 删除用户 | `delete 张三` |
47
+ | `search <name> <dir>` | 在目录中搜索某用户的相似人脸 | `search 张三 /home/photos` |
48
+ | `quick-search <image> <dir>` | 直接用照片搜索相似人脸(不注册) | `quick-search /tmp/face.jpg /home/photos` |
49
+ | `classify <dir>` | 一键分类:遍历所有用户搜索全部照片 | `classify /home/photos` |
50
+ | `copy <target> [--name N]` | 将搜索结果复制到文件夹 | `copy /output --name 张三` |
51
+ | `pack [--name N] [--timeout T]` | 压缩结果为 zip 并上传获取下载链接 | `pack --timeout 120` |
52
+ | `upload <file> [--timeout T]` | 上传文件获取 URL | `upload /path/file.zip` |
53
+ | `init-today-folder` | 创建并返回待搜索目录当天子目录 | `init-today-folder` |
54
+ | `upload-image <file...>` | 将一张或多张图片串行剪切到待搜索目录 `images/当天日期(YYYYMMDD)` | `upload-image /tmp/a.jpg /tmp/b.jpg` |
55
+ | `list-date-folders` | 列出待搜索根目录 `images` 下全部 `YYYYMMDD` 子文件夹(新→旧),供未指定目录时选择 | `list-date-folders` |
56
+
57
+ > ⚠️ 注意:如果用户发送的图片格式为 `![image](xxx.jpg)`,需要先执行 `upload` 命令将其转换为 URL 格式后再处理。
58
+
59
+ ## Usage
60
+
61
+ 根据用户意图匹配以下操作流程:
62
+
63
+ ### 未指定搜索目录时(`search` / `quick-search` / `classify` 共用)
64
+
65
+ 待搜索根目录由脚本内 `get_images_path()` 解析(通常为仓库上级 `images`)。其下按日期命名的子目录(`YYYYMMDD`)为可选搜索范围。
66
+
67
+ 若用户**未说明**搜索目录(或只说「默认目录」「最近上传的」等),**不要猜测路径**,先执行:
68
+
69
+ ```bash
70
+ uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json list-date-folders
71
+ ```
72
+
73
+ 输出 JSON 字段说明:
74
+ - `folders`:全部合法日期文件夹,`{ "name": "20260410", "path": "/绝对路径/20260410" }`,已按日期**从新到旧**排序
75
+ - `preview` / `preview_n`:默认只向用户展示**最近 `preview_n` 个(默认 3 个)**即可
76
+ - `total`:总数;若大于 `preview_n`,用户可说「更多」「全部」「列出全部」——此时用 Markdown 列出剩余项(**只展示 `name`**,不罗列每条 `path`),再请用户回复**序号**或**日期名(YYYYMMDD)**;用户若粘贴目录路径则按路径解析
77
+
78
+ 选定目录后,将解析出的**绝对路径**作为 `<dir>` 传入 `search` / `quick-search` / `classify`。
79
+
80
+ 若 `folders` 为空,提示用户在 `images` 下先上传或创建日期目录(可用 `init-today-folder`、`upload-image`),或**手动提供**任意搜索目录路径。
81
+
82
+ **向用户展示候选目录时(示例模版)** — 用 Markdown 呈现,**只展示日期文件夹名**,不要把磁盘绝对路径列给用户:
83
+
84
+ - 📅📂 **最近可用的日期文件夹(任选其一)**
85
+ - 1️⃣ 📁 `20260410`
86
+
87
+ - 2️⃣ 📁 `20260409`
88
+
89
+ - 3️⃣ 📁 `20260408`
90
+ - 💬 请回复**序号**或**日期名**;需要查看更多请说「更多」。内部调用命令时仍使用 JSON 里的 `path` 字段。✨
91
+
92
+ ### 1. 添加/注册用户
93
+
94
+ **触发词**:「添加 xxx 到照片分类器」「注册 xxx」「把这张照片记为 xxx」
95
+
96
+ **流程**:
97
+
98
+ 1. 获取用户提供的**用户名**和**照片路径**
99
+ 2. 检查用户名是否已存在:
100
+ ```bash
101
+ uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json check "张三"
102
+ ```
103
+ 输出:`{"exists": true/false, "name": "张三"}`
104
+
105
+ 3. **如果不存在** → 注册新用户:
106
+ ```bash
107
+ uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json add "张三" "/path/to/photo.jpg"
108
+ ```
109
+ 输出:`{"success": true/false, "message": "...", "name": "张三", "image_url": "https://..."}`
110
+ - `success: true` → 提示:`🎉✨ **注册成功** · xxx`,并使用返回的 `image_url` 展示照片:`![image](image_url)`
111
+ - `success: false` → 提示:`❌🙈 照片中未发现有效的人脸信息,注册失败!`
112
+
113
+ 4. **如果已存在** → 提示用户选择操作:
114
+ ```
115
+ ⚡👤 用户名已存在,请选择操作:
116
+ 1️⃣ 🔄 更新照片(替换主照片)
117
+ 2️⃣ ✏️ 重新命名
118
+ 3️⃣ ➕ 同时保留多张照片
119
+ ```
120
+ - **更新照片**:
121
+ ```bash
122
+ uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json replace "张三" "/path/to/new.jpg"
123
+ ```
124
+ 输出包含 `image_url` 字段。
125
+ - 成功:`✅🔄 **照片已更新** · xxx`,使用 `image_url` 展示照片:`![image](image_url)`
126
+ - 失败:`❌🙈 照片中未发现有效的人脸信息,更新失败!`
127
+ - **重新命名**:
128
+ ```bash
129
+ uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json rename "张三" "李三"
130
+ ```
131
+ - 提示:`✏️📛 **用户名已更新** · xxx → yyy`
132
+ - **保留多张**:
133
+ ```bash
134
+ uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json append "张三" "/path/to/extra.jpg"
135
+ ```
136
+ 输出包含 `image_url` 字段。
137
+ - 成功:`✅➕ **新照片已追加** · xxx`,使用 `image_url` 展示照片:`![image](image_url)`
138
+ - 失败:`❌🙈 照片中未发现有效的人脸信息,添加失败!`
139
+
140
+ ### 2. 搜索用户照片
141
+
142
+ **触发词**:「用照片分类器在 yy 文件夹下查找 xxx」「搜索 xxx 的照片」
143
+
144
+ **流程**:
145
+
146
+ 1. 从用户表述中提取**用户名**和**搜索目录**。若**未指定搜索目录**,先按上文「未指定搜索目录时」列出最近 3 个日期文件夹供选择(支持「更多」展示全部),得到 `<dir>` 后再继续。
147
+ 2. 检查用户名是否存在(`check` 命令),不存在则提示:`❌🔍 **未找到该用户** · 请确认姓名后重试`
148
+ 3. 使用**子会话**执行搜索(可能耗时较长):
149
+ ```bash
150
+ uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json search "张三" "<dir>"
151
+ ```
152
+ (`<dir>` 为用户指定路径,或从 `list-date-folders` 选中的 `path`。)**命令返回后立刻关闭并删除该子会话。**
153
+ 输出:
154
+ ```json
155
+ {"name": "张三", "count": 3, "results": [{"image_path": "...", "face_index": 0, "similarity": 0.85}, ...]}
156
+ ```
157
+ 4. 将结果通知到当前会话,以表格形式展示:
158
+ ```
159
+ 🔎✨ **人脸搜索结果** · 👤 <用户名>
160
+ ───────────────────────
161
+ ```
162
+ | 🖼️ 照片路径 | 📊 相似度 |
163
+ |:----:|:----:|
164
+ | /path/to/photo.jpg | 0.85 |
165
+ 5. 展示结果后按「结果导出」流程处理:先 `pack` 生成下载链接,再询问是否复制到文件夹(见 §6)
166
+
167
+ ### 3. 直接搜索(不注册)
168
+
169
+ **触发词**:「用这张照片搜索 yy 文件夹」「直接用照片查找」「不注册直接搜」
170
+
171
+ **流程**:
172
+
173
+ 1. 获取用户提供的**照片路径**和**搜索目录**。若**未指定搜索目录**,先按「未指定搜索目录时」列出最近 3 个日期文件夹供选择(支持「更多」),得到 `<dir>` 后再继续。
174
+ 2. 使用**子会话**执行搜索(先提取人脸 embedding,再匹配,可能耗时较长):
175
+ ```bash
176
+ uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json quick-search "/path/to/face.jpg" "<dir>"
177
+ ```
178
+ **命令返回后立刻关闭并删除该子会话。**
179
+ 输出:
180
+ ```json
181
+ {"success": true/false, "count": 3, "results": [...], "message": "..."}
182
+ ```
183
+ - `success: false` → 表示照片中未检测到有效人脸,提示:`❌🙈 **未检测到人脸** · 无法搜索`
184
+ 3. 将结果通知到当前会话,以表格形式展示:
185
+ ```
186
+ 🪪🖼️ **直接搜索**(未注册)· 已用查询图匹配
187
+ ───────────────────────
188
+ ```
189
+ | 🖼️ 照片路径 | 📊 相似度 |
190
+ |:----:|:----:|
191
+ | /path/to/photo.jpg | 0.85 |
192
+ 4. 展示结果后按「结果导出」流程处理:先 `pack` 生成下载链接,再询问是否复制到文件夹(见 §6)
193
+
194
+ ### 4. 一键分类
195
+
196
+ **触发词**:「用照片分类器对 xx 文件夹进行分类」「一键分类」「对这些照片按人分类」
197
+
198
+ **流程**:
199
+
200
+ 1. 从用户表述中提取**搜索目录**。若**未指定搜索目录**,先按「未指定搜索目录时」列出最近 3 个日期文件夹供选择(支持「更多」),得到 `<dir>` 后再继续。
201
+ 2. 使用**子会话**执行分类(可能耗时较长):
202
+ ```bash
203
+ uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json classify "<dir>"
204
+ ```
205
+ **命令返回后立刻关闭并删除该子会话。**
206
+ 输出:
207
+ ```json
208
+ {"user_count": 2, "users": {"张三": {"count": 3, "results": [...]}, "李四": {"count": 1, "results": [...]}}}
209
+ ```
210
+ - `user_count: 0` → 提示:`❌👥 **暂无注册用户** · 请先注册人脸后再分类`
211
+ 3. 将结果通知到当前会话,对每个用户分别展示:
212
+ ```
213
+ 🗂️✨ **一键分类完成** · 共 👥 N 位注册用户参与匹配
214
+ ───────────────────────
215
+ ```
216
+ 对每个有匹配结果的用户:
217
+ ```
218
+ 👤✅ **张三** · 📸 匹配 M 张
219
+ ```
220
+ | 🖼️ 照片路径 | 📊 相似度 |
221
+ |:----:|:----:|
222
+ | /path/to/photo.jpg | 0.85 |
223
+
224
+ 无匹配结果的用户:
225
+ ```
226
+ 👤💤 **王五** · 本轮暂无匹配
227
+ ```
228
+ 4. 展示结果后按「结果导出」流程处理:先 `pack` 生成下载链接,再询问是否复制到文件夹(见 §6)
229
+
230
+ ### 5. 删除用户
231
+
232
+ **触发词**:「删除照片分类器中 xxx 的信息」「把 xxx 从照片分类器移除」
233
+
234
+ **流程**:
235
+
236
+ 1. 从用户表述中提取**用户名**
237
+ 2. 检查用户名是否存在(`check` 命令),不存在则提示:`❌🔍 **未找到该用户** · 请确认姓名后重试`
238
+ 3. 提示确认:`⚠️🗑️ **确认删除用户 xxx?** · 此操作不可撤销`
239
+ - 用户确认 →
240
+ ```bash
241
+ uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json delete "张三"
242
+ ```
243
+ 提示:`🗑️✨ **用户已删除** · xxx`
244
+ - 用户取消 → 提示:`↩️👋 **已取消删除**`
245
+
246
+ ### 6. 结果导出(搜索/分类完成后)
247
+
248
+ 搜索或分类完成后,结果已保存在 `config.json` 中。展示匹配结果表格后,**不要先弹出菜单**,按下面顺序执行。
249
+
250
+ #### 第一步:直接生成下载链接
251
+
252
+ 立即执行 `pack`(压缩包可能较大,超时默认 120 秒),将返回的链接展示给用户:
253
+
254
+ - **单用户 `search`**(指定 `--name`):
255
+ ```bash
256
+ uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json pack --name "张三" --timeout 120
257
+ ```
258
+ 输出:`{"success": true, "url": "https://...", "zip_path": "/tmp/.../search_results.zip"}`
259
+ 成功提示:`📦🔗 **下载链接已就绪** ✨` → `<url>`
260
+
261
+ - **`quick-search`(直接搜索)**:结果存于 `quick_search_result`,执行 **不带 `--name`** 的 `pack`(与仅含直接搜索结果时一致):
262
+ ```bash
263
+ uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json pack --timeout 120
264
+ ```
265
+ 成功提示:`📦🔗 **下载链接已就绪** ✨` → `<url>`
266
+
267
+ - **一键 `classify`**(不指定 `--name`,**每位用户单独打包**):
268
+ ```bash
269
+ uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json pack --timeout 120
270
+ ```
271
+ 输出示例:
272
+ ```json
273
+ {"success": true, "user_urls": {"张三": "https://...", "李四": "https://..."}, "errors": null}
274
+ ```
275
+ 成功提示:逐用户展示链接,例如:
276
+ ```
277
+ 📦✨ **各用户独立下载包**
278
+ ───────────────────────
279
+ 👤 张三 📎 <url>
280
+ 👤 李四 📎 <url>
281
+ ```
282
+ 部分失败:列出已成功链接,并对失败用户提示:`⚠️❌ **<用户名>** · 下载包生成失败:<原因>`。全部失败:`❌📦 下载链接全部失败`(仍进入第二步询问复制,便于用户落盘)。
283
+
284
+ #### 第二步:再询问是否复制到指定文件夹
285
+
286
+ 下载链接处理完毕后,询问用户:
287
+
288
+ ```
289
+ 💾📂 **要不要把匹配照片复制到本地?**
290
+ ✅ 需要 → 💬 请发目标文件夹路径
291
+ 👋 不用了 → 到这里结束 ✨
292
+ ```
293
+
294
+ 用户选择**需要**时,再问 `📂✏️ 请输入目标文件夹路径:` 并执行:
295
+
296
+ - **单用户 `search`**(注册用户搜索结果):
297
+ ```bash
298
+ uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json copy "/output/folder" --name "张三"
299
+ ```
300
+
301
+ - **`quick-search`**(结果为列表、无注册用户名):**不带** `--name`:
302
+ ```bash
303
+ uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json copy "/output/folder"
304
+ ```
305
+
306
+ - **一键 `classify`**(不指定 `--name`,按用户名自动建子目录):
307
+ ```bash
308
+ uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json copy "/output/folder"
309
+ ```
310
+
311
+ 输出:`{"success": true, "copied": 5, "failed": 0, "target": "/output/folder"}`
312
+ - 成功:`✅📁 **复制完成** · 共 N 张 → /path/to/target/`
313
+ - 部分失败:`⚠️📋 **复制结束** · 成功 N 张 · 失败 M 张`
314
+
315
+ 用户选择**不需要**则结束,无需再执行 `copy`。
316
+
317
+ ### 7. 上传图片到待搜索目录
318
+
319
+ **触发词**:「上传这张图片到待搜索目录」「上传这些图片到待搜索目录」「上传这些照片」「把图片放到今天目录供搜索」「把图片移到待搜索目录」
320
+
321
+ **流程**:
322
+
323
+ 1. 获取用户提供的**图片路径**(支持单张或多张)
324
+ 2. 直接执行:
325
+ ```bash
326
+ uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json upload-image "/path/to/a.jpg" "/path/to/b.jpg"
327
+ ```
328
+ 3. 单张时输出:`{"success": true/false, "folder_path": "/abs/path/to/images/YYYYMMDD", "file_path": "/abs/path/to/images/YYYYMMDD/a.jpg", "failed": []}`
329
+ 4. 多张时输出:`{"success": true/false, "folder_path": "/abs/path/to/images/YYYYMMDD", "uploaded": [...], "failed": [...]}`
330
+ 5. 成功后提示:`✅📤 **已放入待搜索目录** → <folder_path> ✨`;如果有失败文件,提示:`⚠️ 部分失败:` 并列出项。
331
+
332
+ ## Example Workflow
333
+
334
+ - 用户:「把这张照片添加为张三」
335
+ 1. `uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json check "张三"`
336
+ 2. 不存在 → `uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json add "张三" "/path/to/photo.jpg"`
337
+ 3. 提示:`🎉✨ **注册成功** · 张三`
338
+
339
+ - 用户:「用照片分类器在 /home/photos 下查找张三」
340
+ 1. `uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json check "张三"` → 存在
341
+ 2. 子会话执行 `uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json search "张三" "/home/photos"`
342
+ 3. 展示结果表格 → **直接** `pack --name "张三" --timeout 120` 生成链接 → 再问是否 `copy`(见 §6)
343
+
344
+ - 用户:「用这张照片在 /home/photos 里找找有没有类似的」
345
+ 1. 子会话执行 `uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json quick-search "/tmp/face.jpg" "/home/photos"`
346
+ 2. 成功 → 展示表格 → **直接** `pack --timeout 120`(不带 `--name`)→ 再问是否 `copy`;失败 → 提示未检测到有效人脸
347
+
348
+ - 用户:「用照片分类器对 /home/album 进行分类」
349
+ 1. 子会话执行 `uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json classify "/home/album"`
350
+ 2. 展示各用户结果 → **直接** `pack --timeout 120`(多用户各一链接)→ 再问是否 `copy`
351
+
352
+ - 用户:「删除照片分类器中李四的信息」
353
+ 1. `uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json check "李四"` → 存在
354
+ 2. 提示确认 → 用户确认 → `uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json delete "李四"`
355
+ 3. 提示:`🗑️✨ **用户已删除** · 李四`
356
+
357
+ - 用户:在搜索/分类完成后表示「要复制到 /output」(§6 第二步)
358
+ 1. `uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json copy "/output"`(按需加 `--name`,与 §6 一致)
359
+ 2. 提示:`✅📁 **复制完成** · N 张 → /output/`
360
+
361
+ - 用户:「把这些图片放到待搜索目录」
362
+ 1. `uv run {baseDir}/scripts/face_search.py -c {baseDir}/references/config.json upload-image "/tmp/a.jpg" "/tmp/b.jpg"`
363
+ 2. 全部成功后提示:`✅📤 **已放入待搜索目录** → <folder_path> ✨`
364
+
365
+ ## Notes
366
+
367
+ - 建议始终通过 `-c` 传入 `{baseDir}/references/config.json` 的绝对路径,避免相对路径导致找不到配置文件。
368
+ - `search`、`quick-search` 和 `classify` 可能耗时较长(取决于搜索目录中的图片数量),应在**子会话**中执行;**结束后立即关闭并删除该子会话**,再将结果与后续 `pack` / `copy` 交互放在**主会话**中完成。
369
+ - `images/` 目录用于存放待搜索图片;`upload-image` 内部会创建当天目录并串行逐张处理图片。
370
+ - 搜索过程中会在图片所在目录下创建 `.embedding` 隐藏目录缓存 embedding 结果,后续搜索同一目录会自动跳过已处理的图片。
371
+ - `copy` 和 `pack` 命令依赖 `config.json` 中保存的搜索结果(`search_result` 或 `quick_search_result` 字段),必须先执行 `search`、`classify` 或 `quick-search` 后才能使用。
372
+ - 结果导出顺序:**先**执行 `pack` 生成下载链接,**再**询问用户是否需要 `copy`(见 §6)。
373
+ - `pack` 的压缩文件存放在系统临时目录中,上传完成后可忽略清理。上传超时默认 120 秒,文件特别大时可通过 `--timeout` 增大。
374
+ - `config.json` 中的 `query_threshold`(默认 0.7)控制人脸检测置信度阈值,`search_similarity_threshold`(默认 0.3)控制搜索匹配的最低相似度。
375
+ - `{baseDir}` 指本 skill 根目录(如 `skills/image-classify`),调用时替换为实际绝对路径。
@@ -0,0 +1,4 @@
1
+ {
2
+ "query_threshold": 0.7,
3
+ "search_similarity_threshold": 0.3
4
+ }