@optima-chat/optima-agent 0.4.28 → 0.4.29

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 (35) hide show
  1. package/.claude/settings.local.json +2 -1
  2. package/.claude/skills/product/SKILL.md +19 -3
  3. package/dist/src/hooks-loader.d.ts +1 -1
  4. package/dist/src/hooks-loader.d.ts.map +1 -1
  5. package/dist/src/hooks-loader.js +116 -12
  6. package/dist/src/hooks-loader.js.map +1 -1
  7. package/dist/src/validation/error-formatter.d.ts +21 -0
  8. package/dist/src/validation/error-formatter.d.ts.map +1 -0
  9. package/dist/src/validation/error-formatter.js +98 -0
  10. package/dist/src/validation/error-formatter.js.map +1 -0
  11. package/dist/src/validation/index.d.ts +10 -0
  12. package/dist/src/validation/index.d.ts.map +1 -0
  13. package/dist/src/validation/index.js +10 -0
  14. package/dist/src/validation/index.js.map +1 -0
  15. package/dist/src/validation/json-validator.d.ts +25 -0
  16. package/dist/src/validation/json-validator.d.ts.map +1 -0
  17. package/dist/src/validation/json-validator.js +173 -0
  18. package/dist/src/validation/json-validator.js.map +1 -0
  19. package/dist/src/validation/schema.d.ts +353 -0
  20. package/dist/src/validation/schema.d.ts.map +1 -0
  21. package/dist/src/validation/schema.js +57 -0
  22. package/dist/src/validation/schema.js.map +1 -0
  23. package/dist/src/validation/suggestions.d.ts +25 -0
  24. package/dist/src/validation/suggestions.d.ts.map +1 -0
  25. package/dist/src/validation/suggestions.js +144 -0
  26. package/dist/src/validation/suggestions.js.map +1 -0
  27. package/dist/src/validation/types.d.ts +40 -0
  28. package/dist/src/validation/types.d.ts.map +1 -0
  29. package/dist/src/validation/types.js +5 -0
  30. package/dist/src/validation/types.js.map +1 -0
  31. package/dist/src/validation/yaml-validator.d.ts +25 -0
  32. package/dist/src/validation/yaml-validator.d.ts.map +1 -0
  33. package/dist/src/validation/yaml-validator.js +177 -0
  34. package/dist/src/validation/yaml-validator.js.map +1 -0
  35. package/package.json +1 -1
@@ -70,7 +70,8 @@
70
70
  "Bash(commerce homepage create-featured:*)",
71
71
  "Bash(commerce homepage create-collection-products:*)",
72
72
  "Bash(commerce homepage create-banner:*)",
73
- "Bash(xargs -I {} sh -c 'echo \"\"\"\"=== {} ===\"\"\"\"; head -3 /Users/verypro/optima-agent/.claude/skills/{}/SKILL.md | grep \"\"\"\"name:\"\"\"\"')"
73
+ "Bash(xargs -I {} sh -c 'echo \"\"\"\"=== {} ===\"\"\"\"; head -3 /Users/verypro/optima-agent/.claude/skills/{}/SKILL.md | grep \"\"\"\"name:\"\"\"\"')",
74
+ "Bash(ls:*)"
74
75
  ],
75
76
  "deny": [],
76
77
  "ask": []
@@ -58,9 +58,9 @@ done
58
58
  # 1. 查找目标商品
59
59
  commerce product list --query "T恤" --limit 50
60
60
 
61
- # 2. 批量更新价格和促销标签
62
- commerce product update --id prod_123 --price 79 --tags "featured,sale"
63
- commerce product update --id prod_456 --price 79 --tags "featured,sale"
61
+ # 2. 批量更新价格和促销标签(设置原价显示折扣)
62
+ commerce product update --id prod_123 --price 79 --original-price 99 --tags "featured,sale"
63
+ commerce product update --id prod_456 --price 79 --original-price 99 --tags "featured,sale"
64
64
  ```
65
65
 
66
66
  ### 场景5:商品图片更新
@@ -73,6 +73,18 @@ commerce upload image --path ./new-photo.jpg # 获得 media_new
73
73
  commerce product add-images --id prod_123 --media-id media_new
74
74
  ```
75
75
 
