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,176 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
/**
|
|
3
|
+
* 执行状态管理工具
|
|
4
|
+
* 提供任务执行状态跟踪、锁文件管理等功能
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import * as fs from 'fs';
|
|
8
|
+
import * as path from 'path';
|
|
9
|
+
import { getHooksDirectory } from './hook-utils';
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* 执行状态接口
|
|
14
|
+
*/
|
|
15
|
+
export interface ExecutionStatus {
|
|
16
|
+
currentTask?: string;
|
|
17
|
+
status: string;
|
|
18
|
+
progress?: string;
|
|
19
|
+
error?: string;
|
|
20
|
+
message?: string;
|
|
21
|
+
totalTasks?: number;
|
|
22
|
+
completed?: number;
|
|
23
|
+
failed?: number;
|
|
24
|
+
successRate?: string;
|
|
25
|
+
timestamp?: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* 锁文件数据接口
|
|
30
|
+
*/
|
|
31
|
+
export interface LockFileData {
|
|
32
|
+
started: string;
|
|
33
|
+
pid: number;
|
|
34
|
+
taskFile?: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* 获取执行状态文件路径
|
|
39
|
+
*/
|
|
40
|
+
function getStatusFilePath(): string {
|
|
41
|
+
const hooksDir = getHooksDirectory();
|
|
42
|
+
return path.join(hooksDir, 'execution-status.json');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* 获取锁文件路径
|
|
47
|
+
*/
|
|
48
|
+
function getLockFilePath(): string {
|
|
49
|
+
const hooksDir = getHooksDirectory();
|
|
50
|
+
return path.join(hooksDir, 'execution-lock');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* 创建执行锁
|
|
55
|
+
*/
|
|
56
|
+
export async function createExecutionLock(taskFile?: string): Promise<boolean> {
|
|
57
|
+
try {
|
|
58
|
+
const lockFile = getLockFilePath();
|
|
59
|
+
const lockDir = path.dirname(lockFile);
|
|
60
|
+
|
|
61
|
+
await fs.promises.mkdir(lockDir, { recursive: true });
|
|
62
|
+
|
|
63
|
+
const lockData: LockFileData = {
|
|
64
|
+
started: new Date().toISOString(),
|
|
65
|
+
pid: process.pid,
|
|
66
|
+
taskFile
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
await fs.promises.writeFile(lockFile, JSON.stringify(lockData, null, 2));
|
|
70
|
+
return true;
|
|
71
|
+
} catch (error) {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* 移除执行锁
|
|
78
|
+
*/
|
|
79
|
+
export async function removeExecutionLock(): Promise<boolean> {
|
|
80
|
+
try {
|
|
81
|
+
const lockFile = getLockFilePath();
|
|
82
|
+
await fs.promises.unlink(lockFile);
|
|
83
|
+
return true;
|
|
84
|
+
} catch (error) {
|
|
85
|
+
// 锁文件不存在时忽略错误
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* 检查是否存在执行锁
|
|
92
|
+
*/
|
|
93
|
+
export async function hasExecutionLock(): Promise<boolean> {
|
|
94
|
+
try {
|
|
95
|
+
const lockFile = getLockFilePath();
|
|
96
|
+
await fs.promises.access(lockFile);
|
|
97
|
+
return true;
|
|
98
|
+
} catch {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* 读取执行锁信息
|
|
105
|
+
*/
|
|
106
|
+
export async function readExecutionLock(): Promise<LockFileData | null> {
|
|
107
|
+
try {
|
|
108
|
+
const lockFile = getLockFilePath();
|
|
109
|
+
const content = await fs.promises.readFile(lockFile, 'utf-8');
|
|
110
|
+
return JSON.parse(content) as LockFileData;
|
|
111
|
+
} catch (error) {
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* 保存执行状态
|
|
118
|
+
*/
|
|
119
|
+
export async function saveExecutionStatus(status: ExecutionStatus): Promise<boolean> {
|
|
120
|
+
try {
|
|
121
|
+
const statusFile = getStatusFilePath();
|
|
122
|
+
const statusDir = path.dirname(statusFile);
|
|
123
|
+
|
|
124
|
+
await fs.promises.mkdir(statusDir, { recursive: true });
|
|
125
|
+
|
|
126
|
+
const statusData: ExecutionStatus = {
|
|
127
|
+
...status,
|
|
128
|
+
timestamp: new Date().toISOString()
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
await fs.promises.writeFile(statusFile, JSON.stringify(statusData, null, 2));
|
|
132
|
+
return true;
|
|
133
|
+
} catch (error) {
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* 读取执行状态
|
|
140
|
+
*/
|
|
141
|
+
export async function readExecutionStatus(): Promise<ExecutionStatus | null> {
|
|
142
|
+
try {
|
|
143
|
+
const statusFile = getStatusFilePath();
|
|
144
|
+
const content = await fs.promises.readFile(statusFile, 'utf-8');
|
|
145
|
+
return JSON.parse(content) as ExecutionStatus;
|
|
146
|
+
} catch (error) {
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* 清理执行状态
|
|
153
|
+
*/
|
|
154
|
+
export async function clearExecutionStatus(): Promise<boolean> {
|
|
155
|
+
try {
|
|
156
|
+
const statusFile = getStatusFilePath();
|
|
157
|
+
await fs.promises.unlink(statusFile);
|
|
158
|
+
return true;
|
|
159
|
+
} catch (error) {
|
|
160
|
+
return true;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* 格式化执行进度
|
|
166
|
+
*/
|
|
167
|
+
export function formatProgress(completed: number, total: number): string {
|
|
168
|
+
return `${completed}/${total} (${((completed / total) * 100).toFixed(1)}%)`;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* 计算成功率
|
|
173
|
+
*/
|
|
174
|
+
export function calculateSuccessRate(completed: number, total: number): string {
|
|
175
|
+
return ((completed / total) * 100).toFixed(1);
|
|
176
|
+
}
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
/**
|
|
3
|
+
* 文件操作工具模块
|
|
4
|
+
* 提供统一的文件读取、解析、glob匹配等功能
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import * as fs from 'fs';
|
|
8
|
+
import * as path from 'path';
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* 任务接口定义
|
|
13
|
+
*/
|
|
14
|
+
export interface Task {
|
|
15
|
+
id: string;
|
|
16
|
+
title: string;
|
|
17
|
+
description: string;
|
|
18
|
+
completed: boolean;
|
|
19
|
+
lineNumber: number;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* 安全读取文件
|
|
24
|
+
*/
|
|
25
|
+
export async function safeReadFile(filePath: string): Promise<string | null> {
|
|
26
|
+
try {
|
|
27
|
+
return await fs.promises.readFile(filePath, 'utf-8');
|
|
28
|
+
} catch (error) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* 安全写入文件
|
|
35
|
+
*/
|
|
36
|
+
export async function safeWriteFile(filePath: string, content: string): Promise<boolean> {
|
|
37
|
+
try {
|
|
38
|
+
await fs.promises.writeFile(filePath, content, 'utf-8');
|
|
39
|
+
return true;
|
|
40
|
+
} catch (error) {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* 简单的glob模式匹配实现
|
|
47
|
+
*/
|
|
48
|
+
export async function glob(pattern: string): Promise<string[]> {
|
|
49
|
+
const baseDir = process.cwd();
|
|
50
|
+
const parts = pattern.split('/');
|
|
51
|
+
const results: string[] = [];
|
|
52
|
+
|
|
53
|
+
try {
|
|
54
|
+
// 处理包含通配符的路径
|
|
55
|
+
if (pattern.includes('*')) {
|
|
56
|
+
const dirPath = parts.slice(0, -1).join('/');
|
|
57
|
+
const fileName = parts[parts.length - 1];
|
|
58
|
+
|
|
59
|
+
// 查找包含通配符的目录部分
|
|
60
|
+
const wildcardIndex = parts.findIndex(part => part.includes('*'));
|
|
61
|
+
if (wildcardIndex !== -1) {
|
|
62
|
+
const searchDir = path.join(baseDir, parts.slice(0, wildcardIndex).join('/'));
|
|
63
|
+
const remainingParts = parts.slice(wildcardIndex);
|
|
64
|
+
|
|
65
|
+
await globRecursive(searchDir, remainingParts, results, baseDir);
|
|
66
|
+
}
|
|
67
|
+
} else {
|
|
68
|
+
// 直接检查文件是否存在
|
|
69
|
+
const fullPath = path.join(baseDir, pattern);
|
|
70
|
+
try {
|
|
71
|
+
await fs.promises.access(fullPath);
|
|
72
|
+
results.push(pattern);
|
|
73
|
+
} catch {
|
|
74
|
+
// 文件不存在
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
} catch (error) {
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return results;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* 递归glob匹配
|
|
85
|
+
*/
|
|
86
|
+
async function globRecursive(
|
|
87
|
+
currentDir: string,
|
|
88
|
+
remainingParts: string[],
|
|
89
|
+
results: string[],
|
|
90
|
+
baseDir: string
|
|
91
|
+
): Promise<void> {
|
|
92
|
+
if (remainingParts.length === 0) return;
|
|
93
|
+
|
|
94
|
+
const currentPart = remainingParts[0];
|
|
95
|
+
const nextParts = remainingParts.slice(1);
|
|
96
|
+
|
|
97
|
+
try {
|
|
98
|
+
const entries = await fs.promises.readdir(currentDir, { withFileTypes: true });
|
|
99
|
+
|
|
100
|
+
for (const entry of entries) {
|
|
101
|
+
if (currentPart === '*' && entry.isDirectory()) {
|
|
102
|
+
// 通配符匹配所有目录
|
|
103
|
+
const nextDir = path.join(currentDir, entry.name);
|
|
104
|
+
|
|
105
|
+
if (nextParts.length === 0) {
|
|
106
|
+
// 最后一个部分
|
|
107
|
+
results.push(path.relative(baseDir, nextDir));
|
|
108
|
+
} else if (nextParts.length === 1 && !nextParts[0].includes('*')) {
|
|
109
|
+
// 下一个是具体文件名
|
|
110
|
+
const targetFile = path.join(nextDir, nextParts[0]);
|
|
111
|
+
try {
|
|
112
|
+
await fs.promises.access(targetFile);
|
|
113
|
+
results.push(path.relative(baseDir, targetFile));
|
|
114
|
+
} catch {
|
|
115
|
+
// 文件不存在
|
|
116
|
+
}
|
|
117
|
+
} else {
|
|
118
|
+
// 继续递归
|
|
119
|
+
await globRecursive(nextDir, nextParts, results, baseDir);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
} catch (error) {
|
|
124
|
+
// 目录不存在或无权限
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* 查找tasks.md文件
|
|
130
|
+
*/
|
|
131
|
+
export async function findTasksFile(): Promise<string | null> {
|
|
132
|
+
const searchPaths = [
|
|
133
|
+
'.claude/specs/*/tasks.md',
|
|
134
|
+
'.qwen/specs/*/tasks.md',
|
|
135
|
+
'.kiro/specs/*/tasks.md'
|
|
136
|
+
];
|
|
137
|
+
|
|
138
|
+
for (const pattern of searchPaths) {
|
|
139
|
+
const files = await glob(pattern);
|
|
140
|
+
if (files.length > 0) {
|
|
141
|
+
return files[0];
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* 解析tasks.md文件
|
|
150
|
+
*/
|
|
151
|
+
export async function parseTasksFile(filePath: string): Promise<Task[]> {
|
|
152
|
+
const content = await safeReadFile(filePath);
|
|
153
|
+
if (!content) return [];
|
|
154
|
+
|
|
155
|
+
const tasks: Task[] = [];
|
|
156
|
+
const lines = content.split('\n');
|
|
157
|
+
|
|
158
|
+
for (let i = 0; i < lines.length; i++) {
|
|
159
|
+
const line = lines[i];
|
|
160
|
+
const taskMatch = line.match(/- \[( |x)\] \*\*Task ([\d.]+):\*\*(.+)$/);
|
|
161
|
+
|
|
162
|
+
if (taskMatch) {
|
|
163
|
+
const completed = taskMatch[1] === 'x';
|
|
164
|
+
const taskId = taskMatch[2];
|
|
165
|
+
const taskTitle = taskMatch[3].trim();
|
|
166
|
+
const description: string[] = [];
|
|
167
|
+
|
|
168
|
+
// 读取任务描述(缩进行)
|
|
169
|
+
let j = i + 1;
|
|
170
|
+
while (j < lines.length && lines[j].startsWith(' ')) {
|
|
171
|
+
description.push(lines[j].trim());
|
|
172
|
+
j++;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
tasks.push({
|
|
176
|
+
id: taskId,
|
|
177
|
+
title: taskTitle,
|
|
178
|
+
description: description.join(' '),
|
|
179
|
+
completed: completed,
|
|
180
|
+
lineNumber: i
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// removed log('INFO', `解析到 ${tasks.length} 个任务`, HOOK_NAME);
|
|
186
|
+
return tasks;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* 标记任务为完成状态
|
|
191
|
+
*/
|
|
192
|
+
export async function markTaskCompleted(filePath: string, taskId: string): Promise<boolean> {
|
|
193
|
+
const content = await safeReadFile(filePath);
|
|
194
|
+
if (!content) return false;
|
|
195
|
+
|
|
196
|
+
const lines = content.split('\n');
|
|
197
|
+
const taskLinePattern = new RegExp(`- \\[ \\] \\*\\*Task ${taskId.replace(/\./g, '\\.')}:\\*\\*`);
|
|
198
|
+
|
|
199
|
+
let updated = false;
|
|
200
|
+
for (let i = 0; i < lines.length; i++) {
|
|
201
|
+
if (taskLinePattern.test(lines[i])) {
|
|
202
|
+
lines[i] = lines[i].replace('- [ ]', '- [x]');
|
|
203
|
+
updated = true;
|
|
204
|
+
break;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
if (updated) {
|
|
209
|
+
const success = await safeWriteFile(filePath, lines.join('\n'));
|
|
210
|
+
if (success) {
|
|
211
|
+
}
|
|
212
|
+
return success;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
return false;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* 重置所有任务为未完成状态
|
|
220
|
+
*/
|
|
221
|
+
export async function resetAllTasks(filePath: string): Promise<boolean> {
|
|
222
|
+
const content = await safeReadFile(filePath);
|
|
223
|
+
if (!content) return false;
|
|
224
|
+
|
|
225
|
+
const updatedContent = content.replace(/- \[x\] \*\*Task/g, '- [ ] **Task');
|
|
226
|
+
const success = await safeWriteFile(filePath, updatedContent);
|
|
227
|
+
|
|
228
|
+
if (success) {
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
return success;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* 确保目录存在
|
|
236
|
+
*/
|
|
237
|
+
export async function ensureDir(dirPath: string): Promise<boolean> {
|
|
238
|
+
try {
|
|
239
|
+
await fs.promises.mkdir(dirPath, { recursive: true });
|
|
240
|
+
return true;
|
|
241
|
+
} catch (error) {
|
|
242
|
+
return false;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* 检查文件是否存在
|
|
248
|
+
*/
|
|
249
|
+
export async function fileExists(filePath: string): Promise<boolean> {
|
|
250
|
+
try {
|
|
251
|
+
await fs.promises.access(filePath);
|
|
252
|
+
return true;
|
|
253
|
+
} catch {
|
|
254
|
+
return false;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
/**
|
|
3
|
+
* UserPromptSubmit Hook - Input Notifier
|
|
4
|
+
* 当用户提交输入时发送通知
|
|
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
|
+
|
|
13
|
+
// 类型定义
|
|
14
|
+
type Platform = 'win32' | 'darwin' | 'linux' | 'aix' | 'freebsd' | 'openbsd' | 'sunos';
|
|
15
|
+
|
|
16
|
+
// 检测操作系统
|
|
17
|
+
const platform = os.platform() as Platform;
|
|
18
|
+
|
|
19
|
+
// 获取 hooks 目录路径
|
|
20
|
+
function getHooksDirectory(): string {
|
|
21
|
+
const homeDir = os.homedir();
|
|
22
|
+
return path.join(homeDir, '.claude', 'hooks');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// 获取项目目录路径
|
|
26
|
+
function getProjectDirectory(): string {
|
|
27
|
+
if (process.env.CLAUDE_PROJECT_DIR) {
|
|
28
|
+
return process.env.CLAUDE_PROJECT_DIR;
|
|
29
|
+
} else {
|
|
30
|
+
return process.cwd();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
// 检查命令是否存在
|
|
37
|
+
function commandExists(command: string): boolean {
|
|
38
|
+
try {
|
|
39
|
+
if (platform === 'win32') {
|
|
40
|
+
execSync(`where ${command}`, { stdio: 'ignore' });
|
|
41
|
+
} else {
|
|
42
|
+
execSync(`command -v ${command}`, { stdio: 'ignore' });
|
|
43
|
+
}
|
|
44
|
+
return true;
|
|
45
|
+
} catch {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// 安全的JSON解析
|
|
51
|
+
function safeJsonParse<T = any>(jsonInput: string): T | null {
|
|
52
|
+
try {
|
|
53
|
+
return JSON.parse(jsonInput) as T;
|
|
54
|
+
} catch (err) {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// 显示系统信息(用于测试)
|
|
60
|
+
function showSystemInfo(): void {
|
|
61
|
+
// System info display removed
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// 主执行函数
|
|
65
|
+
function main(): void {
|
|
66
|
+
try {
|
|
67
|
+
showSystemInfo();
|
|
68
|
+
} catch (err) {
|
|
69
|
+
// 即使失败也返回成功状态码,避免影响主流程
|
|
70
|
+
process.exit(0);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// 导出函数供其他模块使用
|
|
75
|
+
export {
|
|
76
|
+
getHooksDirectory,
|
|
77
|
+
getProjectDirectory,
|
|
78
|
+
commandExists,
|
|
79
|
+
safeJsonParse,
|
|
80
|
+
showSystemInfo
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
// 执行主函数(仅当直接运行时)
|
|
84
|
+
if (require.main === module) {
|
|
85
|
+
main();
|
|
86
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
/**
|
|
3
|
+
* Hooks工具统一导出
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// 导出hook-utils
|
|
7
|
+
export {
|
|
8
|
+
getHooksDirectory,
|
|
9
|
+
getProjectDirectory,
|
|
10
|
+
commandExists,
|
|
11
|
+
safeJsonParse,
|
|
12
|
+
showSystemInfo
|
|
13
|
+
} from './hook-utils';
|
|
14
|
+
|
|
15
|
+
// 导出file-utils
|
|
16
|
+
export {
|
|
17
|
+
Task,
|
|
18
|
+
safeReadFile,
|
|
19
|
+
safeWriteFile,
|
|
20
|
+
glob,
|
|
21
|
+
findTasksFile,
|
|
22
|
+
parseTasksFile,
|
|
23
|
+
markTaskCompleted,
|
|
24
|
+
resetAllTasks,
|
|
25
|
+
ensureDir,
|
|
26
|
+
fileExists
|
|
27
|
+
} from './file-utils';
|
|
28
|
+
|
|
29
|
+
// 导出execution-utils
|
|
30
|
+
export {
|
|
31
|
+
ExecutionStatus,
|
|
32
|
+
LockFileData,
|
|
33
|
+
createExecutionLock,
|
|
34
|
+
removeExecutionLock,
|
|
35
|
+
hasExecutionLock,
|
|
36
|
+
readExecutionLock,
|
|
37
|
+
saveExecutionStatus,
|
|
38
|
+
readExecutionStatus,
|
|
39
|
+
clearExecutionStatus,
|
|
40
|
+
formatProgress,
|
|
41
|
+
calculateSuccessRate
|
|
42
|
+
} from './execution-utils';
|
package/templates/personality.md
CHANGED
|
@@ -73,28 +73,29 @@ description: 架构师级软件工程师,以工程卓越为信仰,为追求
|
|
|
73
73
|
### 3. 系统化分析流程
|
|
74
74
|
|
|
75
75
|
**TODO清单标准流程:**
|
|
76
|
+
|
|
76
77
|
1. **需求分析**
|
|
77
|
-
-
|
|
78
|
-
-
|
|
79
|
-
-
|
|
80
|
-
- 根据充分了解到的信息,清晰完整的复述用户需求,并给出一个高度浓缩的、结论性的核心观点
|
|
78
|
+
- 搜索相关资源,明确核心问题、隐含需求和最终目标
|
|
79
|
+
- 构建知识框架:关键概念、上下文、正反论点、延伸领域
|
|
80
|
+
- 复述需求并给出结论性核心观点
|
|
81
81
|
|
|
82
82
|
2. **场景识别**
|
|
83
|
-
-
|
|
84
|
-
-
|
|
83
|
+
- 定位主要矛盾点和核心问题节点
|
|
84
|
+
- 拆解为可执行子任务,确保逻辑清晰、上下文充足
|
|
85
85
|
|
|
86
86
|
3. **方案设计**
|
|
87
|
-
-
|
|
88
|
-
-
|
|
87
|
+
- 优先复用现有方案、组件、工具方法
|
|
88
|
+
- 扫描测试框架,生成测试脚本或编写测试用例
|
|
89
89
|
|
|
90
90
|
4. **执行验证**
|
|
91
|
-
-
|
|
92
|
-
-
|
|
91
|
+
- **对齐规范**:扫描现有模块的结构、命名、风格,确保一致性
|
|
92
|
+
- **渐进实现**:按优先级逐个完成子任务,每完成一个立即自检
|
|
93
|
+
- **测试验证**:执行测试脚本并修正至通过;无脚本则基于用例手动验证
|
|
94
|
+
- **集成检查**:确认兼容性,排查依赖冲突和副作用
|
|
93
95
|
|
|
94
96
|
5. **总结反馈**
|
|
95
|
-
-
|
|
96
|
-
-
|
|
97
|
-
- 根据情况提供一些前瞻性的思考或建议
|
|
97
|
+
- 输出最终方案并更新TODO清单
|
|
98
|
+
- 提供前瞻性思考或建议
|
|
98
99
|
|
|
99
100
|
**执行原则:**
|
|
100
101
|
- 创建并持续更新TODO清单
|
|
@@ -134,4 +135,8 @@ description: 架构师级软件工程师,以工程卓越为信仰,为追求
|
|
|
134
135
|
测试策略:[如何验证方案有效性]
|
|
135
136
|
潜在风险:[可能遇到的问题]
|
|
136
137
|
优化空间:[未来改进方向]
|
|
137
|
-
```
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### 输出要求
|
|
141
|
+
- 在完成所有任务后,禁止生成使用,说明等md文档,只输出一个精简的总结内容即可
|
|
142
|
+
- 对于代码中的注释只输出方法相关的注释,符合注释规则,不要输出与方法无关的提示信息。
|
package/templates/settings.json
CHANGED
|
@@ -32,12 +32,47 @@
|
|
|
32
32
|
"deny": []
|
|
33
33
|
},
|
|
34
34
|
"hooks": {
|
|
35
|
+
"PreToolUse": [
|
|
36
|
+
{
|
|
37
|
+
"matcher": "Edit|Write",
|
|
38
|
+
"hooks": [
|
|
39
|
+
{
|
|
40
|
+
"type": "command",
|
|
41
|
+
"command": "node -e \"require('child_process').execSync('npx tsx ' + require('path').join(require('os').homedir(), '.claude/hooks/scripts/PreToolUse/pre-tool-use.ts'), {stdio: 'inherit'})\"",
|
|
42
|
+
"timeout": 10
|
|
43
|
+
}
|
|
44
|
+
]
|
|
45
|
+
}
|
|
46
|
+
],
|
|
47
|
+
"PostToolUse":[
|
|
48
|
+
{
|
|
49
|
+
"matcher": "Edit|Write",
|
|
50
|
+
"hooks": [
|
|
51
|
+
{
|
|
52
|
+
"type": "command",
|
|
53
|
+
"command": "node -e \"require('child_process').execSync('npx tsx ' + require('path').join(require('os').homedir(), '.claude/hooks/scripts/PostToolUse/post-tool-use.ts'), {stdio: 'inherit'})\"",
|
|
54
|
+
"timeout": 10
|
|
55
|
+
}
|
|
56
|
+
]
|
|
57
|
+
}
|
|
58
|
+
],
|
|
35
59
|
"UserPromptSubmit": [
|
|
36
60
|
{
|
|
37
61
|
"hooks": [
|
|
38
62
|
{
|
|
39
63
|
"type": "command",
|
|
40
|
-
"command": "
|
|
64
|
+
"command": "node -e \"require('child_process').execSync('npx tsx ' + require('path').join(require('os').homedir(), '.claude/hooks/scripts/UserPromptSubmit/user-prompt-submit.ts'), {stdio: 'inherit'})\"",
|
|
65
|
+
"timeout": 10
|
|
66
|
+
}
|
|
67
|
+
]
|
|
68
|
+
}
|
|
69
|
+
],
|
|
70
|
+
"Notification": [
|
|
71
|
+
{
|
|
72
|
+
"hooks": [
|
|
73
|
+
{
|
|
74
|
+
"type": "command",
|
|
75
|
+
"command": "node -e \"require('child_process').execSync('npx tsx ' + require('path').join(require('os').homedir(), '.claude/hooks/scripts/Notification/notification.ts'), {stdio: 'inherit'})\"",
|
|
41
76
|
"timeout": 10
|
|
42
77
|
}
|
|
43
78
|
]
|
|
@@ -48,7 +83,7 @@
|
|
|
48
83
|
"hooks": [
|
|
49
84
|
{
|
|
50
85
|
"type": "command",
|
|
51
|
-
"command": "
|
|
86
|
+
"command": "node -e \"require('child_process').execSync('npx tsx ' + require('path').join(require('os').homedir(), '.claude/hooks/scripts/Stop/stop.ts'), {stdio: 'inherit'})\"",
|
|
52
87
|
"timeout": 10
|
|
53
88
|
}
|
|
54
89
|
]
|