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 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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "devassist-agent",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "AI Agent 开发质量守护工具 — 30+规则检测代码缺陷/安全漏洞/性能反模式,多引擎AI根因分析,零外部依赖",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -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
- if (!fs.existsSync(configPath)) return null;
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(configPath, 'utf-8'));
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
- console.log(` 配置文件: ${path.join(projectRoot, '.devassist', 'ai-config.json')}\n`);
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
+ };