agent-window 1.0.6 → 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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-window",
3
- "version": "1.0.6",
3
+ "version": "1.0.8",
4
4
  "description": "A window to interact with AI agents through chat interfaces. Simplified interaction, powerful backend capabilities.",
5
5
  "type": "module",
6
6
  "main": "src/bot.js",
@@ -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: '验证失败:项目不是有效的 AgentWindow BMAD 插件',
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
@@ -249,10 +257,24 @@ export async function discoverInstances() {
249
257
  let configPath = null;
250
258
  let pluginPath = null;
251
259
 
252
- // Priority 1: Use CONFIG_PATH from environment variables
253
- if (proc.configPath) {
260
+ // Priority 1: Read CONFIG_PATH and extract PROJECT_DIR from config
261
+ if (proc.configPath && existsSync(proc.configPath)) {
254
262
  configPath = proc.configPath;
255
- projectPath = path.dirname(configPath);
263
+ try {
264
+ const configContent = await fs.readFile(proc.configPath, 'utf8');
265
+ const config = JSON.parse(configContent);
266
+
267
+ // Use PROJECT_DIR from config if available
268
+ if (config.PROJECT_DIR) {
269
+ projectPath = config.PROJECT_DIR;
270
+ } else {
271
+ // Fallback to config directory
272
+ projectPath = path.dirname(configPath);
273
+ }
274
+ } catch {
275
+ // If config read fails, use directory name
276
+ projectPath = path.dirname(configPath);
277
+ }
256
278
  }
257
279
  // Priority 2: Use cwd
258
280
  else if (proc.cwd) {
@@ -267,6 +289,23 @@ export async function discoverInstances() {
267
289
  pluginPath = path.join(projectPath, 'src');
268
290
  }
269
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
+
270
309
  discovered.push({
271
310
  botName: proc.name,
272
311
  name: instanceName,
@@ -274,6 +313,7 @@ export async function discoverInstances() {
274
313
  projectPath,
275
314
  configPath,
276
315
  pluginPath,
316
+ instanceType, // 'bmad' | 'simple' | 'unknown'
277
317
  status: proc.status || 'unknown',
278
318
  pid: proc.pid,
279
319
  memory: proc.memory || 0,
@@ -325,6 +365,7 @@ export async function importInstance(discovered) {
325
365
  configPath: discovered.configPath,
326
366
  pluginPath: validatedPluginPath,
327
367
  botName: discovered.botName,
368
+ instanceType: discovered.instanceType || 'simple-config', // Save instance type
328
369
  addedAt: new Date().toISOString(),
329
370
  tags: ['imported'],
330
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
- // 1. Path exists check
65
- checks.push({
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: 'plugin.botjs',
97
- passed: botJsExists,
96
+ name: 'type.detected',
97
+ passed: instanceType !== 'unknown',
98
98
  required: true,
99
- error: botJsExists ? null : '插件缺少核心文件 src/bot.js'
99
+ error: instanceType === 'unknown' ? '无法识别的实例类型' : `检测到${instanceType === 'bmad-plugin' ? ' BMAD 插件' : '简单配置'}实例`
100
100
  });
101
101
 
102
- // 5. package.json validation (check dependencies, not hardcoded name)
103
- const pluginPkgPath = path.join(pluginPath, 'package.json');
104
- const hasDiscord = await hasDependency(pluginPkgPath, 'discord.js');
105
- checks.push({
106
- name: 'plugin.package',
107
- passed: hasDiscord,
108
- required: true,
109
- error: hasDiscord ? null : '插件 package.json 缺少 discord.js 依赖'
110
- });
111
-
112
- // 6. BMAD config check (optional)
113
- const bmadConfigPath = path.join(normalizedPath, '_bmad/core/config.yaml');
114
- const bmadConfigExists = pathExists(bmadConfigPath);
115
- checks.push({
116
- name: 'bmad.config',
117
- passed: bmadConfigExists,
118
- required: false,
119
- error: bmadConfigExists ? null : 'BMAD 配置文件不存在(非致命)'
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: pluginExists ? pluginPath : null,
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
  }