@winspan/claude-forge 0.1.2 → 0.1.3

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 (120) hide show
  1. package/dist/autopilot/index.d.ts +0 -1
  2. package/dist/autopilot/index.d.ts.map +1 -1
  3. package/dist/autopilot/index.js +0 -1
  4. package/dist/autopilot/index.js.map +1 -1
  5. package/dist/autopilot/intent-engine.d.ts +2 -0
  6. package/dist/autopilot/intent-engine.d.ts.map +1 -1
  7. package/dist/autopilot/intent-engine.js +14 -0
  8. package/dist/autopilot/intent-engine.js.map +1 -1
  9. package/dist/autopilot/quality-gate.d.ts +7 -0
  10. package/dist/autopilot/quality-gate.d.ts.map +1 -1
  11. package/dist/autopilot/quality-gate.js +8 -0
  12. package/dist/autopilot/quality-gate.js.map +1 -1
  13. package/dist/cli/commands/init.d.ts +21 -0
  14. package/dist/cli/commands/init.d.ts.map +1 -1
  15. package/dist/cli/commands/init.js +203 -3
  16. package/dist/cli/commands/init.js.map +1 -1
  17. package/dist/cli/index.js +2 -1
  18. package/dist/cli/index.js.map +1 -1
  19. package/dist/cli/tui.d.ts.map +1 -1
  20. package/dist/cli/tui.js +2 -0
  21. package/dist/cli/tui.js.map +1 -1
  22. package/dist/config/defaults.d.ts.map +1 -1
  23. package/dist/config/defaults.js +0 -2
  24. package/dist/config/defaults.js.map +1 -1
  25. package/dist/config/schema.d.ts +0 -2
  26. package/dist/config/schema.d.ts.map +1 -1
  27. package/dist/config/schema.js +0 -4
  28. package/dist/config/schema.js.map +1 -1
  29. package/dist/daemon/engine-registry/init-autopilot.d.ts +0 -2
  30. package/dist/daemon/engine-registry/init-autopilot.d.ts.map +1 -1
  31. package/dist/daemon/engine-registry/init-autopilot.js +2 -6
  32. package/dist/daemon/engine-registry/init-autopilot.js.map +1 -1
  33. package/dist/daemon/engine-registry.d.ts.map +1 -1
  34. package/dist/daemon/engine-registry.js +1 -2
  35. package/dist/daemon/engine-registry.js.map +1 -1
  36. package/dist/daemon/handler-context.d.ts +0 -2
  37. package/dist/daemon/handler-context.d.ts.map +1 -1
  38. package/dist/daemon/handlers/post-tool-use-handler.d.ts.map +1 -1
  39. package/dist/daemon/handlers/post-tool-use-handler.js +7 -0
  40. package/dist/daemon/handlers/post-tool-use-handler.js.map +1 -1
  41. package/dist/daemon/handlers/pre-tool-use-handler.d.ts.map +1 -1
  42. package/dist/daemon/handlers/pre-tool-use-handler.js +12 -13
  43. package/dist/daemon/handlers/pre-tool-use-handler.js.map +1 -1
  44. package/dist/daemon/handlers/stop-handler.d.ts.map +1 -1
  45. package/dist/daemon/handlers/stop-handler.js +20 -7
  46. package/dist/daemon/handlers/stop-handler.js.map +1 -1
  47. package/dist/daemon/handlers/user-prompt-handler.d.ts +4 -8
  48. package/dist/daemon/handlers/user-prompt-handler.d.ts.map +1 -1
  49. package/dist/daemon/handlers/user-prompt-handler.js +14 -44
  50. package/dist/daemon/handlers/user-prompt-handler.js.map +1 -1
  51. package/dist/daemon/index.d.ts.map +1 -1
  52. package/dist/daemon/index.js +7 -13
  53. package/dist/daemon/index.js.map +1 -1
  54. package/dist/hooks/check-context-limit.sh +0 -0
  55. package/dist/skill-registry/evolver.d.ts.map +1 -1
  56. package/dist/skill-registry/evolver.js +4 -2
  57. package/dist/skill-registry/evolver.js.map +1 -1
  58. package/package.json +10 -4
  59. package/dist/cli/commands/console.d.ts +0 -3
  60. package/dist/cli/commands/console.d.ts.map +0 -1
  61. package/dist/cli/commands/console.js +0 -11
  62. package/dist/cli/commands/console.js.map +0 -1
  63. package/dist/cli/interceptor.d.ts +0 -5
  64. package/dist/cli/interceptor.d.ts.map +0 -1
  65. package/dist/cli/interceptor.js +0 -55
  66. package/dist/cli/interceptor.js.map +0 -1
  67. package/dist/hooks/hooks/check-context-limit.sh +0 -97
  68. package/dist/hooks/hooks/notification.sh +0 -33
  69. package/dist/hooks/hooks/post-tool-use.sh +0 -49
  70. package/dist/hooks/hooks/pre-tool-use.sh +0 -55
  71. package/dist/hooks/hooks/stop.sh +0 -29
  72. package/dist/hooks/hooks/user-prompt-submit.sh +0 -72
  73. package/dist/skill-registry/recommender.d.ts +0 -25
  74. package/dist/skill-registry/recommender.d.ts.map +0 -1
  75. package/dist/skill-registry/recommender.js +0 -91
  76. package/dist/skill-registry/recommender.js.map +0 -1
  77. package/dist/tests/claude-api.test.d.ts +0 -2
  78. package/dist/tests/claude-api.test.d.ts.map +0 -1
  79. package/dist/tests/claude-api.test.js +0 -96
  80. package/dist/tests/claude-api.test.js.map +0 -1
  81. package/dist/tests/conversational-config-handler.test.d.ts +0 -2
  82. package/dist/tests/conversational-config-handler.test.d.ts.map +0 -1
  83. package/dist/tests/conversational-config-handler.test.js +0 -107
  84. package/dist/tests/conversational-config-handler.test.js.map +0 -1
  85. package/dist/tests/doc-sync.test.d.ts +0 -2
  86. package/dist/tests/doc-sync.test.d.ts.map +0 -1
  87. package/dist/tests/doc-sync.test.js +0 -148
  88. package/dist/tests/doc-sync.test.js.map +0 -1
  89. package/dist/tests/orchestration-config.test.d.ts +0 -2
  90. package/dist/tests/orchestration-config.test.d.ts.map +0 -1
  91. package/dist/tests/orchestration-config.test.js +0 -122
  92. package/dist/tests/orchestration-config.test.js.map +0 -1
  93. package/dist/tests/pipeline-options.test.d.ts +0 -2
  94. package/dist/tests/pipeline-options.test.d.ts.map +0 -1
  95. package/dist/tests/pipeline-options.test.js +0 -68
  96. package/dist/tests/pipeline-options.test.js.map +0 -1
  97. package/dist/tests/resume-context-gen.test.d.ts +0 -2
  98. package/dist/tests/resume-context-gen.test.d.ts.map +0 -1
  99. package/dist/tests/resume-context-gen.test.js +0 -93
  100. package/dist/tests/resume-context-gen.test.js.map +0 -1
  101. package/dist/tests/sqlite.test.d.ts +0 -2
  102. package/dist/tests/sqlite.test.d.ts.map +0 -1
  103. package/dist/tests/sqlite.test.js +0 -154
  104. package/dist/tests/sqlite.test.js.map +0 -1
  105. package/dist/tests/tracker.test.d.ts +0 -2
  106. package/dist/tests/tracker.test.d.ts.map +0 -1
  107. package/dist/tests/tracker.test.js +0 -75
  108. package/dist/tests/tracker.test.js.map +0 -1
  109. package/dist/tests/tui.test.d.ts +0 -2
  110. package/dist/tests/tui.test.d.ts.map +0 -1
  111. package/dist/tests/tui.test.js +0 -39
  112. package/dist/tests/tui.test.js.map +0 -1
  113. package/dist/tests/user-prompt-handler.test.d.ts +0 -2
  114. package/dist/tests/user-prompt-handler.test.d.ts.map +0 -1
  115. package/dist/tests/user-prompt-handler.test.js +0 -182
  116. package/dist/tests/user-prompt-handler.test.js.map +0 -1
  117. package/dist/tui/index.d.ts +0 -2
  118. package/dist/tui/index.d.ts.map +0 -1
  119. package/dist/tui/index.js +0 -486
  120. package/dist/tui/index.js.map +0 -1
