aico-cli 2.0.29 → 2.0.30
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/bin/cli/cli.js +2859 -2503
- package/bin/cli/package.json +1 -1
- package/bin/cli/sdk-tools.d.ts +6 -2
- package/dist/chunks/simple-config.mjs +527 -31
- package/dist/cli.mjs +125 -480
- package/dist/index.mjs +1 -0
- package/package.json +11 -3
- package/templates/agents/agent-capability-map.json +598 -0
- package/templates/agents/agent-selector.ts +991 -0
- package/templates/agents/auto-task-executor.ts +222 -0
- package/templates/agents/bonus/studio-coach.md +133 -0
- package/templates/agents/core/code-archaeologist.md +89 -0
- package/templates/agents/core/code-reviewer.md +88 -0
- package/templates/agents/core/documentation-specialist.md +100 -0
- package/templates/agents/core/performance-optimizer.md +67 -0
- package/templates/agents/databases/customer-support.md +34 -0
- package/templates/agents/databases/data-engineer.md +31 -0
- package/templates/agents/databases/data-scientist.md +28 -0
- package/templates/agents/databases/database-admin.md +31 -0
- package/templates/agents/databases/database-optimizer.md +31 -0
- package/templates/agents/deployment/debugger.md +29 -0
- package/templates/agents/deployment/deployment-engineer.md +31 -0
- package/templates/agents/deployment/devops-troubleshooter.md +31 -0
- package/templates/agents/deployment/dx-optimizer.md +62 -0
- package/templates/agents/deployment/error-detective.md +31 -0
- package/templates/agents/deployment/legacy-modernizer.md +31 -0
- package/templates/agents/deployment/network-engineer.md +31 -0
- package/templates/agents/deployment/payment-integration.md +31 -0
- package/templates/agents/deployment/performance-engineer.md +31 -0
- package/templates/agents/deployment/prompt-engineer.md +58 -0
- package/templates/agents/deployment/quant-analyst.md +31 -0
- package/templates/agents/deployment/refactor-agent.md +77 -0
- package/templates/agents/deployment/risk-manager.md +40 -0
- package/templates/agents/deployment/sales-automator.md +34 -0
- package/templates/agents/deployment/search-specialist.md +96 -0
- package/templates/agents/deployment/security-auditor.md +31 -0
- package/templates/agents/design/brand-guardian.md +278 -0
- package/templates/agents/design/frontend-analyst.md +42 -0
- package/templates/agents/design/ui-designer.md +157 -0
- package/templates/agents/design/ui-ux-master.md +568 -0
- package/templates/agents/design/ux-researcher.md +210 -0
- package/templates/agents/design/visual-storyteller.md +271 -0
- package/templates/agents/design/whimsy-injector.md +148 -0
- package/templates/agents/engineering/backend/ai-engineer.md +118 -0
- package/templates/agents/engineering/backend/backend-architect.md +95 -0
- package/templates/agents/engineering/backend/senior-backend-architect.md +554 -0
- package/templates/agents/engineering/frontend/frontend-developer.md +105 -0
- package/templates/agents/engineering/frontend/mobile-app-builder.md +108 -0
- package/templates/agents/engineering/frontend/rapid-prototyper.md +114 -0
- package/templates/agents/engineering/frontend/senior-frontend-architect.md +573 -0
- package/templates/agents/engineering/middlend/api-documenter.md +31 -0
- package/templates/agents/engineering/middlend/architect-review.md +41 -0
- package/templates/agents/engineering/middlend/cloud-architect.md +31 -0
- package/templates/agents/engineering/middlend/code-reviewer.md +28 -0
- package/templates/agents/engineering/middlend/devops-automator.md +118 -0
- package/templates/agents/marketing/app-store-optimizer.md +180 -0
- package/templates/agents/marketing/business-analyst.md +34 -0
- package/templates/agents/marketing/content-creator.md +209 -0
- package/templates/agents/marketing/growth-hacker.md +218 -0
- package/templates/agents/marketing/instagram-curator.md +154 -0
- package/templates/agents/marketing/reddit-community-builder.md +197 -0
- package/templates/agents/marketing/tiktok-strategist.md +151 -0
- package/templates/agents/marketing/twitter-engager.md +175 -0
- package/templates/agents/orchestrators/context-manager.md +63 -0
- package/templates/agents/orchestrators/project-analyst.md +66 -0
- package/templates/agents/orchestrators/team-configurator.md +52 -0
- package/templates/agents/orchestrators/tech-lead-orchestrator.md +103 -0
- package/templates/agents/product/feedback-synthesizer.md +174 -0
- package/templates/agents/product/sprint-prioritizer.md +128 -0
- package/templates/agents/product/trend-researcher.md +133 -0
- package/templates/agents/project-management/experiment-tracker.md +165 -0
- package/templates/agents/project-management/project-shipper.md +190 -0
- package/templates/agents/project-management/studio-producer.md +203 -0
- package/templates/agents/specialist/spec-analyst.md +228 -0
- package/templates/agents/specialist/spec-architect.md +375 -0
- package/templates/agents/specialist/spec-developer.md +544 -0
- package/templates/agents/specialist/spec-orchestrator.md +465 -0
- package/templates/agents/specialist/spec-planner.md +497 -0
- package/templates/agents/specialist/spec-reviewer.md +487 -0
- package/templates/agents/specialist/spec-task-reviewer.md +50 -0
- package/templates/agents/specialist/spec-tester.md +652 -0
- package/templates/agents/specialist/spec-validator.md +441 -0
- package/templates/agents/specialized/C++/cpp-pro.md +37 -0
- package/templates/agents/specialized/Golang/golang-pro.md +31 -0
- package/templates/agents/specialized/JavaScript/javascript-pro.md +34 -0
- package/templates/agents/specialized/Python/python-pro.md +31 -0
- package/templates/agents/specialized/databases/sql-pro.md +34 -0
- package/templates/agents/specialized/django/django-api-developer.md +804 -0
- package/templates/agents/specialized/django/django-backend-expert.md +875 -0
- package/templates/agents/specialized/django/django-orm-expert.md +828 -0
- package/templates/agents/specialized/laravel/laravel-backend-expert.md +174 -0
- package/templates/agents/specialized/laravel/laravel-eloquent-expert.md +75 -0
- package/templates/agents/specialized/rails/rails-activerecord-expert.md +690 -0
- package/templates/agents/specialized/rails/rails-api-developer.md +943 -0
- package/templates/agents/specialized/rails/rails-backend-expert.md +876 -0
- package/templates/agents/specialized/react/react-component-architect.md +41 -0
- package/templates/agents/specialized/react/react-nextjs-expert.md +141 -0
- package/templates/agents/specialized/vue/vue-component-architect.md +98 -0
- package/templates/agents/specialized/vue/vue-nuxt-expert.md +720 -0
- package/templates/agents/specialized/vue/vue-state-manager.md +33 -0
- package/templates/agents/studio-operations/analytics-reporter.md +204 -0
- package/templates/agents/studio-operations/finance-tracker.md +293 -0
- package/templates/agents/studio-operations/infrastructure-maintainer.md +219 -0
- package/templates/agents/studio-operations/legal-compliance-checker.md +259 -0
- package/templates/agents/studio-operations/support-responder.md +166 -0
- package/templates/agents/task-execution-agent.ts +160 -0
- package/templates/agents/testing/api-tester.md +214 -0
- package/templates/agents/testing/integration-test-fixer.md +52 -0
- package/templates/agents/testing/performance-benchmarker.md +277 -0
- package/templates/agents/testing/test-automator.md +31 -0
- package/templates/agents/testing/test-results-analyzer.md +273 -0
- package/templates/agents/testing/test-writer-fixer.md +129 -0
- package/templates/agents/testing/tool-evaluator.md +184 -0
- package/templates/agents/testing/workflow-optimizer.md +239 -0
- package/templates/agents/universal/api-architect.md +84 -0
- package/templates/agents/universal/backend-developer.md +95 -0
- package/templates/agents/universal/frontend-developer.md +66 -0
- package/templates/agents/universal/tailwind-css-expert.md +84 -0
- package/templates/cursor.md +20 -14
- package/templates/hooks/claude-code-hooks.json +22 -7
- package/templates/hooks/hook-wrapper.ts +173 -0
- package/templates/hooks/install-hooks.ts +201 -0
- package/templates/hooks/scripts/Notification/desktop-notifier.ts +268 -0
- package/templates/hooks/scripts/Notification/notification.ts +28 -0
- package/templates/hooks/scripts/PostToolUse/code-formatter.ts +182 -0
- package/templates/hooks/scripts/PostToolUse/post-tool-use.ts +27 -0
- package/templates/hooks/scripts/PreToolUse/command-logger.ts +107 -0
- package/templates/hooks/scripts/PreToolUse/file-protection.ts +109 -0
- package/templates/hooks/scripts/PreToolUse/pre-tool-use.ts +42 -0
- package/templates/hooks/scripts/Stop/session-summary.ts +150 -0
- package/templates/hooks/scripts/Stop/stop.ts +17 -0
- package/templates/hooks/scripts/UserPromptSubmit/input-notifier.ts +139 -0
- package/templates/hooks/scripts/UserPromptSubmit/user-prompt-submit.ts +16 -0
- package/templates/hooks/test-hook.ts +171 -0
- package/templates/hooks/tsconfig.json +27 -0
- package/templates/hooks/utils/execution-utils.ts +176 -0
- package/templates/hooks/utils/file-utils.ts +256 -0
- package/templates/hooks/utils/hook-utils.ts +86 -0
- package/templates/hooks/utils/index.ts +42 -0
- package/templates/personality.md +19 -14
- package/templates/settings.json +37 -2
- package/dist/chunks/run-command.mjs +0 -48
- package/templates/agents/base/frontend-designer.md +0 -193
- package/templates/hooks/scripts/Notification/bash/desktop-notifier.sh +0 -63
- package/templates/hooks/scripts/Notification/powershell/desktop-notifier.ps1 +0 -67
- package/templates/hooks/scripts/PostToolUse/bash/code-formatter.sh +0 -73
- package/templates/hooks/scripts/PostToolUse/powershell/code-formatter.ps1 +0 -90
- package/templates/hooks/scripts/PreToolUse/bash/command-logger.sh +0 -38
- package/templates/hooks/scripts/PreToolUse/bash/file-protection.sh +0 -55
- package/templates/hooks/scripts/PreToolUse/powershell/command-logger.ps1 +0 -34
- package/templates/hooks/scripts/PreToolUse/powershell/file-protection.ps1 +0 -46
- package/templates/hooks/scripts/Stop/bash/session-summary.sh +0 -83
- package/templates/hooks/scripts/Stop/powershell/session-summary.ps1 +0 -125
- package/templates/skills/slack-gif-creator/LICENSE.txt +0 -202
- package/templates/skills/slack-gif-creator/SKILL.md +0 -646
- package/templates/skills/slack-gif-creator/core/color_palettes.py +0 -302
- package/templates/skills/slack-gif-creator/core/easing.py +0 -230
- package/templates/skills/slack-gif-creator/core/frame_composer.py +0 -469
- package/templates/skills/slack-gif-creator/core/gif_builder.py +0 -246
- package/templates/skills/slack-gif-creator/core/typography.py +0 -357
- package/templates/skills/slack-gif-creator/core/validators.py +0 -264
- package/templates/skills/slack-gif-creator/core/visual_effects.py +0 -494
- package/templates/skills/slack-gif-creator/requirements.txt +0 -4
- package/templates/skills/slack-gif-creator/templates/bounce.py +0 -106
- package/templates/skills/slack-gif-creator/templates/explode.py +0 -331
- package/templates/skills/slack-gif-creator/templates/fade.py +0 -329
- package/templates/skills/slack-gif-creator/templates/flip.py +0 -291
- package/templates/skills/slack-gif-creator/templates/kaleidoscope.py +0 -211
- package/templates/skills/slack-gif-creator/templates/morph.py +0 -329
- package/templates/skills/slack-gif-creator/templates/move.py +0 -293
- package/templates/skills/slack-gif-creator/templates/pulse.py +0 -268
- package/templates/skills/slack-gif-creator/templates/shake.py +0 -127
- package/templates/skills/slack-gif-creator/templates/slide.py +0 -291
- package/templates/skills/slack-gif-creator/templates/spin.py +0 -269
- package/templates/skills/slack-gif-creator/templates/wiggle.py +0 -300
- package/templates/skills/slack-gif-creator/templates/zoom.py +0 -312
- package/templates/skills/swimlane-diagram/README.md +0 -373
- package/templates/skills/swimlane-diagram/SKILL.md +0 -242
- package/templates/skills/swimlane-diagram/examples.md +0 -405
- package/templates/skills/swimlane-diagram/generators.mjs +0 -258
- package/templates/skills/swimlane-diagram/package.json +0 -126
- package/templates/skills/swimlane-diagram/reference.md +0 -368
- package/templates/skills/swimlane-diagram/swimlane-diagram.mjs +0 -215
- package/templates/skills/swimlane-diagram/swimlane-diagram.test.mjs +0 -358
- package/templates/skills/swimlane-diagram/validators.mjs +0 -291
- package/templates/skills/theme-factory/LICENSE.txt +0 -202
- package/templates/skills/theme-factory/SKILL.md +0 -59
- package/templates/skills/theme-factory/theme-showcase.pdf +0 -0
- package/templates/skills/theme-factory/themes/arctic-frost.md +0 -19
- package/templates/skills/theme-factory/themes/botanical-garden.md +0 -19
- package/templates/skills/theme-factory/themes/desert-rose.md +0 -19
- package/templates/skills/theme-factory/themes/forest-canopy.md +0 -19
- package/templates/skills/theme-factory/themes/golden-hour.md +0 -19
- package/templates/skills/theme-factory/themes/midnight-galaxy.md +0 -19
- package/templates/skills/theme-factory/themes/modern-minimalist.md +0 -19
- package/templates/skills/theme-factory/themes/ocean-depths.md +0 -19
- package/templates/skills/theme-factory/themes/sunset-boulevard.md +0 -19
- package/templates/skills/theme-factory/themes/tech-innovation.md +0 -19
- /package/templates/agents/{code//346/240/271/346/234/254/345/216/237/345/233/240/345/210/206/346/236/220/345/270/210.md" → core/root-cause-analyst.md} +0 -0
- /package/templates/agents/{code//346/212/200/346/234/257/346/226/207/346/241/243/345/267/245/347/250/213/345/270/210.md" → core/technical-writer.md} +0 -0
- /package/templates/agents/{code//346/200/247/350/203/275/345/210/206/346/236/220/344/270/223/345/256/266.md" → deployment/performance-analyst.md} +0 -0
- /package/templates/agents/{code//345/256/211/345/205/250/346/274/217/346/264/236/350/257/206/345/210/253/344/270/223/345/256/266.md" → deployment/security-engineer.md} +0 -0
- /package/templates/agents/{code//347/263/273/347/273/237/346/236/266/346/236/204/345/270/210.md" → engineering/middlend/architect.md} +0 -0
- /package/templates/agents/{code/python/345/274/200/345/217/221/344/270/223/345/256/266.md" → specialized/Python/python-expert.md} +0 -0
- /package/templates/agents/{code//350/264/250/351/207/217/350/257/204/344/274/260/345/267/245/347/250/213/345/270/210.md" → testing/quality-engineer.md} +0 -0
- /package/templates/agents/{base → universal}/panel-experts.md +0 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
/**
|
|
3
|
+
* PreToolUse Hook - File Protection
|
|
4
|
+
* 阻止对敏感文件的修改操作
|
|
5
|
+
* 跨平台 TypeScript 实现
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import * as fs from 'fs';
|
|
9
|
+
import {
|
|
10
|
+
safeJsonParse
|
|
11
|
+
} from '../../utils/hook-utils';
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* 敏感文件/目录模式列表
|
|
16
|
+
*/
|
|
17
|
+
const SENSITIVE_PATTERNS = [
|
|
18
|
+
/\.env$/,
|
|
19
|
+
/package-lock\.json$/,
|
|
20
|
+
/yarn\.lock$/,
|
|
21
|
+
/pnpm-lock\.yaml$/,
|
|
22
|
+
/[\\\/]\.git[\\\/]/,
|
|
23
|
+
/[\\\/]node_modules[\\\/]/,
|
|
24
|
+
/[\\\/]\.ssh[\\\/]/,
|
|
25
|
+
/[\\\/]\.aws[\\\/]/,
|
|
26
|
+
/[\\\/]\.config[\\\/]/,
|
|
27
|
+
/[\\\/]\.local[\\\/]/,
|
|
28
|
+
/[\\\/]\.kube[\\\/]/,
|
|
29
|
+
/[\\\/]\.docker[\\\/]/
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* 工具输入接口
|
|
34
|
+
*/
|
|
35
|
+
interface ToolInput {
|
|
36
|
+
tool_input?: {
|
|
37
|
+
file_path?: string;
|
|
38
|
+
path?: string;
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* 读取标准输入
|
|
44
|
+
*/
|
|
45
|
+
function readStdinSync(): string {
|
|
46
|
+
try {
|
|
47
|
+
return fs.readFileSync(0, 'utf-8');
|
|
48
|
+
} catch (err) {
|
|
49
|
+
return '';
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* 验证文件路径是否安全
|
|
55
|
+
*/
|
|
56
|
+
function validateFilePath(filePath: string): boolean {
|
|
57
|
+
|
|
58
|
+
for (const pattern of SENSITIVE_PATTERNS) {
|
|
59
|
+
if (pattern.test(filePath)) {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* 主执行函数
|
|
69
|
+
*/
|
|
70
|
+
export function main(inputJson?: string): number {
|
|
71
|
+
|
|
72
|
+
// 读取标准输入的 JSON 数据
|
|
73
|
+
const input = inputJson || readStdinSync();
|
|
74
|
+
|
|
75
|
+
if (!input || input.trim() === '') {
|
|
76
|
+
return 0;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// 解析 JSON
|
|
80
|
+
const toolInput = safeJsonParse<ToolInput>(input);
|
|
81
|
+
|
|
82
|
+
if (!toolInput) {
|
|
83
|
+
return 0;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// 提取文件路径
|
|
87
|
+
const filePath = toolInput.tool_input?.file_path || toolInput.tool_input?.path;
|
|
88
|
+
|
|
89
|
+
if (!filePath) {
|
|
90
|
+
return 0;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// 验证文件路径
|
|
94
|
+
if (!validateFilePath(filePath)) {
|
|
95
|
+
// 返回 2 表示阻止操作
|
|
96
|
+
return 2;
|
|
97
|
+
}
|
|
98
|
+
return 0;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// 执行主函数
|
|
102
|
+
if(require.main === module){
|
|
103
|
+
try{
|
|
104
|
+
const exitCode = main();
|
|
105
|
+
process.exit(exitCode);
|
|
106
|
+
}
|
|
107
|
+
catch(err){
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
/**
|
|
3
|
+
* PreToolUse Hook
|
|
4
|
+
* 在工具使用前触发
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import * as fs from 'fs';
|
|
8
|
+
|
|
9
|
+
// 导入 file-protection 和 command-logger 的主函数
|
|
10
|
+
import { main as executeFileProtectionHook } from './file-protection';
|
|
11
|
+
import { main as executeCommandLoggerHook } from './command-logger';
|
|
12
|
+
|
|
13
|
+
// 读取标准输入
|
|
14
|
+
function readStdinSync(): string {
|
|
15
|
+
try {
|
|
16
|
+
return fs.readFileSync(0, 'utf-8');
|
|
17
|
+
} catch {
|
|
18
|
+
return '';
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// 执行 Hook
|
|
23
|
+
try {
|
|
24
|
+
// 读取标准输入一次
|
|
25
|
+
const inputJson = readStdinSync();
|
|
26
|
+
// 1. 执行文件保护检查
|
|
27
|
+
const fileProtectionResult = executeFileProtectionHook(inputJson);
|
|
28
|
+
|
|
29
|
+
if (fileProtectionResult === 2) {
|
|
30
|
+
// 文件保护检查失败,阻止操作
|
|
31
|
+
process.exit(2);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// 2. 执行命令日志记录
|
|
35
|
+
executeCommandLoggerHook(inputJson);
|
|
36
|
+
// 所有检查通过
|
|
37
|
+
process.exit(0);
|
|
38
|
+
|
|
39
|
+
} catch (err) {
|
|
40
|
+
// 发生错误时允许操作继续
|
|
41
|
+
process.exit(0);
|
|
42
|
+
}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
/**
|
|
3
|
+
* Stop Hook - Session Summary
|
|
4
|
+
* 当 Claude Code 停止工作时记录会话摘要并发送通知
|
|
5
|
+
* 跨平台 TypeScript 实现
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import * as fs from 'fs';
|
|
9
|
+
import * as path from 'path';
|
|
10
|
+
import * as os from 'os';
|
|
11
|
+
import { execSync } from 'child_process';
|
|
12
|
+
import {
|
|
13
|
+
commandExists,
|
|
14
|
+
getHooksDirectory,
|
|
15
|
+
getProjectDirectory
|
|
16
|
+
} from '../../utils/hook-utils';
|
|
17
|
+
|
|
18
|
+
// 类型定义
|
|
19
|
+
type Platform = 'win32' | 'darwin' | 'linux' | 'aix' | 'freebsd' | 'openbsd' | 'sunos';
|
|
20
|
+
// 检测操作系统
|
|
21
|
+
const platform = os.platform() as Platform;
|
|
22
|
+
// 定义控制台输出颜色常量
|
|
23
|
+
const GREEN = '\x1b[32m';
|
|
24
|
+
const WHITE = '\x1b[37m';
|
|
25
|
+
const RESET = '\x1b[0m';
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* 播放系统完成声音
|
|
30
|
+
*/
|
|
31
|
+
function playCompletionSound(): void {
|
|
32
|
+
try {
|
|
33
|
+
switch (platform) {
|
|
34
|
+
case 'win32':
|
|
35
|
+
try{
|
|
36
|
+
// Windows: 播放系统完成声音
|
|
37
|
+
execSync('powershell -Command "[System.Media.SystemSounds]::Asterisk.Play()"', {
|
|
38
|
+
stdio: 'ignore',
|
|
39
|
+
timeout: 2000
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
catch(err){
|
|
43
|
+
}
|
|
44
|
+
break;
|
|
45
|
+
|
|
46
|
+
case 'darwin':
|
|
47
|
+
try{
|
|
48
|
+
// macOS: 播放系统完成声音
|
|
49
|
+
if (commandExists('afplay')) {
|
|
50
|
+
execSync('afplay /System/Library/Sounds/Glass.aiff', {
|
|
51
|
+
stdio: 'ignore',
|
|
52
|
+
timeout: 2000
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
catch(err){
|
|
57
|
+
}
|
|
58
|
+
break;
|
|
59
|
+
|
|
60
|
+
case 'linux':
|
|
61
|
+
try{
|
|
62
|
+
// Linux: 播放系统完成声音
|
|
63
|
+
if (commandExists('paplay')) {
|
|
64
|
+
execSync('paplay /usr/share/sounds/freedesktop/stereo/complete.oga', {
|
|
65
|
+
stdio: 'ignore',
|
|
66
|
+
timeout: 2000
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
catch(err){
|
|
71
|
+
}
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
} catch (err) {
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* 发送会话结束通知
|
|
80
|
+
*/
|
|
81
|
+
function sendStopNotification(): void {
|
|
82
|
+
const title = '智能软件星工厂';
|
|
83
|
+
const message = '任务已完成';
|
|
84
|
+
|
|
85
|
+
try {
|
|
86
|
+
switch (platform) {
|
|
87
|
+
case 'win32':
|
|
88
|
+
// Windows: 控制台输出 + 系统声音
|
|
89
|
+
playCompletionSound();
|
|
90
|
+
break;
|
|
91
|
+
|
|
92
|
+
case 'darwin':
|
|
93
|
+
// macOS: 使用 osascript
|
|
94
|
+
if (commandExists('osascript')) {
|
|
95
|
+
try {
|
|
96
|
+
const script = `display notification "${message}" with title "${title}"`;
|
|
97
|
+
execSync(`osascript -e '${script}'`, {
|
|
98
|
+
stdio: 'ignore',
|
|
99
|
+
timeout: 2000
|
|
100
|
+
});
|
|
101
|
+
} catch (err) {
|
|
102
|
+
// 忽略错误
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
playCompletionSound();
|
|
106
|
+
break;
|
|
107
|
+
|
|
108
|
+
case 'linux':
|
|
109
|
+
// Linux: 使用 notify-send
|
|
110
|
+
if (commandExists('notify-send')) {
|
|
111
|
+
try {
|
|
112
|
+
execSync(`notify-send "${title}" "${message}"`, {
|
|
113
|
+
stdio: 'ignore',
|
|
114
|
+
timeout: 2000
|
|
115
|
+
});
|
|
116
|
+
} catch (err) {
|
|
117
|
+
// 忽略错误
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
playCompletionSound();
|
|
121
|
+
break;
|
|
122
|
+
|
|
123
|
+
default:
|
|
124
|
+
// 未知系统
|
|
125
|
+
break;
|
|
126
|
+
}
|
|
127
|
+
} catch (err) {
|
|
128
|
+
// 忽略错误
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* 主执行函数
|
|
134
|
+
*/
|
|
135
|
+
export function main(): void {
|
|
136
|
+
// 发送完成通知
|
|
137
|
+
sendStopNotification();
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// 执行主函数
|
|
141
|
+
if(require.main === module){
|
|
142
|
+
try{
|
|
143
|
+
main();
|
|
144
|
+
process.exit(0);
|
|
145
|
+
}
|
|
146
|
+
catch(err){
|
|
147
|
+
// 即使失败也返回成功状态码,避免影响主流程
|
|
148
|
+
process.exit(0);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
/**
|
|
3
|
+
* Stop Hook
|
|
4
|
+
* 当会话停止时触发
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import {main as executeSessionSummaryHook} from './session-summary';
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
try{
|
|
11
|
+
executeSessionSummaryHook();
|
|
12
|
+
process.exit(0);
|
|
13
|
+
}
|
|
14
|
+
catch(err){
|
|
15
|
+
// 即使失败也返回成功状态码,避免影响主流程
|
|
16
|
+
process.exit(0);
|
|
17
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
/**
|
|
3
|
+
* UserPromptSubmit Hook - Input Notifier
|
|
4
|
+
* 当用户提交输入时发送通知
|
|
5
|
+
* 跨平台 TypeScript 实现
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import * as os from 'os';
|
|
9
|
+
import { execSync } from 'child_process';
|
|
10
|
+
import {
|
|
11
|
+
commandExists
|
|
12
|
+
} from '../../utils/hook-utils';
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
// 类型定义
|
|
16
|
+
type Platform = 'win32' | 'darwin' | 'linux' | 'aix' | 'freebsd' | 'openbsd' | 'sunos';
|
|
17
|
+
|
|
18
|
+
// 检测操作系统
|
|
19
|
+
const platform = os.platform() as Platform;
|
|
20
|
+
|
|
21
|
+
// 播放系统声音
|
|
22
|
+
function playSystemSound(): void {
|
|
23
|
+
try{
|
|
24
|
+
switch (platform) {
|
|
25
|
+
case 'win32':
|
|
26
|
+
try{
|
|
27
|
+
// Windows: 播放系统蜂鸣声
|
|
28
|
+
execSync('powershell -Command "[System.Media.SystemSounds]::Beep.Play()"', {
|
|
29
|
+
stdio: 'ignore',
|
|
30
|
+
timeout: 2000
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
catch(err){
|
|
34
|
+
}
|
|
35
|
+
break;
|
|
36
|
+
|
|
37
|
+
case 'darwin':
|
|
38
|
+
try{
|
|
39
|
+
// macOS: 播放系统声音
|
|
40
|
+
if (commandExists('afplay')) {
|
|
41
|
+
execSync('afplay /System/Library/Sounds/Ping.aiff', {
|
|
42
|
+
stdio: 'ignore',
|
|
43
|
+
timeout: 2000
|
|
44
|
+
});
|
|
45
|
+
}}
|
|
46
|
+
catch(err){
|
|
47
|
+
}
|
|
48
|
+
break;
|
|
49
|
+
|
|
50
|
+
case 'linux':
|
|
51
|
+
try{
|
|
52
|
+
// Linux: 播放系统声音
|
|
53
|
+
if (commandExists('paplay')) {
|
|
54
|
+
execSync('paplay /usr/share/sounds/freedesktop/stereo/bell.oga', {
|
|
55
|
+
stdio: 'ignore',
|
|
56
|
+
timeout: 2000
|
|
57
|
+
});
|
|
58
|
+
}}
|
|
59
|
+
catch(err){
|
|
60
|
+
}
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
catch(err){
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// 发送桌面通知
|
|
69
|
+
function sendDesktopNotification(title: string, message: string): void {
|
|
70
|
+
|
|
71
|
+
try {
|
|
72
|
+
switch (platform) {
|
|
73
|
+
case 'win32':
|
|
74
|
+
// Windows: 使用控制台输出 + 系统声音
|
|
75
|
+
playSystemSound();
|
|
76
|
+
break;
|
|
77
|
+
|
|
78
|
+
case 'darwin':
|
|
79
|
+
// macOS: 使用 osascript
|
|
80
|
+
|
|
81
|
+
if (commandExists('osascript')) {
|
|
82
|
+
try {
|
|
83
|
+
const script = `display notification "${message}" with title "${title}"`;
|
|
84
|
+
execSync(`osascript -e '${script}'`, {
|
|
85
|
+
stdio: 'ignore',
|
|
86
|
+
timeout: 2000
|
|
87
|
+
});
|
|
88
|
+
} catch (err) {
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
playSystemSound();
|
|
93
|
+
break;
|
|
94
|
+
|
|
95
|
+
case 'linux':
|
|
96
|
+
// Linux: 使用 notify-send
|
|
97
|
+
|
|
98
|
+
if (commandExists('notify-send')) {
|
|
99
|
+
try {
|
|
100
|
+
execSync(`notify-send "${title}" "${message}"`, {
|
|
101
|
+
stdio: 'ignore',
|
|
102
|
+
timeout: 2000
|
|
103
|
+
});
|
|
104
|
+
} catch (err) {
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
playSystemSound();
|
|
109
|
+
break;
|
|
110
|
+
|
|
111
|
+
default:
|
|
112
|
+
// 未知系统
|
|
113
|
+
break;
|
|
114
|
+
}
|
|
115
|
+
} catch (err) {
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* 主执行函数
|
|
121
|
+
*/
|
|
122
|
+
export function main(): void {
|
|
123
|
+
const title = "智能软件星工厂";
|
|
124
|
+
const message = "开始执行任务";
|
|
125
|
+
// 发送输入提示
|
|
126
|
+
sendDesktopNotification(title, message);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// 执行主函数(仅当直接运行时)
|
|
130
|
+
if(require.main == module){
|
|
131
|
+
try{
|
|
132
|
+
main();
|
|
133
|
+
process.exit(0);
|
|
134
|
+
}
|
|
135
|
+
catch(err){
|
|
136
|
+
// 即使失败也返回成功状态码,避免影响主流程
|
|
137
|
+
process.exit(0);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
/**
|
|
3
|
+
* UserPromptSubmit Hook
|
|
4
|
+
* 当用户提交提示时触发
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// 直接导入并执行 input-notifier 的主函数
|
|
8
|
+
import { main as executeInputNotifierHook} from './input-notifier';
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
try {
|
|
12
|
+
executeInputNotifierHook();
|
|
13
|
+
process.exit(0);
|
|
14
|
+
} catch (err) {
|
|
15
|
+
process.exit(1);
|
|
16
|
+
}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
/**
|
|
3
|
+
* Hook 测试脚本 (TypeScript)
|
|
4
|
+
* 用于验证 hook 系统是否正常工作
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import * as fs from 'fs';
|
|
8
|
+
import * as path from 'path';
|
|
9
|
+
import * as os from 'os';
|
|
10
|
+
import { execSync } from 'child_process';
|
|
11
|
+
|
|
12
|
+
// 类型定义
|
|
13
|
+
type Platform = 'win32' | 'darwin' | 'linux' | 'aix' | 'freebsd' | 'openbsd' | 'sunos';
|
|
14
|
+
type HookType = 'UserPromptSubmit' | 'PreToolUse' | 'PostToolUse' | 'Notification' | 'Stop';
|
|
15
|
+
|
|
16
|
+
interface TestResult {
|
|
17
|
+
name: string;
|
|
18
|
+
passed: boolean;
|
|
19
|
+
message?: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const platform = os.platform() as Platform;
|
|
23
|
+
const homeDir = os.homedir();
|
|
24
|
+
const hooksDir = path.join(homeDir, '.claude', 'hooks');
|
|
25
|
+
const hook_types = ['UserPromptSubmit', 'PreToolUse', 'PostToolUse',
|
|
26
|
+
'Notification', 'Stop'];
|
|
27
|
+
const execution_scr_name = ['input-notifier', 'file-protection',
|
|
28
|
+
'code-formatter', 'desktop-notifier', 'session-summary'];
|
|
29
|
+
const executionScriptMap = new Map<String, any>();
|
|
30
|
+
|
|
31
|
+
// 确保数组长度一致
|
|
32
|
+
if (hook_types.length === execution_scr_name.length) {
|
|
33
|
+
for (let i = 0; i < hook_types.length; i++) {
|
|
34
|
+
executionScriptMap.set(hook_types[i], execution_scr_name[i]);
|
|
35
|
+
}
|
|
36
|
+
} else {
|
|
37
|
+
throw new Error('Keys and values arrays must have the same length');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
// 测试 1: 检查 Node.js 版本
|
|
42
|
+
function testNodeVersion(): TestResult {
|
|
43
|
+
try {
|
|
44
|
+
const version = process.version;
|
|
45
|
+
return { name: 'nodeVersion', passed: true };
|
|
46
|
+
} catch (err) {
|
|
47
|
+
const message = `失败: ${(err as Error).message}`;
|
|
48
|
+
return { name: 'nodeVersion', passed: false, message };
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// 测试 2: 检查目录结构
|
|
53
|
+
function testDirectoryStructure(): TestResult {
|
|
54
|
+
const requiredDirs = [
|
|
55
|
+
hooksDir,
|
|
56
|
+
path.join(hooksDir, 'scripts'),
|
|
57
|
+
path.join(hooksDir, 'logs')
|
|
58
|
+
];
|
|
59
|
+
|
|
60
|
+
let allExist = true;
|
|
61
|
+
requiredDirs.forEach(dir => {
|
|
62
|
+
if (!fs.existsSync(dir)) {
|
|
63
|
+
allExist = false;
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
return { name: 'directoryStructure', passed: allExist };
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// 测试 3: 检查包装脚本
|
|
71
|
+
function testWrapperScript(): TestResult {
|
|
72
|
+
const tsWrapperPath = path.join(hooksDir, 'scripts', 'hook-wrapper.ts');
|
|
73
|
+
|
|
74
|
+
if (fs.existsSync(tsWrapperPath)) {
|
|
75
|
+
return { name: 'wrapperScript', passed: true };
|
|
76
|
+
} else {
|
|
77
|
+
return { name: 'wrapperScript', passed: false };
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// 测试 4: 执行测试 hook
|
|
82
|
+
function testHookExecution(): TestResult {
|
|
83
|
+
let testHookPath: string;
|
|
84
|
+
testHookPath = path.join(hooksDir, 'scripts', 'Stop',
|
|
85
|
+
'stop.ts');
|
|
86
|
+
|
|
87
|
+
if (!fs.existsSync(testHookPath)) {
|
|
88
|
+
return { name: 'hookExecution', passed: false };
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
try {
|
|
92
|
+
execSync(`tsx ${testHookPath}`, {
|
|
93
|
+
cwd: path.dirname(testHookPath),
|
|
94
|
+
timeout: 5000
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
return { name: 'hookExecution', passed: true };
|
|
98
|
+
} catch (err) {
|
|
99
|
+
const message = `执行失败: ${(err as Error).message}`;
|
|
100
|
+
return { name: 'hookExecution', passed: false, message };
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// 测试 5: 检查平台特定脚本
|
|
105
|
+
function testPlatformScripts(): TestResult {
|
|
106
|
+
const hookTypes: HookType[] = ['UserPromptSubmit', 'PreToolUse', 'PostToolUse', 'Notification', 'Stop'];
|
|
107
|
+
let foundScripts = 0;
|
|
108
|
+
|
|
109
|
+
hookTypes.forEach(type => {
|
|
110
|
+
let scriptPath: string;
|
|
111
|
+
|
|
112
|
+
if (platform === 'win32') {
|
|
113
|
+
scriptPath = path.join(hooksDir, 'scripts', type, 'powershell', `${executionScriptMap.get(type)}.ps1`);
|
|
114
|
+
} else {
|
|
115
|
+
scriptPath = path.join(hooksDir, 'scripts', type, 'bash', `${executionScriptMap.get(type)}.sh`);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (fs.existsSync(scriptPath)) {
|
|
119
|
+
foundScripts++;
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
return { name: 'platformScripts', passed: foundScripts > 0 };
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// 测试 6: 检查配置文件
|
|
127
|
+
function testConfigFile(): TestResult {
|
|
128
|
+
const configPath = path.join(hooksDir, 'claude-code-hooks.json');
|
|
129
|
+
|
|
130
|
+
if (fs.existsSync(configPath)) {
|
|
131
|
+
try {
|
|
132
|
+
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
133
|
+
const hookCount = Object.keys(config.hooks || {}).length;
|
|
134
|
+
return { name: 'configFile', passed: true };
|
|
135
|
+
} catch (err) {
|
|
136
|
+
const message = `配置文件解析失败: ${(err as Error).message}`;
|
|
137
|
+
return { name: 'configFile', passed: false, message };
|
|
138
|
+
}
|
|
139
|
+
} else {
|
|
140
|
+
return { name: 'configFile', passed: false };
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// 测试 7: 检查 TypeScript 配置
|
|
145
|
+
function testTypeScriptSetup(): TestResult {
|
|
146
|
+
const scriptsDir = path.join(hooksDir, 'scripts');
|
|
147
|
+
const tsconfigPath = path.join(scriptsDir, 'tsconfig.json');
|
|
148
|
+
|
|
149
|
+
let passed = true;
|
|
150
|
+
|
|
151
|
+
if (!fs.existsSync(tsconfigPath)) {
|
|
152
|
+
passed = false;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return { name: 'typeScriptSetup', passed };
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// 运行所有测试
|
|
159
|
+
function runAllTests(): void {
|
|
160
|
+
const results: TestResult[] = [
|
|
161
|
+
testNodeVersion(),
|
|
162
|
+
testDirectoryStructure(),
|
|
163
|
+
testHookExecution(),
|
|
164
|
+
];
|
|
165
|
+
|
|
166
|
+
const passed = results.filter(r => r.passed).length;
|
|
167
|
+
const total = results.length;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// 执行测试
|
|
171
|
+
runAllTests();
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "commonjs",
|
|
5
|
+
"lib": ["ES2020"],
|
|
6
|
+
"outDir": "./",
|
|
7
|
+
"rootDir": "./",
|
|
8
|
+
"strict": true,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"skipLibCheck": true,
|
|
11
|
+
"forceConsistentCasingInFileNames": true,
|
|
12
|
+
"resolveJsonModule": true,
|
|
13
|
+
"declaration": true,
|
|
14
|
+
"declarationMap": true,
|
|
15
|
+
"sourceMap": true,
|
|
16
|
+
"moduleResolution": "bundler",
|
|
17
|
+
"types": ["node"],
|
|
18
|
+
"ignoreDeprecations": "5.0"
|
|
19
|
+
},
|
|
20
|
+
"include": [
|
|
21
|
+
"*.ts"
|
|
22
|
+
],
|
|
23
|
+
"exclude": [
|
|
24
|
+
"node_modules",
|
|
25
|
+
"**/*.js"
|
|
26
|
+
]
|
|
27
|
+
}
|