neo-skill 0.1.23 → 0.1.24

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neo-skill",
3
- "version": "0.1.23",
3
+ "version": "0.1.24",
4
4
  "description": "A multi-assistant skill generator (Claude/Windsurf/Cursor/GitHub Skills) driven by a canonical SkillSpec.",
5
5
  "license": "MIT",
6
6
  "bin": {
@@ -35,7 +35,16 @@
35
35
  "title": "分析用户需求",
36
36
  "kind": "action",
37
37
  "commands": [],
38
- "notes": "提取关键信息:任务类型、输出形态、约束条件、工具边界。可用搜索辅助:`python3 .shared/skill-creator/scripts/search.py \"<keywords>\" --skill-system`"
38
+ "notes": "提取关键信息:任务类型、输出形态、约束条件、工具边界。\n\n重要:在进入详细提问之前,必须优先检查是否已有高置信度第三方 skill 可用(通过 skill-finder)。可用搜索辅助:`python3 .shared/skill-creator/scripts/search.py \"<keywords>\" --skill-system`"
39
+ },
40
+ {
41
+ "id": "third-party-recommend",
42
+ "title": "优先推荐第三方 skill(skill-finder)",
43
+ "kind": "gate",
44
+ "commands": [
45
+ "python -m skill_finder.cli match --goal \"<user_request>\" --ide <ide> --format json --min-score 0.7"
46
+ ],
47
+ "notes": "规则:skill-creator 创建前必须先从第三方 registry 推荐。\n\n执行:用用户的原始请求作为 goal(<user_request>),调用 skill-finder 进行高置信匹配(min-score=0.7),并读取 JSON 输出。\n\n- 若命中(matches 非空):\n 1) 展示 Top1 推荐(unit + package + score + README + 安装方式摘要)\n 2) 明确询问二次确认:是否安装该第三方 skill(y/n)\n 3) 若用户选择安装:输出 package.install.auto_install_cmd / manual_install_cmd,并建议用户转到 /skill-finder 完成安装与记录;本次不再继续创建 skill\n 4) 若用户拒绝安装:继续进入后续创建流程\n\n- 若未命中:直接进入后续创建流程\n\n注意:不得臆测“registry/索引缺失”;只基于命令返回的 JSON 做结论。"
39
48
  },
40
49
  {
41
50
  "id": "collect",
@@ -68,7 +68,14 @@ class SkillCreatorEngine:
68
68
  "task_type": task_type,
69
69
  "capability_tags": capability_tags
70
70
  })
71
-
71
+
72
+ third_party = self._recommend_third_party(user_request)
73
+ if third_party:
74
+ ctx.add_trace("third_party_recommendation", third_party["trace"])
75
+ rec = third_party.get("recommendation")
76
+ if rec is not None:
77
+ ctx.recommendations[third_party["provider_name"]] = rec
78
+
72
79
  # 2. Interview Engine - Level 1
73
80
  level1_questions = self.interview_engine.get_level1_questions(task_type, capability_tags)
74
81
  ctx.add_trace("level1_questions", {
@@ -81,6 +88,63 @@ class SkillCreatorEngine:
81
88
  # 在实际实现中,应该返回 questions 给调用者,等待用户回答
82
89
 
83
90
  return ctx
91
+
92
+ def _recommend_third_party(self, user_request: str) -> Optional[dict]:
93
+ try:
94
+ from skill_finder.recommender import Recommender
95
+ from skill_finder.models import SearchQuery as ThirdPartySearchQuery
96
+ except Exception:
97
+ return None
98
+
99
+ try:
100
+ recommender = Recommender(min_score=0.7)
101
+ result = recommender.recommend(ThirdPartySearchQuery(goal=user_request))
102
+ if not result.matches:
103
+ return None
104
+
105
+ m = result.matches[0]
106
+ from .types import Recommendation
107
+
108
+ rec = Recommendation(
109
+ provider_name="skill_finder",
110
+ confidence=float(m.score),
111
+ items=[
112
+ {
113
+ "unit_id": m.unit.unit_id,
114
+ "unit_name": m.unit.name,
115
+ "package_id": m.package.package_id,
116
+ "package_name": m.package.name,
117
+ "score": float(m.score),
118
+ "reasons": m.reasons,
119
+ "readme": m.package.docs.readme,
120
+ "auto_install_cmd": m.package.install.auto_install_cmd,
121
+ "manual_install_cmd": m.package.install.manual_install_cmd,
122
+ }
123
+ ],
124
+ trace={
125
+ "min_score": 0.7,
126
+ "matched": True,
127
+ },
128
+ )
129
+
130
+ return {
131
+ "provider_name": "skill_finder",
132
+ "recommendation": rec,
133
+ "trace": {
134
+ "matched": True,
135
+ "top1": {
136
+ "unit_id": m.unit.unit_id,
137
+ "package_id": m.package.package_id,
138
+ "score": float(m.score),
139
+ },
140
+ },
141
+ }
142
+ except Exception as e:
143
+ return {
144
+ "provider_name": "skill_finder",
145
+ "recommendation": None,
146
+ "trace": {"matched": False, "error": str(e)},
147
+ }
84
148
 
85
149
  def continue_with_answers(
86
150
  self,
@@ -110,7 +110,7 @@ class InterviewEngine:
110
110
  QuestionSpec(
111
111
  slot="acceptance",
112
112
  required=True,
113
- prompt="请提供至少 2 条验收用例(必须包含"无数据""失败"场景之一)",
113
+ prompt="请提供至少 2 条验收用例(必须包含'无数据''失败'场景之一)",
114
114
  answer_type=AnswerType.EXAMPLES,
115
115
  level=1
116
116
  ),