@opentiny/next-sdk 0.2.6 → 0.2.7

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/skills/index.ts CHANGED
@@ -42,21 +42,42 @@ export function parseSkillFrontMatter(content: string): { name: string; descript
42
42
  return name && description ? { name, description } : null
43
43
  }
44
44
 
45
+ /**
46
+ * 将 Vite import.meta.glob 得到的多种 key 格式统一为「相对 skills 根目录」的路径(如 ./calculator/SKILL.md),
47
+ * 以便 getSkillMdContent / getMainSkillPathByName 等能正确按 path 查找。
48
+ * 兼容任意引入位置:./skills/xxx、../skills/xxx、src/skills/xxx 等,取最后一个 skills/ 后的部分并加上 ./
49
+ */
50
+ function normalizeSkillModuleKeys(modules: Record<string, string>): Record<string, string> {
51
+ const result: Record<string, string> = {}
52
+ for (const [key, content] of Object.entries(modules)) {
53
+ const normalizedKey = key.replace(/\\/g, '/')
54
+ const skillsIndex = normalizedKey.lastIndexOf('skills/')
55
+ const relativePath = skillsIndex >= 0 ? normalizedKey.slice(skillsIndex + 7) : normalizedKey
56
+ const standardPath = relativePath.startsWith('./') ? relativePath : `./${relativePath}`
57
+ result[standardPath] = content
58
+ }
59
+ return result
60
+ }
61
+
45
62
  /**
46
63
  * 获取所有「主 SKILL.md」的路径(一级子目录下的 SKILL.md)
64
+ * - 对传入的 modules 先做 normalize,兼容任意 import.meta.glob 写法
47
65
  */
48
66
  export function getMainSkillPaths(modules: Record<string, string>): string[] {
49
- return Object.keys(modules).filter((path) => MAIN_SKILL_PATH_REG.test(path))
67
+ const normalized = normalizeSkillModuleKeys(modules)
68
+ return Object.keys(normalized).filter((path) => MAIN_SKILL_PATH_REG.test(path))
50
69
  }
51
70
 
52
71
  /**
53
72
  * 获取所有技能的概况列表(name、description、path),用于 systemPrompt 或列表展示
73
+ * - 内部统一对 modules 做 normalize,避免调用方关心路径细节
54
74
  */
55
75
  export function getSkillOverviews(modules: Record<string, string>): SkillMeta[] {
56
- const mainPaths = getMainSkillPaths(modules)
76
+ const normalized = normalizeSkillModuleKeys(modules)
77
+ const mainPaths = Object.keys(normalized).filter((path) => MAIN_SKILL_PATH_REG.test(path))
57
78
  const list: SkillMeta[] = []
58
79
  for (const path of mainPaths) {
59
- const content = modules[path]
80
+ const content = normalized[path]
60
81
  if (!content) continue
61
82
  const parsed = parseSkillFrontMatter(content)
62
83
  if (!parsed) continue
@@ -81,20 +102,25 @@ export function formatSkillsForSystemPrompt(skills: SkillMeta[]): string {
81
102
 
82
103
  /**
83
104
  * 获取所有已加载的技能文件路径(含主 SKILL.md 与 reference 下的 .md/.json/.xml 等)
105
+ * - 对 modules 做 normalize 后再返回 key 列表
84
106
  */
85
107
  export function getSkillMdPaths(modules: Record<string, string>): string[] {
86
- return Object.keys(modules)
108
+ const normalized = normalizeSkillModuleKeys(modules)
109
+ return Object.keys(normalized)
87
110
  }
88
111
 
89
112
  /**
90
113
  * 根据相对路径获取某个技能文档的原始内容(支持 .md、.json、.xml 等文本格式)
114
+ * - 自动对 modules 做 normalize,再按 path 查找
91
115
  */
92
116
  export function getSkillMdContent(modules: Record<string, string>, path: string): string | undefined {
93
- return modules[path]
117
+ const normalized = normalizeSkillModuleKeys(modules)
118
+ return normalized[path]
94
119
  }
95
120
 
96
121
  /**
97
122
  * 根据技能 name 查找其主 SKILL.md 的路径(name 与目录名一致)
123
+ * - 依赖 getMainSkillPaths,内部已做 normalize
98
124
  */
99
125
  export function getMainSkillPathByName(modules: Record<string, string>, name: string): string | undefined {
100
126
  return getMainSkillPaths(modules).find((p) => p.startsWith(`./${name}/SKILL.md`))
@@ -106,32 +132,36 @@ export function getMainSkillPathByName(modules: Record<string, string>, name: st
106
132
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
107
133
  export type SkillToolsSet = Record<string, any>
108
134
 
135
+ // 提升为模块级常量:避免 tool() 推断 PARAMETERS 泛型时递归展开 Zod 链导致"类型实例化过深"
136
+ const SKILL_INPUT_SCHEMA = z.object({
137
+ skillName: z.string().optional().describe('技能名称,与目录名一致,如 calculator'),
138
+ path: z.string().optional().describe('文档相对路径,如 ./calculator/SKILL.md 或 ./product-guide/reference/xxx.json')
139
+ })
140
+
109
141
  /**
110
142
  * 根据 skillMdModules 创建供 AI 调用的工具集
111
143
  * - get_skill_content: 按技能名或路径获取完整文档内容,便于大模型自动识别并加载技能
112
144
  * remoter 可将返回的 tools 合并进 extraTools 注入 agent
113
145
  */
114
146
  export function createSkillTools(modules: Record<string, string>): SkillToolsSet {
147
+ const normalizedModules = normalizeSkillModuleKeys(modules)
115
148
  const getSkillContent = tool({
116
149
  description:
117
150
  '根据技能名称或文档路径获取该技能的完整文档内容。传入 skillName(如 calculator)或 path(如 ./calculator/SKILL.md)。支持 .md、.json、.xml 等各类文本格式文件。',
118
- inputSchema: z.object({
119
- skillName: z.string().optional().describe('技能名称,与目录名一致,如 calculator'),
120
- path: z.string().optional().describe('文档相对路径,如 ./calculator/SKILL.md 或 ./product-guide/reference/xxx.json')
121
- }),
122
- execute: (args: { skillName?: string; path?: string }) => {
151
+ inputSchema: SKILL_INPUT_SCHEMA,
152
+ execute: (args: { skillName?: string; path?: string }): Record<string, unknown> => {
123
153
  const { skillName, path: pathArg } = args
124
154
  let content: string | undefined
125
155
  if (pathArg) {
126
- content = getSkillMdContent(modules, pathArg)
156
+ content = getSkillMdContent(normalizedModules, pathArg)
127
157
  } else if (skillName) {
128
- const mainPath = getMainSkillPathByName(modules, skillName)
129
- content = mainPath ? getSkillMdContent(modules, mainPath) : undefined
158
+ const mainPath = getMainSkillPathByName(normalizedModules, skillName)
159
+ content = mainPath ? getSkillMdContent(normalizedModules, mainPath) : undefined
130
160
  }
131
161
  if (content === undefined) {
132
162
  return { error: '未找到对应技能文档', skillName: skillName ?? pathArg }
133
163
  }
134
- return { content, path: pathArg ?? getMainSkillPathByName(modules, skillName!) }
164
+ return { content, path: pathArg ?? getMainSkillPathByName(normalizedModules, skillName!) }
135
165
  }
136
166
  })
137
167