devassist-agent 1.0.0 → 1.0.2

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,8 +134,10 @@ 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
- return require(path.join(cmdDir, 'watch'))(projectRoot, args.slice(1), { printHeader, printFinding, c });
140
+ return require(path.join(cmdDir, 'watch'))(projectRoot, args.slice(1), { printHeader, printFinding, printStats, c });
139
141
  case 'report':
140
142
  return require(path.join(cmdDir, 'report'))(projectRoot, args.slice(1), { printHeader, printFinding, c });
141
143
  case 'diff':
@@ -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,9 +195,12 @@ 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 # 开发时实时监控`);
203
+ console.log(` ${c.gray('$')} devassist watch --ai --compare # 实时监控+AI多引擎对比`);
198
204
  console.log(` ${c.gray('$')} devassist diff --staged # 提交前检查暂存文件`);
199
205
  console.log(` ${c.gray('$')} devassist report --open # 生成并查看 HTML 报告`);
200
206
  console.log(` ${c.gray('$')} devassist convention add --id naming-list --rule "使用 data.list 而非 data.items" --severity block`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "devassist-agent",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
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,82 @@
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)
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
+ const projectAIConfig = path.join(projectRoot, '.devassist', 'ai-config.json');
40
+ const globalAIConfig = path.join(os.homedir(), '.devassist', 'ai-config.json');
41
+
42
+ let aiReady = false;
43
+ let configSource = '';
44
+
45
+ if (fs.existsSync(projectAIConfig)) {
46
+ aiReady = true;
47
+ configSource = '项目配置';
48
+ } else if (fs.existsSync(globalAIConfig)) {
49
+ aiReady = true;
50
+ configSource = '全局配置';
51
+ }
52
+
53
+ if (aiReady && !noAI) {
54
+ console.log(` ${c.green('2/3')} AI 引擎已就绪 ✓ (${configSource}:通义千问 + 腾讯混元)`);
55
+ } else if (!aiReady && !noAI) {
56
+ console.log(` ${c.yellow('2/3')} 未检测到 AI 配置`);
57
+ console.log(` ${c.gray('将仅使用规则引擎检查(28条规则)')}`);
58
+ console.log(` ${c.gray('配置 AI 后可启用多引擎对比:devassist ai --setup --provider qwen --key <key>')}`);
59
+ noAI = true; // fallback to rules-only
60
+ } else {
61
+ console.log(` ${c.green('2/3')} 规则引擎模式 ✓`);
62
+ }
63
+
64
+ // ─── Step 3: Run ──────────────────────────────────
65
+ if (checkOnly) {
66
+ console.log(` ${c.cyan('3/3')} 正在执行完整检查...\n`);
67
+ const checkCmd = require('./check');
68
+ const checkArgs = [];
69
+ if (!noAI) {
70
+ checkArgs.push('--ai', '--compare');
71
+ }
72
+ await checkCmd(projectRoot, checkArgs, ui);
73
+ } else {
74
+ console.log(` ${c.cyan('3/3')} 启动实时监控...\n`);
75
+ const watchCmd = require('./watch');
76
+ const watchArgs = [];
77
+ if (!noAI) {
78
+ watchArgs.push('--ai', '--compare');
79
+ }
80
+ await watchCmd(projectRoot, watchArgs, ui);
81
+ }
82
+ };
@@ -32,12 +32,14 @@ const SKIP_DIRS = ['node_modules', '.git', '.devassist', 'dist', 'build', 'vendo
32
32
  module.exports = async function watch(projectRoot, args, ui) {
33
33
  const { printHeader, printFinding, c } = ui;
34
34
  const useAI = args.includes('--ai');
35
+ const useCompare = args.includes('--compare');
35
36
  const watchDir = args.includes('--dir') ? args[args.indexOf('--dir') + 1] : null;
36
37
 
37
38
  printHeader('监控模式');
38
39
 
39
40
  console.log(` ${c.gray('监控目录:')} ${watchDir || '整个项目'}`);
40
41
  console.log(` ${c.gray('AI 分析:')} ${useAI ? '已启用' : '已禁用'}`);
42
+ console.log(` ${c.gray('多引擎对比:')} ${useCompare ? '已启用' : '已禁用'}`);
41
43
  console.log(` ${c.gray('按 Ctrl+C 停止')}\n`);
42
44
 
43
45
  // Initialize convention store
@@ -166,7 +168,10 @@ module.exports = async function watch(projectRoot, args, ui) {
166
168
  // Initial full check
167
169
  console.log(` ${c.gray('正在执行初始检查...')}`);
168
170
  const checkCmd = require('./check');
169
- await checkCmd(projectRoot, useAI ? ['--ai'] : [], ui);
171
+ const checkArgs = [];
172
+ if (useAI) checkArgs.push('--ai');
173
+ if (useCompare) checkArgs.push('--compare');
174
+ await checkCmd(projectRoot, checkArgs, ui);
170
175
  console.log(`\n ${c.cyan('开始监控变更...')}`);
171
176
 
172
177
  // Handle new files being added (watch parent dirs for new entries)