devassist-agent 1.0.1 → 1.0.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.
- package/bin/devassist.js +5 -0
- package/package.json +1 -1
- package/src/cli/commands/ai.js +12 -3
- package/src/cli/commands/start.js +84 -0
package/bin/devassist.js
CHANGED
|
@@ -134,6 +134,8 @@ async function main() {
|
|
|
134
134
|
return require(path.join(cmdDir, 'clean'))(projectRoot, args.slice(1), { printHeader, c });
|
|
135
135
|
case 'fix':
|
|
136
136
|
return require(path.join(cmdDir, 'fix'))(projectRoot, args.slice(1), { printHeader, c });
|
|
137
|
+
case 'start':
|
|
138
|
+
return require(path.join(cmdDir, 'start'))(projectRoot, args.slice(1), { printHeader, printFinding, printStats, c });
|
|
137
139
|
case 'watch':
|
|
138
140
|
return require(path.join(cmdDir, 'watch'))(projectRoot, args.slice(1), { printHeader, printFinding, printStats, c });
|
|
139
141
|
case 'report':
|
|
@@ -164,6 +166,7 @@ function printHelp() {
|
|
|
164
166
|
printHeader('开发守护 CLI');
|
|
165
167
|
console.log(`${c.bold('用法:')} devassist <命令> [选项]\n`);
|
|
166
168
|
console.log(`${c.bold('命令:')}`);
|
|
169
|
+
console.log(` ${c.green('start')} 一键启动:自动初始化 + AI多引擎实时监控`);
|
|
167
170
|
console.log(` ${c.green('init')} 初始化项目——创建 .devassist/ 配置与基础代码`);
|
|
168
171
|
console.log(` ${c.green('check')} 运行全部开发时检查(代码质量 + 约定 + 模式 + 架构)`);
|
|
169
172
|
console.log(` ${c.green('watch')} 实时监控文件变更并运行检查`);
|
|
@@ -192,6 +195,8 @@ function printHelp() {
|
|
|
192
195
|
console.log(` ${c.gray('-v, --version')} 显示版本`);
|
|
193
196
|
console.log(` ${c.gray('-h, --help')} 显示帮助\n`);
|
|
194
197
|
console.log(`${c.bold('示例:')}`);
|
|
198
|
+
console.log(` ${c.gray('$')} devassist start # 一键启动(自动init+AI多引擎监控)`);
|
|
199
|
+
console.log(` ${c.gray('$')} devassist start --check # 一键检查(不启动监控)`);
|
|
195
200
|
console.log(` ${c.gray('$')} devassist init`);
|
|
196
201
|
console.log(` ${c.gray('$')} devassist check --ai`);
|
|
197
202
|
console.log(` ${c.gray('$')} devassist watch # 开发时实时监控`);
|
package/package.json
CHANGED
package/src/cli/commands/ai.js
CHANGED
|
@@ -125,6 +125,7 @@ function printHelp(c) {
|
|
|
125
125
|
* Returns: { ...rawConfig, engines: [{ provider, apiKey, model, baseUrl, enabled, name }] }
|
|
126
126
|
*
|
|
127
127
|
* Resolution order:
|
|
128
|
+
* 0. Project config .devassist/ai-config.json → fallback to global ~/.devassist/ai-config.json
|
|
128
129
|
* 1. Primary engine from top-level fields (provider/apiKey/model)
|
|
129
130
|
* 2. Legacy `secondary` field (if present)
|
|
130
131
|
* 3. `engines` array (if present)
|
|
@@ -132,10 +133,13 @@ function printHelp(c) {
|
|
|
132
133
|
* 5. Deduplicate by provider+model
|
|
133
134
|
*/
|
|
134
135
|
function loadAIConfig(projectRoot) {
|
|
136
|
+
// Try project-level config first, then global config
|
|
135
137
|
const configPath = path.join(projectRoot, '.devassist', 'ai-config.json');
|
|
136
|
-
|
|
138
|
+
const globalConfigPath = path.join(require('os').homedir(), '.devassist', 'ai-config.json');
|
|
139
|
+
const usePath = fs.existsSync(configPath) ? configPath : (fs.existsSync(globalConfigPath) ? globalConfigPath : null);
|
|
140
|
+
if (!usePath) return null;
|
|
137
141
|
try {
|
|
138
|
-
const rawConfig = JSON.parse(fs.readFileSync(
|
|
142
|
+
const rawConfig = JSON.parse(fs.readFileSync(usePath, 'utf-8'));
|
|
139
143
|
|
|
140
144
|
// Build engines array
|
|
141
145
|
const engines = [];
|
|
@@ -246,7 +250,12 @@ function showAIStatus(projectRoot, c) {
|
|
|
246
250
|
console.log(` ${c.bold('devassist ai --add-engine --provider hunyuan --key <key>')}\n`);
|
|
247
251
|
}
|
|
248
252
|
|
|
249
|
-
|
|
253
|
+
// Show which config file is in use
|
|
254
|
+
const projectConfigPath = path.join(projectRoot, '.devassist', 'ai-config.json');
|
|
255
|
+
const globalConfigPath = path.join(require('os').homedir(), '.devassist', 'ai-config.json');
|
|
256
|
+
const usedPath = fs.existsSync(projectConfigPath) ? projectConfigPath : (fs.existsSync(globalConfigPath) ? globalConfigPath : null);
|
|
257
|
+
const configSource = usedPath === globalConfigPath ? c.cyan('全局') + ' ' : '';
|
|
258
|
+
console.log(` 配置文件: ${configSource}${usedPath || c.yellow('未配置')}\n`);
|
|
250
259
|
}
|
|
251
260
|
|
|
252
261
|
// ─── Setup / Add / Remove Engine ─────────────────────
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* devassist start - One-command quick start
|
|
3
|
+
*
|
|
4
|
+
* Automatically:
|
|
5
|
+
* 1. Initialize project (if not already initialized)
|
|
6
|
+
* 2. Verify AI config (global or project-level, with real API keys)
|
|
7
|
+
* 3. Start watch mode with --ai --compare
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* devassist start # Full auto: init + watch --ai --compare
|
|
11
|
+
* devassist start --no-ai # Init + watch (rules only, no AI)
|
|
12
|
+
* devassist start --check # Init + one-time check --ai --compare (no watch)
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
const fs = require('fs');
|
|
16
|
+
const path = require('path');
|
|
17
|
+
const os = require('os');
|
|
18
|
+
|
|
19
|
+
module.exports = async function start(projectRoot, args, ui) {
|
|
20
|
+
const { printHeader, printFinding, printStats, c } = ui;
|
|
21
|
+
|
|
22
|
+
const noAI = args.includes('--no-ai');
|
|
23
|
+
const checkOnly = args.includes('--check');
|
|
24
|
+
|
|
25
|
+
printHeader('一键启动');
|
|
26
|
+
|
|
27
|
+
// ─── Step 1: Auto init ────────────────────────────
|
|
28
|
+
const configDir = path.join(projectRoot, '.devassist');
|
|
29
|
+
if (!fs.existsSync(configDir)) {
|
|
30
|
+
console.log(` ${c.gray('1/3')} 项目未初始化,正在自动初始化...`);
|
|
31
|
+
const initCmd = require('./init');
|
|
32
|
+
initCmd(projectRoot, ['--force'], ui);
|
|
33
|
+
console.log('');
|
|
34
|
+
} else {
|
|
35
|
+
console.log(` ${c.green('1/3')} 项目已初始化 ✓`);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// ─── Step 2: Verify AI config ─────────────────────
|
|
39
|
+
// Use loadAIConfig to check if real API keys are configured
|
|
40
|
+
const aiCmd = require('./ai');
|
|
41
|
+
const config = aiCmd.loadAIConfig(projectRoot);
|
|
42
|
+
const readyEngines = config ? config.engines.filter(e => e.enabled && e.apiKey) : [];
|
|
43
|
+
const aiReady = readyEngines.length >= 2;
|
|
44
|
+
|
|
45
|
+
// Determine config source
|
|
46
|
+
const projectConfigPath = path.join(projectRoot, '.devassist', 'ai-config.json');
|
|
47
|
+
const globalConfigPath = path.join(os.homedir(), '.devassist', 'ai-config.json');
|
|
48
|
+
const configSource = fs.existsSync(projectConfigPath) ? '项目配置' :
|
|
49
|
+
(fs.existsSync(globalConfigPath) ? '全局配置' : '');
|
|
50
|
+
|
|
51
|
+
if (aiReady && !noAI) {
|
|
52
|
+
const engineNames = readyEngines.map(e => e.name || e.provider).join(' + ');
|
|
53
|
+
console.log(` ${c.green('2/3')} AI 引擎已就绪 ✓ (${configSource}:${engineNames})`);
|
|
54
|
+
} else if (readyEngines.length === 1 && !noAI) {
|
|
55
|
+
console.log(` ${c.green('2/3')} AI 引擎已就绪 ✓ (${configSource}:${readyEngines[0].name},仅单引擎)`);
|
|
56
|
+
console.log(` ${c.gray('提示:配置第二个引擎可启用对比模式')}`);
|
|
57
|
+
} else if (!noAI) {
|
|
58
|
+
console.log(` ${c.yellow('2/3')} 未检测到 AI 配置`);
|
|
59
|
+
console.log(` ${c.gray('将仅使用规则引擎检查(30条规则)')}`);
|
|
60
|
+
console.log(` ${c.gray('配置 AI:devassist ai --setup --provider qwen --key <key>')}`);
|
|
61
|
+
noAI = true; // fallback to rules-only
|
|
62
|
+
} else {
|
|
63
|
+
console.log(` ${c.green('2/3')} 规则引擎模式 ✓`);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// ─── Step 3: Run ──────────────────────────────────
|
|
67
|
+
if (checkOnly) {
|
|
68
|
+
console.log(` ${c.cyan('3/3')} 正在执行完整检查...\n`);
|
|
69
|
+
const checkCmd = require('./check');
|
|
70
|
+
const checkArgs = [];
|
|
71
|
+
if (!noAI) {
|
|
72
|
+
checkArgs.push('--ai', '--compare');
|
|
73
|
+
}
|
|
74
|
+
await checkCmd(projectRoot, checkArgs, ui);
|
|
75
|
+
} else {
|
|
76
|
+
console.log(` ${c.cyan('3/3')} 启动实时监控...\n`);
|
|
77
|
+
const watchCmd = require('./watch');
|
|
78
|
+
const watchArgs = [];
|
|
79
|
+
if (!noAI) {
|
|
80
|
+
watchArgs.push('--ai', '--compare');
|
|
81
|
+
}
|
|
82
|
+
await watchCmd(projectRoot, watchArgs, ui);
|
|
83
|
+
}
|
|
84
|
+
};
|