@@ -1,55 +0,0 @@
1
- #!/usr/bin/env bash
2
- # Claude Forge - PreToolUse Hook(双向通信)
3
-
4
- SOCKET_PATH="${CLAUDE_FORGE_SOCKET:-$HOME/.claude-forge/daemon.sock}"
5
-
6
- # 读取 stdin(Claude Code 传入的 JSON)
7
- INPUT=$(cat)
8
-
9
- # 提取字段
10
- TOOL_NAME="${CLAUDE_TOOL_NAME:-$(echo "$INPUT" | python3 -c 'import sys,json; d=json.load(sys.stdin); print(d.get("tool_name",""))' 2>/dev/null || echo '')}"
11
- TOOL_INPUT=$(echo "$INPUT" | python3 -c 'import sys,json; d=json.load(sys.stdin); print(json.dumps(d.get("tool_input",{})))' 2>/dev/null || echo '{}')
12
- PROJECT_PATH=$(echo "$INPUT" | python3 -c 'import sys,json; d=json.load(sys.stdin); print(d.get("cwd",""))' 2>/dev/null || echo '')
13
- PROJECT_PATH="${PROJECT_PATH:-${PWD}}"
14
-
15
- # 构造事件 JSON(通过环境变量传参,避免 shell 注入)
16
- EVENT=$(FORGE_TOOL_NAME="$TOOL_NAME" FORGE_TOOL_INPUT="$TOOL_INPUT" FORGE_PROJECT_PATH="$PROJECT_PATH" \
17
- python3 -c "
18
- import json, os
19
- from datetime import datetime
20
- tool_input_raw = os.environ.get('FORGE_TOOL_INPUT', '{}')
21
- try:
22
- tool_input = json.loads(tool_input_raw)
23
- except Exception:
24
- tool_input = {}
25
- print(json.dumps({
26
- 'hook_type': 'PreToolUse',
27
- 'timestamp': datetime.now().strftime('%Y-%m-%dT%H:%M:%S'),
28
- 'session_id': os.environ.get('CLAUDE_CODE_SESSION_ID', 'cli'),
29
- 'project_path': os.environ.get('FORGE_PROJECT_PATH', ''),
30
- 'tool_name': os.environ.get('FORGE_TOOL_NAME', ''),
31
- 'tool_input': tool_input,
32
- }))
33
- " 2>/dev/null)
34
-
35
- # 发送事件并等待响应(双向通信,5 秒超时)
36
- RESPONSE=$(echo "$EVENT" | nc -U -w 5 "$SOCKET_PATH" 2>/dev/null)
37
-
38
- if [ -n "$RESPONSE" ]; then
39
- # 解析响应
40
- ALLOW=$(echo "$RESPONSE" | python3 -c 'import sys,json; d=json.load(sys.stdin); print(str(d.get("allow",True)).lower())' 2>/dev/null || echo 'true')
41
-
42
- if [ "$ALLOW" = "false" ]; then
43
- # 输出拦截 JSON 到 stdout(Claude Code 读取)
44
- echo "$RESPONSE"
45
- exit 2
46
- fi
47
-
48
- # 有 additionalContext 时输出
49
- HAS_CONTEXT=$(echo "$RESPONSE" | python3 -c 'import sys,json; d=json.load(sys.stdin); print("yes" if d.get("additionalContext") else "no")' 2>/dev/null || echo 'no')
50
- if [ "$HAS_CONTEXT" = "yes" ]; then
51
- echo "$RESPONSE"
52
- fi
53
- fi
54
-
55
- exit 0
@@ -1,29 +0,0 @@
1
- #!/usr/bin/env bash
2
- # Claude Forge - Stop Hook
3
-
4
- SOCKET_PATH="${CLAUDE_FORGE_SOCKET:-$HOME/.claude-forge/daemon.sock}"
5
-
6
- # 读取 stdin
7
- INPUT=$(cat 2>/dev/null || echo '{}')
8
-
9
- # 提取 cwd
10
- PROJECT_PATH=$(echo "$INPUT" | python3 -c 'import sys,json; d=json.load(sys.stdin); print(d.get("cwd",""))' 2>/dev/null || echo '')
11
- PROJECT_PATH="${PROJECT_PATH:-${PWD}}"
12
-
13
- # 构造事件 JSON(通过环境变量传参,避免 shell 注入)
14
- EVENT=$(FORGE_PROJECT_PATH="$PROJECT_PATH" \
15
- python3 -c "
16
- import json, os
17
- from datetime import datetime
18
- print(json.dumps({
19
- 'hook_type': 'Stop',
20
- 'timestamp': datetime.now().strftime('%Y-%m-%dT%H:%M:%S'),
21
- 'session_id': os.environ.get('CLAUDE_CODE_SESSION_ID', 'cli'),
22
- 'project_path': os.environ.get('FORGE_PROJECT_PATH', ''),
23
- 'tool_name': 'stop',
24
- 'tool_input': {},
25
- }))
26
- " 2>/dev/null)
27
-
28
- echo "$EVENT" | nc -U -w 1 "$SOCKET_PATH" 2>/dev/null || true
29
- exit 0
@@ -1,72 +0,0 @@
1
- #!/usr/bin/env bash
2
- # Claude Forge - UserPromptSubmit Hook
3
- # 拦截用户输入,触发意图分析和自动 Pipeline 编排
4
-
5
- SOCKET_PATH="${CLAUDE_FORGE_SOCKET:-$HOME/.claude-forge/daemon.sock}"
6
-
7
- # daemon 未运行,快速跳过
8
- if [ ! -S "$SOCKET_PATH" ]; then
9
- exit 0
10
- fi
11
-
12
- # 读取 stdin(Claude Code 传入的 JSON)
13
- INPUT=$(cat)
14
-
15
- # 提取字段
16
- USER_PROMPT=$(echo "$INPUT" | python3 -c 'import sys,json; d=json.load(sys.stdin); print(d.get("prompt",""))' 2>/dev/null || echo '')
17
- PROJECT_PATH=$(echo "$INPUT" | python3 -c 'import sys,json; d=json.load(sys.stdin); print(d.get("cwd",""))' 2>/dev/null || echo '')
18
- PROJECT_PATH="${PROJECT_PATH:-${PWD}}"
19
-
20
- # 空 prompt 跳过
21
- if [ -z "$USER_PROMPT" ]; then
22
- exit 0
23
- fi
24
-
25
- # 安全地构造事件 JSON(通过环境变量传参,避免 shell 注入)
26
- EVENT=$(FORGE_USER_PROMPT="$USER_PROMPT" FORGE_PROJECT_PATH="$PROJECT_PATH" \
27
- python3 -c "
28
- import json, os
29
- from datetime import datetime
30
- print(json.dumps({
31
- 'hook_type': 'UserPromptSubmit',
32
- 'timestamp': datetime.now().strftime('%Y-%m-%dT%H:%M:%S'),
33
- 'session_id': os.environ.get('CLAUDE_CODE_SESSION_ID', 'cli'),
34
- 'project_path': os.environ.get('FORGE_PROJECT_PATH', ''),
35
- 'tool_name': 'UserPrompt',
36
- 'tool_input': {'user_prompt': os.environ.get('FORGE_USER_PROMPT', '')},
37
- }))
38
- " 2>/dev/null)
39
-
40
- if [ -z "$EVENT" ]; then
41
- exit 0
42
- fi
43
-
44
- # 发送事件并等待响应(10 秒超时,AI 分析可能需要更多时间)
45
- RESPONSE=$(echo "$EVENT" | nc -U -w 10 "$SOCKET_PATH" 2>/dev/null)
46
-
47
- if [ -n "$RESPONSE" ]; then
48
- HAS_CONTEXT=$(echo "$RESPONSE" | python3 -c 'import sys,json; d=json.load(sys.stdin); print("yes" if d.get("additionalContext") else "no")' 2>/dev/null || echo 'no')
49
- if [ "$HAS_CONTEXT" = "yes" ]; then
50
- # stderr 输出到终端,让用户实时看到决策过程
51
- # 用 fd3 保存真实 stderr,python3 错误丢弃,面板输出保留
52
- exec 3>&2
53
- echo "$RESPONSE" | python3 -c '
54
- import sys, json, os
55
- d = json.load(sys.stdin)
56
- ctx = d.get("additionalContext", "")
57
- lines = []
58
- for line in ctx.split("\n"):
59
- if line.startswith("请在回复"):
60
- break
61
- if line.strip():
62
- lines.append(line)
63
- if lines:
64
- os.write(3, ("\033[36m" + "\n".join(lines) + "\033[0m\n").encode())
65
- ' 2>/dev/null
66
- exec 3>&-
67
- # stdout 返回给 Claude Code
68
- echo "$RESPONSE"
69
- fi
70
- fi
71
-
72
- exit 0
@@ -1,25 +0,0 @@
1
- import type { ForgeEvent } from '../types/index.js';
2
- import { SkillRegistry } from './registry.js';
3
- export declare class SkillRecommender {
4
- private registry;
5
- private sessionRecommended;
6
- constructor(registry: SkillRegistry);
7
- /**
8
- * 根据工具调用事件推荐 Skill
9
- * 返回 additionalContext 或 null
10
- */
11
- recommend(event: ForgeEvent): string | null;
12
- /**
13
- * 检测工具调用中是否使用了已注册的 Skill
14
- */
15
- private detectSkillUsage;
16
- /**
17
- * 根据工具调用内容匹配可能有用的 Skill
18
- */
19
- private matchSkills;
20
- /**
21
- * 会话结束时重置推荐记录
22
- */
23
- resetSession(): void;
24
- }
25
- //# sourceMappingURL=recommender.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"recommender.d.ts","sourceRoot":"","sources":["../../src/skill-registry/recommender.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAG9C,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAgB;IAChC,OAAO,CAAC,kBAAkB,CAAqB;gBAEnC,QAAQ,EAAE,aAAa;IAInC;;;OAGG;IACH,SAAS,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,GAAG,IAAI;IAyB3C;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAqBxB;;OAEG;IACH,OAAO,CAAC,WAAW;IAkCnB;;OAEG;IACH,YAAY,IAAI,IAAI;CAGrB"}
@@ -1,91 +0,0 @@
1
- export class SkillRecommender {
2
- registry;
3
- sessionRecommended = new Set();
4
- constructor(registry) {
5
- this.registry = registry;
6
- }
7
- /**
8
- * 根据工具调用事件推荐 Skill
9
- * 返回 additionalContext 或 null
10
- */
11
- recommend(event) {
12
- const inputStr = event.tool_input ? JSON.stringify(event.tool_input) : '';
13
- const toolName = event.tool_name || '';
14
- // 检测 Skill 调用(Bash 中包含 skill 名或 lark-cli 等)
15
- this.detectSkillUsage(event);
16
- // 根据上下文推荐(只在每个 session 推荐一次)
17
- const recommendations = this.matchSkills(toolName, inputStr);
18
- const newRecs = recommendations.filter(r => !this.sessionRecommended.has(r.name));
19
- if (newRecs.length === 0)
20
- return null;
21
- // 标记已推荐
22
- for (const r of newRecs) {
23
- this.sessionRecommended.add(r.name);
24
- }
25
- const recList = newRecs
26
- .map(r => `- **${r.name}**: ${r.description.substring(0, 80)}`)
27
- .join('\n');
28
- return `[Forge 能力推荐] 检测到相关操作,以下 Skill 可能有帮助:\n${recList}`;
29
- }
30
- /**
31
- * 检测工具调用中是否使用了已注册的 Skill
32
- */
33
- detectSkillUsage(event) {
34
- if (event.tool_name !== 'Bash' && event.tool_name !== 'Skill')
35
- return;
36
- const inputStr = event.tool_input ? JSON.stringify(event.tool_input) : '';
37
- // 检测 lark-cli 调用
38
- const larkMatch = inputStr.match(/lark-cli\s+(\w+)/);
39
- if (larkMatch) {
40
- const skillName = `lark-${larkMatch[1]}`;
41
- this.registry.recordUsage(skillName, true);
42
- }
43
- // 检测 Skill 工具调用
44
- if (event.tool_name === 'Skill') {
45
- const skillField = event.tool_input?.skill;
46
- if (skillField) {
47
- this.registry.recordUsage(skillField, true);
48
- }
49
- }
50
- }
51
- /**
52
- * 根据工具调用内容匹配可能有用的 Skill
53
- */
54
- matchSkills(toolName, inputStr) {
55
- const matches = [];
56
- const allSkills = this.registry.getAll();
57
- const input = inputStr.toLowerCase();
58
- // 关键词 → Skill 映射
59
- const KEYWORD_MAP = [
60
- { keywords: ['飞书', 'feishu', 'lark'], skills: ['lark-shared'] },
61
- { keywords: ['日历', 'calendar', '日程', '会议'], skills: ['lark-calendar'] },
62
- { keywords: ['消息', 'message', '群聊', 'chat'], skills: ['lark-im'] },
63
- { keywords: ['文档', 'document', 'doc'], skills: ['lark-doc'] },
64
- { keywords: ['表格', 'sheet', 'spreadsheet'], skills: ['lark-sheets'] },
65
- { keywords: ['多维表格', 'bitable', 'base'], skills: ['lark-base'] },
66
- { keywords: ['任务', 'task', '待办', 'todo'], skills: ['lark-task'] },
67
- { keywords: ['邮件', 'email', 'mail'], skills: ['lark-mail'] },
68
- { keywords: ['知识库', 'wiki'], skills: ['lark-wiki'] },
69
- { keywords: ['云空间', 'drive', '文件管理'], skills: ['lark-drive'] },
70
- { keywords: ['通讯录', 'contact', '员工', '搜索人'], skills: ['lark-contact'] },
71
- ];
72
- for (const mapping of KEYWORD_MAP) {
73
- if (mapping.keywords.some(kw => input.includes(kw))) {
74
- for (const skillName of mapping.skills) {
75
- const skill = this.registry.get(skillName);
76
- if (skill && !matches.some(m => m.name === skill.name)) {
77
- matches.push(skill);
78
- }
79
- }
80
- }
81
- }
82
- return matches;
83
- }
84
- /**
85
- * 会话结束时重置推荐记录
86
- */
87
- resetSession() {
88
- this.sessionRecommended.clear();
89
- }
90
- }
91
- //# sourceMappingURL=recommender.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"recommender.js","sourceRoot":"","sources":["../../src/skill-registry/recommender.ts"],"names":[],"mappings":"AAKA,MAAM,OAAO,gBAAgB;IACnB,QAAQ,CAAgB;IACxB,kBAAkB,GAAG,IAAI,GAAG,EAAU,CAAC;IAE/C,YAAY,QAAuB;QACjC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED;;;OAGG;IACH,SAAS,CAAC,KAAiB;QACzB,MAAM,QAAQ,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1E,MAAM,QAAQ,GAAG,KAAK,CAAC,SAAS,IAAI,EAAE,CAAC;QAEvC,4CAA4C;QAC5C,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;QAE7B,6BAA6B;QAC7B,MAAM,eAAe,GAAG,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAC7D,MAAM,OAAO,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QAElF,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QAEtC,QAAQ;QACR,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACxB,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACtC,CAAC;QAED,MAAM,OAAO,GAAG,OAAO;aACpB,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;aAC9D,IAAI,CAAC,IAAI,CAAC,CAAC;QAEd,OAAO,yCAAyC,OAAO,EAAE,CAAC;IAC5D,CAAC;IAED;;OAEG;IACK,gBAAgB,CAAC,KAAiB;QACxC,IAAI,KAAK,CAAC,SAAS,KAAK,MAAM,IAAI,KAAK,CAAC,SAAS,KAAK,OAAO;YAAE,OAAO;QAEtE,MAAM,QAAQ,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAE1E,iBAAiB;QACjB,MAAM,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;QACrD,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,SAAS,GAAG,QAAQ,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;YACzC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QAC7C,CAAC;QAED,gBAAgB;QAChB,IAAI,KAAK,CAAC,SAAS,KAAK,OAAO,EAAE,CAAC;YAChC,MAAM,UAAU,GAAG,KAAK,CAAC,UAAU,EAAE,KAA2B,CAAC;YACjE,IAAI,UAAU,EAAE,CAAC;gBACf,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;YAC9C,CAAC;QACH,CAAC;IACH,CAAC;IAED;;OAEG;IACK,WAAW,CAAC,QAAgB,EAAE,QAAgB;QACpD,MAAM,OAAO,GAAgB,EAAE,CAAC;QAChC,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;QACzC,MAAM,KAAK,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;QAErC,iBAAiB;QACjB,MAAM,WAAW,GAAoD;YACnE,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,aAAa,CAAC,EAAE;YAC/D,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,eAAe,CAAC,EAAE;YACvE,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,SAAS,CAAC,EAAE;YAClE,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC,UAAU,CAAC,EAAE;YAC7D,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC,aAAa,CAAC,EAAE;YACrE,EAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,WAAW,CAAC,EAAE;YAChE,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,WAAW,CAAC,EAAE;YACjE,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,WAAW,CAAC,EAAE;YAC5D,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,WAAW,CAAC,EAAE;YACpD,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,YAAY,CAAC,EAAE;YAC9D,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC,cAAc,CAAC,EAAE;SACxE,CAAC;QAEF,KAAK,MAAM,OAAO,IAAI,WAAW,EAAE,CAAC;YAClC,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;gBACpD,KAAK,MAAM,SAAS,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;oBACvC,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;oBAC3C,IAAI,KAAK,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;wBACvD,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;oBACtB,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;OAEG;IACH,YAAY;QACV,IAAI,CAAC,kBAAkB,CAAC,KAAK,EAAE,CAAC;IAClC,CAAC;CACF"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=claude-api.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"claude-api.test.d.ts","sourceRoot":"","sources":["../../src/tests/claude-api.test.ts"],"names":[],"mappings":""}
@@ -1,96 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
2
- const mockCreate = vi.hoisted(() => vi.fn());
3
- vi.mock('@anthropic-ai/sdk', () => ({
4
- default: vi.fn(function () {
5
- return { messages: { create: mockCreate } };
6
- }),
7
- }));
8
- import { ClaudeAPI, ApiTimeoutError, CircuitOpenError } from '../utils/claude-api.js';
9
- function makeApi() {
10
- process.env.ANTHROPIC_API_KEY = 'test-key';
11
- return new ClaudeAPI(undefined, 'claude-test');
12
- }
13
- function okResponse(text = 'ok') {
14
- return Promise.resolve({ content: [{ type: 'text', text }] });
15
- }
16
- describe('ClaudeAPI', () => {
17
- beforeEach(() => {
18
- process.env.ANTHROPIC_API_KEY = 'test-key';
19
- mockCreate.mockReset();
20
- });
21
- afterEach(() => {
22
- delete process.env.ANTHROPIC_API_KEY;
23
- });
24
- // ── 正常调用 ──────────────────────────────────────────────────────────────
25
- it('成功调用返回文本内容', async () => {
26
- mockCreate.mockReturnValueOnce(okResponse('hello'));
27
- expect(await makeApi().complete('prompt')).toBe('hello');
28
- });
29
- it('content 为空时返回空字符串', async () => {
30
- mockCreate.mockReturnValueOnce(Promise.resolve({ content: [] }));
31
- expect(await makeApi().complete('prompt')).toBe('');
32
- });
33
- // ── 重试逻辑 ──────────────────────────────────────────────────────────────
34
- it('网络错误后重试并最终成功', async () => {
35
- mockCreate
36
- .mockRejectedValueOnce(new Error('network'))
37
- .mockReturnValueOnce(okResponse('ok'));
38
- const api = makeApi();
39
- expect(await api.complete('prompt', 'test', 1, 30_000)).toBe('ok');
40
- expect(mockCreate).toHaveBeenCalledTimes(2);
41
- expect(api.getStats().totalRetries).toBe(1);
42
- });
43
- it('4xx 错误不重试', async () => {
44
- mockCreate.mockRejectedValue(Object.assign(new Error('bad request'), { status: 400 }));
45
- const api = makeApi();
46
- await expect(api.complete('prompt', 'test', 2, 30_000)).rejects.toThrow('bad request');
47
- expect(mockCreate).toHaveBeenCalledTimes(1);
48
- });
49
- it('超时后抛出 ApiTimeoutError 且不重试', async () => {
50
- mockCreate.mockReturnValue(new Promise(() => { })); // never resolves
51
- const api = makeApi();
52
- await expect(api.complete('prompt', 'test', 2, 10)).rejects.toBeInstanceOf(ApiTimeoutError);
53
- expect(mockCreate).toHaveBeenCalledTimes(1);
54
- });
55
- // ── 熔断器 ────────────────────────────────────────────────────────────────
56
- it('连续失败 5 次后触发熔断', async () => {
57
- mockCreate.mockRejectedValue(new Error('server error'));
58
- const api = makeApi();
59
- for (let i = 0; i < 5; i++) {
60
- await expect(api.complete('prompt', 'test', 0, 30_000)).rejects.toThrow();
61
- }
62
- await expect(api.complete('prompt', 'test', 0, 30_000)).rejects.toBeInstanceOf(CircuitOpenError);
63
- expect(api.getStats().circuitBreakerTrips).toBe(1);
64
- });
65
- it('成功后重置熔断计数', async () => {
66
- mockCreate
67
- .mockRejectedValueOnce(new Error('fail'))
68
- .mockReturnValueOnce(okResponse())
69
- .mockRejectedValue(new Error('fail'));
70
- const api = makeApi();
71
- await expect(api.complete('prompt', 'test', 0, 30_000)).rejects.toThrow();
72
- await api.complete('prompt', 'test', 0, 30_000);
73
- for (let i = 0; i < 4; i++) {
74
- await expect(api.complete('prompt', 'test', 0, 30_000)).rejects.toThrow('fail');
75
- }
76
- expect(api.getStats().circuitBreakerTrips).toBe(0);
77
- });
78
- // ── 统计 ──────────────────────────────────────────────────────────────────
79
- it('formatStats 包含调用数', async () => {
80
- mockCreate.mockReturnValue(okResponse());
81
- const api = makeApi();
82
- await api.complete('prompt', 'distill');
83
- const stats = api.formatStats();
84
- expect(stats).toContain('API calls: 1');
85
- expect(stats).toContain('[distill]');
86
- });
87
- it('getStats 返回快照,修改不影响内部状态', async () => {
88
- mockCreate.mockReturnValue(okResponse());
89
- const api = makeApi();
90
- await api.complete('prompt', 'x');
91
- const snap = api.getStats();
92
- snap.totalCalls = 999;
93
- expect(api.getStats().totalCalls).toBe(1);
94
- });
95
- });
96
- //# sourceMappingURL=claude-api.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"claude-api.test.js","sourceRoot":"","sources":["../../src/tests/claude-api.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=conversational-config-handler.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"conversational-config-handler.test.d.ts","sourceRoot":"","sources":["../../src/tests/conversational-config-handler.test.ts"],"names":[],"mappings":""}
@@ -1,107 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach } from 'vitest';
2
- const { mockModulesConfigManager, mockClaudeMdEngine } = vi.hoisted(() => {
3
- const mockModulesConfigRead = vi.fn().mockReturnValue({});
4
- const mockModulesConfigWrite = vi.fn();
5
- const mockClaudeMdGenerate = vi.fn().mockResolvedValue(true);
6
- const mockClaudeMdRefine = vi.fn().mockResolvedValue(true);
7
- const mockModulesConfigManager = vi.fn(function () {
8
- return { read: mockModulesConfigRead, write: mockModulesConfigWrite };
9
- });
10
- const mockClaudeMdEngine = vi.fn(function () {
11
- return { generate: mockClaudeMdGenerate, refine: mockClaudeMdRefine };
12
- });
13
- return { mockModulesConfigManager, mockClaudeMdEngine };
14
- });
15
- vi.mock('../claudemd/modules-config.js', () => ({
16
- ModulesConfigManager: mockModulesConfigManager,
17
- }));
18
- vi.mock('../claudemd/index.js', () => ({
19
- ClaudeMdEngine: mockClaudeMdEngine,
20
- }));
21
- vi.mock('fs', async (importOriginal) => {
22
- const actual = await importOriginal();
23
- const mocked = {
24
- ...actual,
25
- existsSync: vi.fn().mockReturnValue(false),
26
- unlinkSync: vi.fn(),
27
- mkdirSync: vi.fn(),
28
- writeFileSync: vi.fn(),
29
- readFileSync: vi.fn().mockReturnValue(''),
30
- };
31
- return { ...mocked, default: mocked };
32
- });
33
- import { ConversationalConfigHandler } from '../daemon/handlers/conversational-config-handler.js';
34
- function makeCtx(overrides = {}) {
35
- return {
36
- storage: { queryEvents: vi.fn().mockReturnValue([]) },
37
- config: {},
38
- trigger: null,
39
- resumeEngine: null,
40
- orchestration: null,
41
- skillRegistry: {},
42
- pipelineEngine: null,
43
- intentEngine: null,
44
- knowledgeEngine: null,
45
- qualityGate: null,
46
- profileManager: null,
47
- sharedApi: { complete: vi.fn() },
48
- patternEngine: null,
49
- conventionManager: { getActivePrompt: vi.fn().mockReturnValue(null), getActiveConventions: vi.fn().mockReturnValue([]) },
50
- checkedProjects: new Set(),
51
- ...overrides,
52
- };
53
- }
54
- describe('ConversationalConfigHandler', () => {
55
- let handler;
56
- beforeEach(() => {
57
- vi.clearAllMocks();
58
- handler = new ConversationalConfigHandler(makeCtx());
59
- });
60
- // ── 无匹配 ────────────────────────────────────────────────────────────────
61
- it('无意图时返回 undefined', async () => {
62
- expect(await handler.handle('帮我写一个排序算法', '/proj')).toBeUndefined();
63
- });
64
- // ── 人设意图 ──────────────────────────────────────────────────────────────
65
- it('检测"设置人设为"意图', async () => {
66
- const result = await handler.handle('设置人设为:资深 TypeScript 工程师', '/proj');
67
- expect(result).toBeDefined();
68
- expect(result).toContain('已设置人设');
69
- });
70
- it('检测"重置人设"意图(无已有人设)', async () => {
71
- const result = await handler.handle('重置人设', '/proj');
72
- expect(result).toBeDefined();
73
- expect(result).toContain('人设');
74
- });
75
- it('人设内容为空时不抛出', async () => {
76
- await expect(handler.handle('设置人设为:', '/proj')).resolves.toBeDefined();
77
- });
78
- // ── CLAUDE.md 意图 ────────��───────────────────────────────────────────────
79
- it('检测"生成 CLAUDE.md"意图', async () => {
80
- const result = await handler.handle('生成 CLAUDE.md', '/proj');
81
- expect(result).toBeDefined();
82
- expect(result).toContain('CLAUDE.md');
83
- });
84
- it('检测"强制生成 CLAUDE.md"意图', async () => {
85
- const result = await handler.handle('强制生成 CLAUDE.md', '/proj');
86
- expect(result).toBeDefined();
87
- expect(result).toContain('CLAUDE.md');
88
- });
89
- it('检测"细化 CLAUDE.md"意图', async () => {
90
- const result = await handler.handle('细化 CLAUDE.md', '/proj');
91
- expect(result).toBeDefined();
92
- });
93
- it('sharedApi 为 null 时 CLAUDE.md 操作返回不可用提示', async () => {
94
- handler = new ConversationalConfigHandler(makeCtx({ sharedApi: null }));
95
- const result = await handler.handle('生成 CLAUDE.md', '/proj');
96
- expect(result).toContain('不可用');
97
- });
98
- // ── 技能意图 ──────────────────────────────────────────────────────────────
99
- it('skillRegistry 为 null 时返回不可用提示', async () => {
100
- handler = new ConversationalConfigHandler(makeCtx({
101
- skillRegistry: null,
102
- }));
103
- const result = await handler.handle('添加技能 sk:内容', '/proj');
104
- expect(result).toContain('不可用');
105
- });
106
- });
107
- //# sourceMappingURL=conversational-config-handler.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"conversational-config-handler.test.js","sourceRoot":"","sources":["../../src/tests/conversational-config-handler.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=doc-sync.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"doc-sync.test.d.ts","sourceRoot":"","sources":["../../src/tests/doc-sync.test.ts"],"names":[],"mappings":""}