76
+ ### 场景6:创建促销商品
77
+ **任务**: 创建带折扣显示的商品(显示划线价)
78
+ ```bash
79
+ # 创建促销商品:售价79,原价99(显示划线价)
80
+ commerce product create \
81
+ --title "夏日特惠T恤" \
82
+ --price 79 \
83
+ --original-price 99 \
84
+ --stock 100 \
85
+ --tags "sale"
86
+ ```
87
+
76
88
  ### 场景决策表
77
89
 
78
90
  | 用户需求 | 推荐命令 | 关键注意点 |
@@ -81,6 +93,7 @@ commerce product add-images --id prod_123 --media-id media_new
81
93
  | 多规格商品 | `product create` + `variant create` | 主商品设置基础价格,变体设置差异价 |
82
94
  | 批量上架 | 脚本循环 `product create` | 复用共享图片的media_id,避免重复上传 |
83
95
  | 更新价格 | `product update --price` | 如有变体,需逐个更新变体价格 |
96
+ | 促销商品 | `product create --original-price` | `--original-price` 必须大于 `--price` |
84
97
  | 促销标签 | `product update --tags` | 用逗号分隔,保留原有标签 |
85
98
  | 图片更新 | `upload` + `add-images` | 先上传再关联,不要直接删除旧图 |
86
99
 
@@ -184,9 +197,12 @@ commerce product create --title "T恤" --price 99 --stock 50 # 确保真实有5
184
197
 
185
198
  当用户说:
186
199
  - "创建XX商品,价格YY" → `commerce product create --title XX --price YY`
200
+ - "创建XX商品,售价YY,原价ZZ" → `commerce product create --title XX --price YY --original-price ZZ`
201
+ - "创建促销商品,价格79,划线价99" → `commerce product create --title XX --price 79 --original-price 99`
187
202
  - "上传商品图片" → `commerce upload image --path ./photo.jpg`
188
203
  - "添加商品变体" → `commerce variant create --product-id XX --sku YY`
189
204
  - "更新商品价格" → `commerce product update --id XX --price YY`
205
+ - "设置商品原价/划线价" → `commerce product update --id XX --original-price YY`
190
206
  - "给商品打标签" → `commerce product update --id XX --tags "featured,new"`
191
207
  - "设置商品重量和尺寸" → `commerce product update --id XX --weight 0.5 --length 10 --width 8 --height 5`
192
208
  - "查看所有商品" → `commerce product list`
@@ -2,5 +2,5 @@ import type { HooksConfig } from "./types.js";
2
2
  /**
3
3
  * 从 skills 目录加载所有 skill 的 hooks
4
4
  */
5
- export declare function loadSkillHooks(skillsDir: string, cwd: string): HooksConfig;
5
+ export declare function loadSkillHooks(skillsDir: string, cwd: string, getSessionId: () => string | undefined): HooksConfig;
6
6
  //# sourceMappingURL=hooks-loader.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"hooks-loader.d.ts","sourceRoot":"","sources":["../../src/hooks-loader.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAgB,MAAM,YAAY,CAAC;AAuF5D;;GAEG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,WAAW,CA+D1E"}
