agent-window 1.0.7 → 1.0.8
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/package.json +1 -1
- package/src/core/instance/manager.js +29 -2
- package/src/core/instance/validator.js +109 -54
package/package.json
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
import fs from 'fs/promises';
|
|
9
9
|
import path from 'path';
|
|
10
10
|
import { existsSync } from 'fs';
|
|
11
|
-
import { validateInstance } from './validator.js';
|
|
11
|
+
import { validateInstance, detectInstanceType } from './validator.js';
|
|
12
12
|
import { paths } from '../platform/index.js';
|
|
13
13
|
import { getProcesses } from './pm2-bridge.js';
|
|
14
14
|
|
|
@@ -92,9 +92,16 @@ export async function addInstance(name, projectPath, options = {}) {
|
|
|
92
92
|
// Validate the instance
|
|
93
93
|
const validation = await validateInstance(projectPath);
|
|
94
94
|
if (!validation.valid) {
|
|
95
|
+
// Provide helpful error message based on instance type
|
|
96
|
+
const typeMsg = validation.instanceType === 'simple-config'
|
|
97
|
+
? '简单配置实例无法通过"添加实例"功能添加。请先使用 PM2 启动 bot,然后在 Web UI 中导入。'
|
|
98
|
+
: validation.instanceType === 'unknown'
|
|
99
|
+
? '无法识别的项目类型'
|
|
100
|
+
: '项目不是有效的 AgentWindow BMAD 插件';
|
|
101
|
+
|
|
95
102
|
return {
|
|
96
103
|
success: false,
|
|
97
|
-
error: '
|
|
104
|
+
error: '验证失败:' + typeMsg,
|
|
98
105
|
validation
|
|
99
106
|
};
|
|
100
107
|
}
|
|
@@ -113,6 +120,7 @@ export async function addInstance(name, projectPath, options = {}) {
|
|
|
113
120
|
pluginPath: validation.pluginPath,
|
|
114
121
|
configPath,
|
|
115
122
|
botName: `bot-${name}`,
|
|
123
|
+
instanceType: validation.instanceType, // Save instance type
|
|
116
124
|
addedAt: new Date().toISOString(),
|
|
117
125
|
tags: options.tags || [],
|
|
118
126
|
enabled: true
|
|
@@ -281,6 +289,23 @@ export async function discoverInstances() {
|
|
|
281
289
|
pluginPath = path.join(projectPath, 'src');
|
|
282
290
|
}
|
|
283
291
|
|
|
292
|
+
// Detect instance type based on project structure
|
|
293
|
+
let instanceType = 'unknown';
|
|
294
|
+
if (projectPath) {
|
|
295
|
+
// Check if it has BMAD plugin (_agent-bridge directory)
|
|
296
|
+
if (existsSync(path.join(projectPath, '_agent-bridge'))) {
|
|
297
|
+
instanceType = 'bmad-plugin';
|
|
298
|
+
}
|
|
299
|
+
// Check if it has a config file (simple config instance)
|
|
300
|
+
else if (existsSync(path.join(projectPath, 'config.json'))) {
|
|
301
|
+
instanceType = 'simple-config';
|
|
302
|
+
}
|
|
303
|
+
// Check if configPath exists and has config.json
|
|
304
|
+
else if (configPath && existsSync(configPath)) {
|
|
305
|
+
instanceType = 'simple-config';
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
284
309
|
discovered.push({
|
|
285
310
|
botName: proc.name,
|
|
286
311
|
name: instanceName,
|
|
@@ -288,6 +313,7 @@ export async function discoverInstances() {
|
|
|
288
313
|
projectPath,
|
|
289
314
|
configPath,
|
|
290
315
|
pluginPath,
|
|
316
|
+
instanceType, // 'bmad' | 'simple' | 'unknown'
|
|
291
317
|
status: proc.status || 'unknown',
|
|
292
318
|
pid: proc.pid,
|
|
293
319
|
memory: proc.memory || 0,
|
|
@@ -339,6 +365,7 @@ export async function importInstance(discovered) {
|
|
|
339
365
|
configPath: discovered.configPath,
|
|
340
366
|
pluginPath: validatedPluginPath,
|
|
341
367
|
botName: discovered.botName,
|
|
368
|
+
instanceType: discovered.instanceType || 'simple-config', // Save instance type
|
|
342
369
|
addedAt: new Date().toISOString(),
|
|
343
370
|
tags: ['imported'],
|
|
344
371
|
enabled: true,
|
|
@@ -2,12 +2,39 @@
|
|
|
2
2
|
* Instance Validator
|
|
3
3
|
*
|
|
4
4
|
* Validates if a project path contains a valid AgentWindow BMAD plugin instance.
|
|
5
|
+
* Supports two types:
|
|
6
|
+
* 1. Simple config (基础版) - Only has config.json
|
|
7
|
+
* 2. BMAD plugin (增强版) - Has _bmad and _agent-bridge directories
|
|
5
8
|
*/
|
|
6
9
|
|
|
7
10
|
import fs from 'fs/promises';
|
|
8
11
|
import path from 'path';
|
|
9
12
|
import { existsSync } from 'fs';
|
|
10
13
|
|
|
14
|
+
/**
|
|
15
|
+
* Detect instance type
|
|
16
|
+
* @param {string} projectPath - Path to check
|
|
17
|
+
* @returns {string} 'bmad-plugin' | 'simple-config' | 'unknown'
|
|
18
|
+
*/
|
|
19
|
+
export function detectInstanceType(projectPath) {
|
|
20
|
+
const normalizedPath = path.resolve(projectPath);
|
|
21
|
+
|
|
22
|
+
// Check if it has BMAD plugin (_agent-bridge directory)
|
|
23
|
+
const hasPlugin = existsSync(path.join(normalizedPath, '_agent-bridge'));
|
|
24
|
+
|
|
25
|
+
if (hasPlugin) {
|
|
26
|
+
return 'bmad-plugin';
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Check if it has config.json (simple config instance)
|
|
30
|
+
const hasConfig = existsSync(path.join(normalizedPath, 'config.json'));
|
|
31
|
+
if (hasConfig) {
|
|
32
|
+
return 'simple-config';
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return 'unknown';
|
|
36
|
+
}
|
|
37
|
+
|
|
11
38
|
/**
|
|
12
39
|
* Validation check definition
|
|
13
40
|
* @typedef {Object} ValidationCheck
|
|
@@ -21,6 +48,7 @@ import { existsSync } from 'fs';
|
|
|
21
48
|
* Validation result
|
|
22
49
|
* @typedef {Object} ValidationResult
|
|
23
50
|
* @property {boolean} valid - Overall validation result
|
|
51
|
+
* @property {string} instanceType - 'bmad' | 'simple' | 'unknown'
|
|
24
52
|
* @property {Array<Object>} checks - Individual check results
|
|
25
53
|
* @property {string|null} pluginPath - Path to the plugin directory
|
|
26
54
|
* @property {string} projectPath - Path to the project directory
|
|
@@ -61,63 +89,88 @@ export async function validateInstance(projectPath) {
|
|
|
61
89
|
const checks = [];
|
|
62
90
|
const normalizedPath = path.resolve(projectPath);
|
|
63
91
|
|
|
64
|
-
//
|
|
65
|
-
|
|
66
|
-
name: 'path.exists',
|
|
67
|
-
passed: pathExists(normalizedPath),
|
|
68
|
-
required: true,
|
|
69
|
-
error: pathExists(normalizedPath) ? null : '项目路径不存在'
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
// 2. BMAD framework check
|
|
73
|
-
const bmadPath = path.join(normalizedPath, '_bmad');
|
|
74
|
-
const bmadExists = pathExists(bmadPath);
|
|
75
|
-
checks.push({
|
|
76
|
-
name: 'bmad.exists',
|
|
77
|
-
passed: bmadExists,
|
|
78
|
-
required: true,
|
|
79
|
-
error: bmadExists ? null : '未检测到 BMAD 框架 (_bmad 目录)'
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
// 3. Plugin directory check
|
|
83
|
-
const pluginPath = path.join(normalizedPath, '_agent-bridge');
|
|
84
|
-
const pluginExists = pathExists(pluginPath);
|
|
85
|
-
checks.push({
|
|
86
|
-
name: 'plugin.exists',
|
|
87
|
-
passed: pluginExists,
|
|
88
|
-
required: true,
|
|
89
|
-
error: pluginExists ? null : '未检测到 _agent-bridge 插件目录'
|
|
90
|
-
});
|
|
92
|
+
// Detect instance type
|
|
93
|
+
const instanceType = detectInstanceType(normalizedPath);
|
|
91
94
|
|
|
92
|
-
// 4. Core bot.js file check
|
|
93
|
-
const botJsPath = path.join(pluginPath, 'src/bot.js');
|
|
94
|
-
const botJsExists = pathExists(botJsPath);
|
|
95
95
|
checks.push({
|
|
96
|
-
name: '
|
|
97
|
-
passed:
|
|
96
|
+
name: 'type.detected',
|
|
97
|
+
passed: instanceType !== 'unknown',
|
|
98
98
|
required: true,
|
|
99
|
-
error:
|
|
99
|
+
error: instanceType === 'unknown' ? '无法识别的实例类型' : `检测到${instanceType === 'bmad-plugin' ? ' BMAD 插件' : '简单配置'}实例`
|
|
100
100
|
});
|
|
101
101
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
102
|
+
let pluginPath = null;
|
|
103
|
+
|
|
104
|
+
if (instanceType === 'bmad-plugin') {
|
|
105
|
+
// BMAD-specific checks
|
|
106
|
+
const bmadPath = path.join(normalizedPath, '_bmad');
|
|
107
|
+
const bmadExists = pathExists(bmadPath);
|
|
108
|
+
checks.push({
|
|
109
|
+
name: 'bmad.exists',
|
|
110
|
+
passed: bmadExists,
|
|
111
|
+
required: true,
|
|
112
|
+
error: bmadExists ? null : '未检测到 BMAD 框架 (_bmad 目录)'
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
pluginPath = path.join(normalizedPath, '_agent-bridge');
|
|
116
|
+
const pluginExists = pathExists(pluginPath);
|
|
117
|
+
checks.push({
|
|
118
|
+
name: 'plugin.exists',
|
|
119
|
+
passed: pluginExists,
|
|
120
|
+
required: true,
|
|
121
|
+
error: pluginExists ? null : '未检测到 _agent-bridge 插件目录'
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
const botJsPath = path.join(pluginPath, 'src/bot.js');
|
|
125
|
+
const botJsExists = pathExists(botJsPath);
|
|
126
|
+
checks.push({
|
|
127
|
+
name: 'plugin.botjs',
|
|
128
|
+
passed: botJsExists,
|
|
129
|
+
required: true,
|
|
130
|
+
error: botJsExists ? null : '插件缺少核心文件 src/bot.js'
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
const pluginPkgPath = path.join(pluginPath, 'package.json');
|
|
134
|
+
const hasDiscord = await hasDependency(pluginPkgPath, 'discord.js');
|
|
135
|
+
checks.push({
|
|
136
|
+
name: 'plugin.package',
|
|
137
|
+
passed: hasDiscord,
|
|
138
|
+
required: true,
|
|
139
|
+
error: hasDiscord ? null : '插件 package.json 缺少 discord.js 依赖'
|
|
140
|
+
});
|
|
141
|
+
} else if (instanceType === 'simple-config') {
|
|
142
|
+
// Simple config instance
|
|
143
|
+
const configPath = path.join(normalizedPath, 'config.json');
|
|
144
|
+
const configExists = pathExists(configPath);
|
|
145
|
+
checks.push({
|
|
146
|
+
name: 'config.exists',
|
|
147
|
+
passed: configExists,
|
|
148
|
+
required: true,
|
|
149
|
+
error: configExists ? null : '配置文件不存在'
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
// Try to validate config structure
|
|
153
|
+
if (configExists) {
|
|
154
|
+
try {
|
|
155
|
+
const configContent = await fs.readFile(configPath, 'utf-8');
|
|
156
|
+
const config = JSON.parse(configContent);
|
|
157
|
+
const hasBotToken = !!(config.BOT_TOKEN || config.token);
|
|
158
|
+
checks.push({
|
|
159
|
+
name: 'config.token',
|
|
160
|
+
passed: hasBotToken,
|
|
161
|
+
required: true,
|
|
162
|
+
error: hasBotToken ? null : '配置文件缺少 BOT_TOKEN'
|
|
163
|
+
});
|
|
164
|
+
} catch (e) {
|
|
165
|
+
checks.push({
|
|
166
|
+
name: 'config.valid',
|
|
167
|
+
passed: false,
|
|
168
|
+
required: true,
|
|
169
|
+
error: '配置文件格式错误'
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
121
174
|
|
|
122
175
|
// Determine overall validity
|
|
123
176
|
const allRequiredPassed = checks
|
|
@@ -126,8 +179,9 @@ export async function validateInstance(projectPath) {
|
|
|
126
179
|
|
|
127
180
|
return {
|
|
128
181
|
valid: allRequiredPassed,
|
|
182
|
+
instanceType,
|
|
129
183
|
checks,
|
|
130
|
-
pluginPath
|
|
184
|
+
pluginPath,
|
|
131
185
|
projectPath: normalizedPath
|
|
132
186
|
};
|
|
133
187
|
}
|
|
@@ -140,6 +194,7 @@ export async function validateInstance(projectPath) {
|
|
|
140
194
|
export function formatValidationResult(result) {
|
|
141
195
|
const lines = [
|
|
142
196
|
'验证结果: ' + (result.valid ? '✓ 通过' : '✗ 失败'),
|
|
197
|
+
`实例类型: ${result.instanceType === 'bmad-plugin' ? 'BMAD 插件' : result.instanceType === 'simple-config' ? '简单配置' : '未知'}`,
|
|
143
198
|
''
|
|
144
199
|
];
|
|
145
200
|
|
|
@@ -152,7 +207,7 @@ export function formatValidationResult(result) {
|
|
|
152
207
|
}
|
|
153
208
|
}
|
|
154
209
|
|
|
155
|
-
if (result.valid) {
|
|
210
|
+
if (result.valid && result.pluginPath) {
|
|
156
211
|
lines.push('');
|
|
157
212
|
lines.push(`插件路径: ${result.pluginPath}`);
|
|
158
213
|
}
|