1
+ {"version":3,"file":"hooks-loader.d.ts","sourceRoot":"","sources":["../../src/hooks-loader.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAgB,MAAM,YAAY,CAAC;AAwL5D;;GAEG;AACH,wBAAgB,cAAc,CAC5B,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,EACX,YAAY,EAAE,MAAM,MAAM,GAAG,SAAS,GACrC,WAAW,CAiFb"}
@@ -1,7 +1,8 @@
1
- import { readFileSync, readdirSync, existsSync } from "fs";
2
- import { join } from "path";
1
+ import { readFileSync, readdirSync, existsSync, writeFileSync, mkdirSync } from "fs";
2
+ import { join, dirname } from "path";
3
3
  import yaml from "js-yaml";
4
4
  import { execSync } from "child_process";
5
+ import { YamlValidator, formatValidationErrors, formatValidationWarning } from "./validation/index.js";
5
6
  /**
6
7
  * 从 SKILL.md 提取 YAML frontmatter
7
8
  */
@@ -20,10 +21,12 @@ function extractYamlFrontmatter(content) {
20
21
  /**
21
22
  * 执行 shell 命令并返回结果
22
23
  */
23
- function executeCommand(command, cwd, skillDir) {
24
+ function executeCommand(command, cwd, skillDir, sessionId) {
24
25
  try {
25
- // 替换 ${CLAUDE_PLUGIN_ROOT} 为实际的 skill 目录
26
- const expandedCommand = command.replace(/\$\{CLAUDE_PLUGIN_ROOT\}/g, skillDir);
26
+ // 替换环境变量
27
+ const expandedCommand = command
28
+ .replace(/\$\{CLAUDE_PLUGIN_ROOT\}/g, skillDir)
29
+ .replace(/\$\{SESSION_ID\}/g, sessionId || 'default');
27
30
  const result = execSync(expandedCommand, {
28
31
  cwd,
29
32
  encoding: "utf-8",
@@ -39,14 +42,101 @@ function executeCommand(command, cwd, skillDir) {
39
42
  /**
40
43
  * 转换 skill hooks 为 SDK hooks 格式
41
44
  */
42
- function convertSkillHooksToSdkHooks(skillHooks, skillDir, cwd) {
45
+ function convertSkillHooksToSdkHooks(skillHooks, skillDir, cwd, getSessionId, hookType) {
43
46
  return skillHooks.map((hookConfig) => ({
44
47
  matcher: hookConfig.matcher,
45
48
  hooks: hookConfig.hooks.map((hook) => {
46
49
  // SDK HookCallback 签名: (input, toolUseID, options) => Promise<HookJSONOutput>
47
50
  return async (input, toolUseID, options) => {
51
+ // PreToolUse: 拦截并重定向 planning 文件操作
52
+ if (hookType === "PreToolUse" && input.tool_name && input.tool_input) {
53
+ const toolName = input.tool_name;
54
+ const toolInput = input.tool_input;
55
+ // 处理文件操作工具的路径重定向
56
+ if ((toolName === "Write" || toolName === "Read" || toolName === "Edit") && toolInput.file_path) {
57
+ const filePath = toolInput.file_path;
58
+ if (filePath.includes(".planning/default/")) {
59
+ const sessionId = getSessionId() || "default";
60
+ const updatedPath = filePath.replace(".planning/default/", `.planning/${sessionId}/`);
61
+ console.log(`[hooks-loader] Intercepting and redirecting: ${filePath} -> ${updatedPath}`);
62
+ // 手动执行文件操作并 return,不要继续到 command 部分
63
+ try {
64
+ console.log(`[hooks-loader] Inside try block, toolName=${toolName}`);
65
+ if (toolName === "Write") {
66
+ console.log(`[hooks-loader] Handling Write operation`);
67
+ // 创建目录
68
+ const dir = dirname(updatedPath);
69
+ if (!existsSync(dir)) {
70
+ mkdirSync(dir, { recursive: true });
71
+ }
72
+ // 写入文件
73
+ writeFileSync(updatedPath, toolInput.content || "", "utf-8");
74
+ console.log(`[hooks-loader] File written to ${updatedPath}`);
75
+ // Block 原始工具执行
76
+ return {
77
+ decision: "block",
78
+ systemMessage: `File written to session-specific directory`,
79
+ };
80
+ }
81
+ else if (toolName === "Read") {
82
+ // 读取文件
83
+ if (existsSync(updatedPath)) {
84
+ const content = readFileSync(updatedPath, "utf-8");
85
+ console.log(`[hooks-loader] File read from ${updatedPath}`);
86
+ // Block 原始工具,返回文件内容
87
+ return {
88
+ decision: "block",
89
+ systemMessage: `File content:\n\n${content}`,
90
+ };
91
+ }
92
+ else {
93
+ return {
94
+ decision: "block",
95
+ systemMessage: `File not found: ${updatedPath}`,
96
+ };
97
+ }
98
+ }
99
+ else if (toolName === "Edit") {
100
+ // Edit 需要读取、修改、写入
101
+ if (existsSync(updatedPath)) {
102
+ let content = readFileSync(updatedPath, "utf-8");
103
+ // 执行替换
104
+ if (toolInput.old_string && toolInput.new_string) {
105
+ if (toolInput.replace_all) {
106
+ content = content.split(toolInput.old_string).join(toolInput.new_string);
107
+ }
108
+ else {
109
+ content = content.replace(toolInput.old_string, toolInput.new_string);
110
+ }
111
+ writeFileSync(updatedPath, content, "utf-8");
112
+ console.log(`[hooks-loader] File edited at ${updatedPath}`);
113
+ }
114
+ return {
115
+ decision: "block",
116
+ systemMessage: `File edited successfully`,
117
+ };
118
+ }
119
+ else {
120
+ return {
121
+ decision: "block",
122
+ systemMessage: `File not found: ${updatedPath}`,
123
+ };
124
+ }
125
+ }
126
+ }
127
+ catch (error) {
128
+ console.error(`[hooks-loader] Error:`, error);
129
+ return {
130
+ decision: "block",
131
+ systemMessage: `Error: ${error.message}`,
132
+ };
133
+ }
134
+ }
135
+ }
136
+ }
48
137
  if (hook.type === "command") {
49
- const result = executeCommand(hook.command, cwd, skillDir);
138
+ const sessionId = getSessionId();
139
+ const result = executeCommand(hook.command, cwd, skillDir, sessionId);
50
140
  // 如果有输出,作为系统消息返回
51
141
  if (result) {
52
142
  return {
@@ -63,7 +153,7 @@ function convertSkillHooksToSdkHooks(skillHooks, skillDir, cwd) {
63
153
  /**
64
154
  * 从 skills 目录加载所有 skill 的 hooks
65
155
  */
66
- export function loadSkillHooks(skillsDir, cwd) {
156
+ export function loadSkillHooks(skillsDir, cwd, getSessionId) {
67
157
  const hooks = {};
68
158
  if (!existsSync(skillsDir)) {
69
159
  return hooks;
@@ -79,6 +169,20 @@ export function loadSkillHooks(skillsDir, cwd) {
79
169
  }
80
170
  try {
81
171
  const content = readFileSync(skillMdPath, "utf-8");
172
+ // 验证配置文件
173
+ const validator = new YamlValidator();
174
+ const validationResult = validator.validate(content, skillMdPath);
175
+ // 显示错误
176
+ if (!validationResult.valid) {
177
+ console.error(formatValidationErrors(validationResult.errors));
178
+ continue;
179
+ }
180
+ // 显示警告
181
+ if (validationResult.warnings && validationResult.warnings.length > 0) {
182
+ for (const warning of validationResult.warnings) {
183
+ console.warn(formatValidationWarning(warning));
184
+ }
185
+ }
82
186
  const frontmatter = extractYamlFrontmatter(content);
83
187
  if (!frontmatter?.hooks) {
84
188
  continue;
@@ -86,19 +190,19 @@ export function loadSkillHooks(skillsDir, cwd) {
86
190
  // 转换各个 hook 事件
87
191
  if (frontmatter.hooks.SessionStart) {
88
192
  hooks.SessionStart = hooks.SessionStart || [];
89
- hooks.SessionStart.push(...convertSkillHooksToSdkHooks(frontmatter.hooks.SessionStart, skillDir, cwd));
193
+ hooks.SessionStart.push(...convertSkillHooksToSdkHooks(frontmatter.hooks.SessionStart, skillDir, cwd, getSessionId, "SessionStart"));
90
194
  }
91
195
  if (frontmatter.hooks.PreToolUse) {
92
196
  hooks.PreToolUse = hooks.PreToolUse || [];
93
- hooks.PreToolUse.push(...convertSkillHooksToSdkHooks(frontmatter.hooks.PreToolUse, skillDir, cwd));
197
+ hooks.PreToolUse.push(...convertSkillHooksToSdkHooks(frontmatter.hooks.PreToolUse, skillDir, cwd, getSessionId, "PreToolUse"));
94
198
  }
95
199
  if (frontmatter.hooks.PostToolUse) {
96
200
  hooks.PostToolUse = hooks.PostToolUse || [];
97
- hooks.PostToolUse.push(...convertSkillHooksToSdkHooks(frontmatter.hooks.PostToolUse, skillDir, cwd));
201
+ hooks.PostToolUse.push(...convertSkillHooksToSdkHooks(frontmatter.hooks.PostToolUse, skillDir, cwd, getSessionId, "PostToolUse"));
98
202
  }
99
203
  if (frontmatter.hooks.Stop) {
100
204
  hooks.Stop = hooks.Stop || [];
101
- hooks.Stop.push(...convertSkillHooksToSdkHooks(frontmatter.hooks.Stop, skillDir, cwd));
205
+ hooks.Stop.push(...convertSkillHooksToSdkHooks(frontmatter.hooks.Stop, skillDir, cwd, getSessionId, "Stop"));
102
206
  }
103
207
  console.log(`[hooks-loader] Loaded hooks from skill: ${skillName}`);
104
208
  }
@@ -1 +1 @@
1
- {"version":3,"file":"hooks-loader.js","sourceRoot":"","sources":["../../src/hooks-loader.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"hooks-loader.js","sourceRoot":"","sources":["../../src/hooks-loader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * 错误消息格式化工具
3
+ */
4
+ import type { ValidationError } from "./types.js";
5
+ /**
6
+ * 格式化单个验证错误为用户友好的消息
7
+ */
8
+ export declare function formatValidationError(error: ValidationError): string;
9
+ /**
10
+ * 格式化多个验证错误
11
+ */
12
+ export declare function formatValidationErrors(errors: ValidationError[]): string;
13
+ /**
14
+ * 格式化验证警告
15
+ */
16
+ export declare function formatValidationWarning(warning: ValidationError): string;
17
+ /**
18
+ * 创建代码片段显示(带行号)
19
+ */
20
+ export declare function createCodeSnippet(content: string, errorLine: number, contextLines?: number): string;
21
+ //# sourceMappingURL=error-formatter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-formatter.d.ts","sourceRoot":"","sources":["../../../src/validation/error-formatter.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,eAAe,GAAG,MAAM,CAuDpE;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,CAOxE;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,CAgBxE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,YAAY,GAAE,MAAU,GACvB,MAAM,CAoBR"}
@@ -0,0 +1,98 @@
1
+ /**
2
+ * 格式化单个验证错误为用户友好的消息
3
+ */
4
+ export function formatValidationError(error) {
5
+ const parts = [];
6
+ // 错误标题
7
+ const errorType = {
8
+ syntax: "语法错误",
9
+ schema: "配置错误",
10
+ semantic: "语义错误",
11
+ }[error.type];
12
+ parts.push(`\n❌ ${errorType} (${error.filePath})`);
13
+ parts.push("");
14
+ // 错误位置
15
+ if (error.line !== undefined) {
16
+ const location = error.column !== undefined ? `第 ${error.line} 行,第 ${error.column} 列` : `第 ${error.line} 行`;
17
+ parts.push(`位置: ${location}`);
18
+ }
19
+ // 问题字段
20
+ if (error.path && error.path.length > 0) {
21
+ parts.push(`字段: ${error.path.join(".")}`);
22
+ }
23
+ // 错误消息
24
+ parts.push("");
25
+ parts.push(`问题: ${error.message}`);
26
+ // 详细描述
27
+ if (error.details) {
28
+ parts.push("");
29
+ parts.push(error.details);
30
+ }
31
+ // 修复建议
32
+ if (error.suggestions.length > 0) {
33
+ parts.push("");
34
+ parts.push("修复建议:");
35
+ error.suggestions.forEach((suggestion) => {
36
+ parts.push(` • ${suggestion}`);
37
+ });
38
+ }
39
+ // 示例配置
40
+ if (error.examplePath) {
41
+ parts.push("");
42
+ parts.push(`参考示例: ${error.examplePath}`);
43
+ }
44
+ // 文档链接
45
+ if (error.docUrl) {
46
+ parts.push(`相关文档: ${error.docUrl}`);
47
+ }
48
+ return parts.join("\n");
49
+ }
50
+ /**
51
+ * 格式化多个验证错误
52
+ */
53
+ export function formatValidationErrors(errors) {
54
+ if (errors.length === 0) {
55
+ return "";
56
+ }
57
+ const formatted = errors.map((error) => formatValidationError(error));
58
+ return formatted.join("\n\n" + "─".repeat(60) + "\n");
59
+ }
60
+ /**
61
+ * 格式化验证警告
62
+ */
63
+ export function formatValidationWarning(warning) {
64
+ const parts = [];
65
+ parts.push(`\n⚠️ 警告 (${warning.filePath})`);
66
+ parts.push("");
67
+ parts.push(warning.message);
68
+ if (warning.suggestions.length > 0) {
69
+ parts.push("");
70
+ parts.push("建议:");
71
+ warning.suggestions.forEach((suggestion) => {
72
+ parts.push(` • ${suggestion}`);
73
+ });
74
+ }
75
+ return parts.join("\n");
76
+ }
77
+ /**
78
+ * 创建代码片段显示(带行号)
79
+ */
80
+ export function createCodeSnippet(content, errorLine, contextLines = 2) {
81
+ const lines = content.split("\n");
82
+ const startLine = Math.max(0, errorLine - contextLines - 1);
83
+ const endLine = Math.min(lines.length - 1, errorLine + contextLines - 1);
84
+ const snippet = [];
85
+ for (let i = startLine; i <= endLine; i++) {
86
+ const lineNum = i + 1;
87
+ const isErrorLine = lineNum === errorLine;
88
+ const prefix = isErrorLine ? ">" : " ";
89
+ const lineNumStr = String(lineNum).padStart(4);
90
+ snippet.push(`${prefix} ${lineNumStr} | ${lines[i]}`);
91
+ if (isErrorLine) {
92
+ // 添加指示符
93
+ snippet.push(" " + " ".repeat(lines[i].length) + "^");
94
+ }
95
+ }
96
+ return snippet.join("\n");
97
+ }
98
+ //# sourceMappingURL=error-formatter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-formatter.js","sourceRoot":"","sources":["../../../src/validation/error-formatter.ts"],"names":[],"mappings":"AAKA;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,KAAsB;IAC1D,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,OAAO;IACP,MAAM,SAAS,GAAG;QAChB,MAAM,EAAE,MAAM;QACd,MAAM,EAAE,MAAM;QACd,QAAQ,EAAE,MAAM;KACjB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAEd,KAAK,CAAC,IAAI,CAAC,OAAO,SAAS,KAAK,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC;IACnD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEf,OAAO;IACP,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC7B,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,IAAI,QAAQ,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,IAAI,IAAI,CAAC;QAC5G,KAAK,CAAC,IAAI,CAAC,OAAO,QAAQ,EAAE,CAAC,CAAC;IAChC,CAAC;IAED,OAAO;IACP,IAAI,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxC,KAAK,CAAC,IAAI,CAAC,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC5C,CAAC;IAED,OAAO;IACP,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,OAAO,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IAEnC,OAAO;IACP,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QAClB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC5B,CAAC;IAED,OAAO;IACP,IAAI,KAAK,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACjC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACpB,KAAK,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,UAAU,EAAE,EAAE;YACvC,KAAK,CAAC,IAAI,CAAC,OAAO,UAAU,EAAE,CAAC,CAAC;QAClC,CAAC,CAAC,CAAC;IACL,CAAC;IAED,OAAO;IACP,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;QACtB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,SAAS,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC;IAC3C,CAAC;IAED,OAAO;IACP,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QACjB,KAAK,CAAC,IAAI,CAAC,SAAS,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IACtC,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,sBAAsB,CAAC,MAAyB;IAC9D,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC,CAAC;IACtE,OAAO,SAAS,CAAC,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;AACxD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,uBAAuB,CAAC,OAAwB;IAC9D,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,KAAK,CAAC,IAAI,CAAC,aAAa,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;IAC7C,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAE5B,IAAI,OAAO,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACnC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAClB,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,UAAU,EAAE,EAAE;YACzC,KAAK,CAAC,IAAI,CAAC,OAAO,UAAU,EAAE,CAAC,CAAC;QAClC,CAAC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAC/B,OAAe,EACf,SAAiB,EACjB,eAAuB,CAAC;IAExB,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,GAAG,YAAY,GAAG,CAAC,CAAC,CAAC;IAC5D,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,SAAS,GAAG,YAAY,GAAG,CAAC,CAAC,CAAC;IAEzE,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,KAAK,IAAI,CAAC,GAAG,SAAS,EAAE,CAAC,IAAI,OAAO,EAAE,CAAC,EAAE,EAAE,CAAC;QAC1C,MAAM,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC;QACtB,MAAM,WAAW,GAAG,OAAO,KAAK,SAAS,CAAC;QAC1C,MAAM,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;QACvC,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QAC/C,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,IAAI,UAAU,MAAM,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAEtD,IAAI,WAAW,EAAE,CAAC;YAChB,QAAQ;YACR,OAAO,CAAC,IAAI,CAAC,SAAS,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC5B,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * 配置验证模块
3
+ */
4
+ export * from "./types.js";
5
+ export * from "./schema.js";
6
+ export * from "./yaml-validator.js";
7
+ export * from "./json-validator.js";
8
+ export * from "./error-formatter.js";
9
+ export * from "./suggestions.js";
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/validation/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * 配置验证模块
3
+ */
4
+ export * from "./types.js";
5
+ export * from "./schema.js";
6
+ export * from "./yaml-validator.js";
7
+ export * from "./json-validator.js";
8
+ export * from "./error-formatter.js";
9
+ export * from "./suggestions.js";
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/validation/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC"}
@@ -0,0 +1,25 @@
1
+ import type { Validator, ValidationResult } from "./types.js";
2
+ import { type OptimaConfig } from "./schema.js";
3
+ export declare class JsonValidator implements Validator<OptimaConfig> {
4
+ /**
5
+ * 解析 JSON 内容
6
+ */
7
+ private parseJson;
8
+ /**
9
+ * 从 JSON 错误中提取位置信息
10
+ */
11
+ private extractErrorPosition;
12
+ /**
13
+ * 将字符位置转换为行号和列号
14
+ */
15
+ private positionToLineColumn;
16
+ /**
17
+ * 验证 JSON 配置
18
+ */
19
+ validate(content: string, filePath: string): ValidationResult;
20
+ /**
21
+ * 解析配置(验证成功后调用)
22
+ */
23
+ parse(content: string): OptimaConfig | null;
24
+ }
25
+ //# sourceMappingURL=json-validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json-validator.d.ts","sourceRoot":"","sources":["../../../src/validation/json-validator.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAmB,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC/E,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAOpE,qBAAa,aAAc,YAAW,SAAS,CAAC,YAAY,CAAC;IAC3D;;OAEG;IACH,OAAO,CAAC,SAAS;IAUjB;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAS5B;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAQ5B;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,gBAAgB;IAyH7D;;OAEG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI;CAY5C"}
@@ -0,0 +1,173 @@
1
+ /**
2
+ * JSON 配置验证器
3
+ */
4
+ import { ZodError } from "zod";
5
+ import { OptimaConfigSchema } from "./schema.js";
6
+ import { generateSuggestionsFromZodError, generateJsonSyntaxSuggestions, generateOptimaConfigSuggestions, } from "./suggestions.js";
7
+ export class JsonValidator {
8
+ /**
9
+ * 解析 JSON 内容
10
+ */
11
+ parseJson(content) {
12
+ try {
13
+ const data = JSON.parse(content);
14
+ return { data };
15
+ }
16
+ catch (error) {
17
+ const position = this.extractErrorPosition(error);
18
+ return { data: null, error: error, position };
19
+ }
20
+ }
21
+ /**
22
+ * 从 JSON 错误中提取位置信息
23
+ */
24
+ extractErrorPosition(error) {
25
+ // JSON.parse 错误通常包含 "at position X"
26
+ const match = error.message.match(/position (\d+)/);
27
+ if (match) {
28
+ return parseInt(match[1], 10);
29
+ }
30
+ return undefined;
31
+ }
32
+ /**
33
+ * 将字符位置转换为行号和列号
34
+ */
35
+ positionToLineColumn(content, position) {
36
+ const lines = content.substring(0, position).split("\n");
37
+ return {
38
+ line: lines.length,
39
+ column: lines[lines.length - 1].length + 1,
40
+ };
41
+ }
42
+ /**
43
+ * 验证 JSON 配置
44
+ */
45
+ validate(content, filePath) {
46
+ const errors = [];
47
+ const warnings = [];
48
+ // 1. 检查是否为空
49
+ if (!content.trim()) {
50
+ errors.push({
51
+ type: "syntax",
52
+ filePath,
53
+ message: "配置文件为空",
54
+ suggestions: [
55
+ "添加配置内容",
56
+ "如果不需要配置,可以删除该文件",
57
+ "最小配置示例: {}",
58
+ ],
59
+ });
60
+ return { valid: false, errors, warnings };
61
+ }
62
+ // 2. 解析 JSON
63
+ const { data, error: jsonError, position } = this.parseJson(content);
64
+ if (jsonError) {
65
+ let line;
66
+ let column;
67
+ if (position !== undefined) {
68
+ const loc = this.positionToLineColumn(content, position);
69
+ line = loc.line;
70
+ column = loc.column;
71
+ }
72
+ errors.push({
73
+ type: "syntax",
74
+ filePath,
75
+ message: "JSON 语法错误",
76
+ details: jsonError.message,
77
+ line,
78
+ column,
79
+ suggestions: generateJsonSyntaxSuggestions(jsonError.message),
80
+ });
81
+ return { valid: false, errors, warnings };
82
+ }
83
+ // 3. 检查是否为对象
84
+ if (typeof data !== "object" || data === null || Array.isArray(data)) {
85
+ errors.push({
86
+ type: "schema",
87
+ filePath,
88
+ message: "配置文件必须是一个 JSON 对象",
89
+ suggestions: ["配置应该用大括号 {} 包裹", "示例: { \"model\": \"...\", \"theme\": \"dark\" }"],
90
+ });
91
+ return { valid: false, errors, warnings };
92
+ }
93
+ // 4. 使用 Zod 验证 schema
94
+ try {
95
+ OptimaConfigSchema.parse(data);
96
+ }
97
+ catch (error) {
98
+ if (error instanceof ZodError) {
99
+ for (const issue of error.issues) {
100
+ const zodSuggestions = generateSuggestionsFromZodError(error);
101
+ const optimaSuggestions = generateOptimaConfigSuggestions(issue.path.map(String));
102
+ errors.push({
103
+ type: "schema",
104
+ filePath,
105
+ message: issue.message,
106
+ path: issue.path.map(String),
107
+ suggestions: [...zodSuggestions, ...optimaSuggestions],
108
+ });
109
+ }
110
+ }
111
+ else {
112
+ errors.push({
113
+ type: "schema",
114
+ filePath,
115
+ message: "未知的验证错误",
116
+ details: String(error),
117
+ suggestions: ["请检查配置文件格式"],
118
+ });
119
+ }
120
+ return { valid: false, errors, warnings };
121
+ }
122
+ // 5. 语义检查和警告
123
+ // 检查未知字段
124
+ const knownFields = ["model", "theme", "ui", "server"];
125
+ const unknownFields = Object.keys(data).filter((key) => !knownFields.includes(key));
126
+ if (unknownFields.length > 0) {
127
+ warnings.push({
128
+ type: "semantic",
129
+ filePath,
130
+ message: `发现未知字段: ${unknownFields.join(", ")}`,
131
+ suggestions: [
132
+ "这些字段会被忽略",
133
+ "检查是否拼写错误",
134
+ `已知字段: ${knownFields.join(", ")}`,
135
+ ],
136
+ });
137
+ }
138
+ // 检查服务器配置
139
+ if (data.server?.port) {
140
+ const commonPorts = [3000, 8080, 8000, 5000];
141
+ if (!commonPorts.includes(data.server.port)) {
142
+ warnings.push({
143
+ type: "semantic",
144
+ filePath,
145
+ message: `使用非常见端口: ${data.server.port}`,
146
+ path: ["server", "port"],
147
+ suggestions: ["确保该端口未被占用", `常用端口: ${commonPorts.join(", ")}`],
148
+ });
149
+ }
150
+ }
151
+ return {
152
+ valid: errors.length === 0,
153
+ errors,
154
+ warnings,
155
+ };
156
+ }
157
+ /**
158
+ * 解析配置(验证成功后调用)
159
+ */
160
+ parse(content) {
161
+ const { data, error } = this.parseJson(content);
162
+ if (error) {
163
+ return null;
164
+ }
165
+ try {
166
+ return OptimaConfigSchema.parse(data);
167
+ }
168
+ catch {
169
+ return null;
170
+ }
171
+ }
172
+ }
173
+ //# sourceMappingURL=json-validator.js.map