agent-window 1.3.8 → 1.4.0

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.
@@ -11,5 +11,72 @@
11
11
  ]
12
12
  }
13
13
  ]
14
+ },
15
+ "permissions": {
16
+ "allow": [
17
+ "WebSearch",
18
+ "Bash(npm install)",
19
+ "Bash(pm2 list:*)",
20
+ "Bash(pm2 start:*)",
21
+ "Bash(pm2 logs:*)",
22
+ "WebFetch(domain:github.com)",
23
+ "Bash(docker stop:*)",
24
+ "Bash(docker rm:*)",
25
+ "Bash(pm2 restart:*)",
26
+ "Bash(docker exec:*)",
27
+ "Bash(docker logs:*)",
28
+ "Bash(pm2 flush:*)",
29
+ "Bash(chmod:*)",
30
+ "Bash(node bin/cli.js:*)",
31
+ "Bash(node /Users/cyrus/Documents/project/discord-cli-bot/bin/cli.js:*)",
32
+ "Bash(pm2 stop:*)",
33
+ "Bash(pm2 delete:*)",
34
+ "Bash(git checkout:*)",
35
+ "Skill(bmad:bmm:workflows:quick-spec)",
36
+ "Skill(bmad:bmb:workflows:module)",
37
+ "Skill(bmad:bmb:workflows:quick-dev)",
38
+ "Bash(git rev-parse:*)",
39
+ "Bash(node --check:*)",
40
+ "Bash(npm init -y)",
41
+ "Bash(node:*)",
42
+ "Bash(git add:*)",
43
+ "Bash(git commit:*)",
44
+ "Bash(python3:*)",
45
+ "WebFetch(domain:www.vibesparking.com)",
46
+ "WebFetch(domain:docs.z.ai)",
47
+ "Bash(claude mcp search:*)",
48
+ "Bash(npm search:*)",
49
+ "Bash(npm view:*)",
50
+ "WebFetch(domain:docs.bigmodel.cn)",
51
+ "mcp__web-search-prime__webSearchPrime",
52
+ "mcp__web-reader__webReader",
53
+ "Bash(docker stats:*)",
54
+ "Bash(git stash:*)",
55
+ "Bash(git -C /Users/cyrus/Documents/project/corp-office/finance-department log:*)",
56
+ "Bash(git -C /Users/cyrus/Documents/project/corp-office/finance-department status)",
57
+ "Bash(lsof:*)",
58
+ "Bash(pwdx:*)",
59
+ "Bash(docker:*)",
60
+ "Bash(kill:*)",
61
+ "Bash(pkill:*)",
62
+ "Bash(env:*)",
63
+ "Bash(compgen:*)",
64
+ "Bash(claude:*)",
65
+ "Bash(for:*)",
66
+ "Bash(do echo:*)",
67
+ "Bash(done:*)",
68
+ "mcp__zai-mcp-server__analyze_image",
69
+ "mcp__zread__search_doc",
70
+ "mcp__zread__get_repo_structure",
71
+ "mcp__zread__read_file",
72
+ "mcp__zai-mcp-server__extract_text_from_screenshot",
73
+ "mcp__zai-mcp-server__ui_to_artifact",
74
+ "mcp__zai-mcp-server__understand_technical_diagram",
75
+ "mcp__zai-mcp-server__diagnose_error_screenshot",
76
+ "mcp__zai-mcp-server__analyze_data_visualization",
77
+ "mcp__zai-mcp-server__analyze_video",
78
+ "Skill(bmad:core:workflows:party-mode)",
79
+ "Skill(bmad:core:agents:bmad-master)"
80
+ ]
14
81
  }
15
82
  }
@@ -0,0 +1,91 @@
1
+ #!/usr/bin/expect -f
2
+
3
+ # BMAD Framework Automated Installation Script
4
+ # This script automates the BMAD framework installation
5
+
6
+ set timeout 120
7
+
8
+ # Check if expect is installed
9
+ if {catch {exec expect << EOC
10
+ package require Expect
11
+ EOC
12
+ }} {
13
+ puts "Error: expect is not installed"
14
+ puts "Install with: brew install expect"
15
+ exit 1
16
+ }
17
+
18
+ puts "\n🔧 BMAD Framework Automated Installer"
19
+ puts "==================================\n"
20
+
21
+ # Change to project directory
22
+ cd /Users/cyrus/Documents/project/agent-window-main
23
+
24
+ puts "📍 Current directory: [exec pwd]"
25
+ puts "🚀 Starting: npx observer-ggboy-bmad-method install\n"
26
+
27
+ # Spawn the installer
28
+ spawn npx observer-gyboy-bmad-method install
29
+
30
+ # Wait for installer to load
31
+ expect {
32
+ -timeout 30
33
+ "Installation directory:"
34
+ }
35
+
36
+ puts "\n✓ Installer loaded"
37
+ puts "\n⚠️ IMPORTANT: Please make selections manually:"
38
+ puts " 1. Use ↑↓ arrows to navigate"
39
+ puts " 2. Press SPACE to select/deselect modules"
40
+ puts " 3. SKIP 'agent-window' module (your project)"
41
+ puts " 4. Install official BMAD modules:"
42
+ puts " - bmad-builder"
43
+ puts " - bmad-creative-intelligence-suite"
44
+ puts " - bmad-game-dev-studio"
45
+ puts " 5. Press ENTER to start installation"
46
+ puts "\n📝 Press ENTER when ready to see selections...\n"
47
+
48
+ # Wait for user to press Enter
49
+ expect {
50
+ "\n"
51
+ puts "\n✓ Ready. Proceeding with installation..."
52
+ exp_continue
53
+ }
54
+
55
+ # Wait for installation to complete
56
+ expect {
57
+ timeout 300
58
+ eof
59
+ }
60
+
61
+ puts "\n✅ Installation completed!"
62
+ puts "\n🔍 Verifying installation..."
63
+
64
+ # Check if BMAD files were installed
65
+ after 3 {
66
+ if {[file exists "_bmad/core/agents"]} {
67
+ puts "✓ BMAD core files installed"
68
+ } else {
69
+ puts "⚠️ BMAD core files not found"
70
+ }
71
+
72
+ if {[file exists "_bmad/bmm/agents"]} {
73
+ puts "✓ BMM module installed"
74
+ } else {
75
+ puts "⚠️ BMM module not found"
76
+ }
77
+
78
+ if {[file exists "_bmad/bmb/agents"]} {
79
+ puts "✓ BMB module installed"
80
+ } else {
81
+ puts "⚠️ BMB module not found"
82
+ }
83
+ }
84
+
85
+ puts "\n📚 Next steps:"
86
+ puts "1. Check _bmad/ directory structure"
87
+ puts "2. Test BMAD commands in Claude Code by typing /"
88
+ puts "3. Read BMAD-INSTALL-GUIDE.md for detailed information\n"
89
+
90
+ puts "Press ENTER to exit..."
91
+ expect user "\n"
@@ -0,0 +1,22 @@
1
+ #!/bin/bash
2
+
3
+ # BMAD Framework Installation Script
4
+ # Interactive installation that preserves existing files
5
+
6
+ echo "🔧 BMAD Framework Installer"
7
+ echo ""
8
+ echo "Starting: npx observer-ggboy-bmad-method install"
9
+ echo ""
10
+
11
+ # Run installer in background with input stream
12
+ {
13
+ # Wait a bit for installer to start
14
+ sleep 3
15
+
16
+ # Check if it's asking about modules
17
+ echo "Skipping AgentWindow module installation..."
18
+
19
+ } | npx observer-ggboy-bmad-method install
20
+
21
+ echo ""
22
+ echo "✅ Installation complete!"
@@ -0,0 +1,148 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * BMAD Framework Installation Script
5
+ * Interactive installer that preserves existing files
6
+ */
7
+
8
+ const { spawn } = require('child_process');
9
+ const readline = require('readline');
10
+ const fs = require('fs');
11
+ const path = require('path');
12
+
13
+ class BMADInstaller {
14
+ constructor() {
15
+ this.bmadDir = path.join(process.cwd(), '_bmad');
16
+ this.installer = null;
17
+ }
18
+
19
+ log(message) {
20
+ console.log(`[BMAD Installer] ${message}`);
21
+ }
22
+
23
+ async checkExistingFiles() {
24
+ this.log('Checking existing BMAD files...');
25
+
26
+ const existing = [];
27
+
28
+ // Check core directories
29
+ const coreDirs = ['agents', 'tasks', 'workflows', 'resources'];
30
+ const corePath = path.join(this.bmadDir, 'core');
31
+
32
+ if (fs.existsSync(corePath)) {
33
+ for (const dir of coreDirs) {
34
+ const dirPath = path.join(corePath, dir);
35
+ if (fs.existsSync(dirPath)) {
36
+ const files = fs.readdirSync(dirPath);
37
+ if (files.length > 0) {
38
+ existing.push(`core/${dir}/ (${files.length} files)`);
39
+ }
40
+ }
41
+ }
42
+ }
43
+
44
+ // Check modules
45
+ const modules = ['bmm', 'bmb'];
46
+ for (const mod of modules) {
47
+ const modPath = path.join(this.bmadDir, mod);
48
+ if (fs.existsSync(modPath)) {
49
+ const files = fs.readdirSync(modPath, { recursive: true });
50
+ existing.push(`${mod}/ (${files.length} files)`);
51
+ }
52
+ }
53
+
54
+ if (existing.length > 0) {
55
+ this.log(`Found existing files:\n - ${existing.join('\n - ')}`);
56
+ } else {
57
+ this.log('No existing BMAD framework files found');
58
+ }
59
+
60
+ return existing;
61
+ }
62
+
63
+ async runInteractive(input) {
64
+ return new Promise((resolve, reject) => {
65
+ this.log('Starting BMAD framework installer...');
66
+ this.log('Command: npx observer-ggboy-bmad-method install');
67
+
68
+ this.installer = spawn('npm', ['exec', 'observer-ggboy-bmad-method', 'install'], {
69
+ cwd: process.cwd(),
70
+ stdio: ['pipe', 'pipe', 'pipe']
71
+ });
72
+
73
+ let output = '';
74
+ let prompt = '';
75
+
76
+ this.installer.stdout.on('data', (data) => {
77
+ const text = data.toString();
78
+ output += text;
79
+ process.stdout.write(text);
80
+
81
+ // Check if installer is waiting for input
82
+ if (text.includes('?') || text.includes('Select')) {
83
+ prompt = text;
84
+ }
85
+ });
86
+
87
+ this.installer.stderr.on('data', (data) => {
88
+ process.stderr.write(data);
89
+ });
90
+
91
+ this.installer.on('close', (code) => {
92
+ if (code === 0) {
93
+ this.log('✅ Installation completed');
94
+ resolve(output);
95
+ } else {
96
+ this.log(`Installer exited with code ${code}`);
97
+ resolve(output);
98
+ }
99
+ });
100
+
101
+ // Send input if provided
102
+ if (input) {
103
+ setTimeout(() => {
104
+ this.installer.stdin.write(input + '\n');
105
+ }, 1000);
106
+ }
107
+ });
108
+ }
109
+
110
+ async installWithDefaults() {
111
+ this.log('Installing with default options (skip AgentWindow module)...');
112
+
113
+ // The installer will ask which modules to install
114
+ // We'll provide default answers
115
+ const responses = [
116
+ // Skip AgentWindow module (we want official modules only)
117
+ '\n', // Press Enter to skip AgentWindow
118
+ ];
119
+
120
+ for (const response of responses) {
121
+ await new Promise(resolve => setTimeout(resolve, 2000));
122
+ this.installer.stdin.write(response);
123
+ }
124
+ }
125
+ }
126
+
127
+ // Main installation
128
+ async function main() {
129
+ const installer = new BMADInstaller();
130
+
131
+ console.log('\n🔧 BMAD Framework Interactive Installer\n');
132
+ console.log('This will install the BMAD framework without overwriting existing files.\n');
133
+
134
+ await installer.checkExistingFiles();
135
+
136
+ console.log('\nStarting interactive installer...');
137
+ console.log('Note: When prompted, SKIP the AgentWindow module installation.');
138
+ console.log('Only install official BMAD modules (core, bmm, bmb).\n');
139
+
140
+ await installer.runInteractive();
141
+
142
+ console.log('\n✅ Installation complete!\n');
143
+ }
144
+
145
+ main().catch(err => {
146
+ console.error('Error:', err);
147
+ process.exit(1);
148
+ });
package/package.json CHANGED
@@ -1,12 +1,9 @@
1
1
  {
2
2
  "name": "agent-window",
3
- "version": "1.3.8",
3
+ "version": "1.4.0",
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",
7
- "bin": {
8
- "agent-window": "./bin/cli.js"
9
- },
10
7
  "scripts": {
11
8
  "start": "node src/bot.js",
12
9
  "dev": "node --watch src/bot.js",
@@ -15,23 +12,16 @@
15
12
  "ui:dev": "cd web && npm run dev",
16
13
  "ui:build": "cd web && npm run build",
17
14
  "pm2:start": "pm2 start ecosystem.config.cjs",
18
- "pm2:stop": "pm2 stop agent-window",
19
- "pm2:restart": "pm2 restart agent-window",
20
- "pm2:logs": "pm2 logs agent-window"
15
+ "pm2:stop": "pm2 stop bot-corp",
16
+ "pm2:restart": "pm2 restart bot-corp",
17
+ "pm2:logs": "pm2 logs bot-corp"
21
18
  },
22
19
  "keywords": [
23
- "agent",
24
- "window",
25
20
  "discord",
26
- "slack",
27
21
  "bot",
22
+ "bmad",
28
23
  "claude",
29
- "ai",
30
- "cli",
31
- "docker",
32
- "sandbox",
33
- "chat",
34
- "interface"
24
+ "ai"
35
25
  ],
36
26
  "author": "",
37
27
  "license": "MIT",
@@ -49,9 +39,5 @@
49
39
  },
50
40
  "overrides": {
51
41
  "undici": "^7.19.0"
52
- },
53
- "repository": {
54
- "type": "git",
55
- "url": "https://github.com/Observer-GGboy/AgentWindow"
56
42
  }
57
43
  }
@@ -24,7 +24,9 @@ import {
24
24
  getLogs
25
25
  } from '../../core/instance/pm2-bridge.js';
26
26
  import { readConfig, writeConfig } from '../../core/instance/config-reader.js';
27
+ import { paths } from '../../core/platform/index.js';
27
28
  import { existsSync } from 'fs';
29
+ import { promises as fs } from 'fs';
28
30
  import path from 'path';
29
31
 
30
32
  /**
@@ -113,27 +115,68 @@ export async function registerInstanceRoutes(fastify) {
113
115
  try {
114
116
  const { name, projectPath, displayName, tags, configPath, config, createConfig, instanceType } = request.body;
115
117
 
116
- // If creating config file, ensure project path exists or create it
118
+ // If creating config file, ensure directories exist
117
119
  if (createConfig) {
118
- const fs = await import('fs/promises');
119
- const { existsSync } = await import('fs');
120
+ // For simple-config instances, config goes in botsDir/{name}/config.json
121
+ // For bmad-plugin instances, config goes in project directory
122
+ let configFilePath;
123
+ const effectiveInstanceType = instanceType || 'simple-config';
124
+
125
+ if (effectiveInstanceType === 'simple-config') {
126
+ // Simple-config: use botsDir/{name}/config.json
127
+ const botsDir = paths.getBotsDir();
128
+ configFilePath = configPath || path.join(botsDir, name, 'config.json');
129
+
130
+ // Ensure bots directory exists
131
+ if (!existsSync(botsDir)) {
132
+ try {
133
+ await fs.mkdir(botsDir, { recursive: true });
134
+ } catch (err) {
135
+ return reply.code(400).send({
136
+ error: 'Failed to create bots directory',
137
+ message: err.message
138
+ });
139
+ }
140
+ }
120
141
 
121
- // Create project directory if it doesn't exist
122
- if (!existsSync(projectPath)) {
123
- try {
124
- await fs.mkdir(projectPath, { recursive: true });
125
- } catch (err) {
126
- return reply.code(400).send({
127
- error: 'Failed to create project directory',
128
- message: err.message
129
- });
142
+ // Create instance directory (botsDir/{name})
143
+ const instanceDir = path.dirname(configFilePath);
144
+ if (!existsSync(instanceDir)) {
145
+ try {
146
+ await fs.mkdir(instanceDir, { recursive: true });
147
+ } catch (err) {
148
+ return reply.code(400).send({
149
+ error: 'Failed to create instance directory',
150
+ message: err.message
151
+ });
152
+ }
153
+ }
154
+ } else {
155
+ // BMAD plugin: use projectPath/config.json
156
+ configFilePath = configPath || path.join(projectPath, 'config.json');
157
+
158
+ // Create project directory if it doesn't exist
159
+ if (!existsSync(projectPath)) {
160
+ try {
161
+ await fs.mkdir(projectPath, { recursive: true });
162
+ } catch (err) {
163
+ return reply.code(400).send({
164
+ error: 'Failed to create project directory',
165
+ message: err.message
166
+ });
167
+ }
130
168
  }
131
169
  }
132
170
 
133
171
  // Write config file
134
- const configFilePath = configPath || path.join(projectPath, 'config.json');
135
172
  try {
136
- await fs.writeFile(configFilePath, JSON.stringify(config, null, 2), 'utf-8');
173
+ // Ensure dockerImage uses local claude-sandbox if workspace specified but no dockerImage
174
+ const finalConfig = { ...config };
175
+ if (finalConfig.workspace && finalConfig.workspace.containerName && !finalConfig.workspace.dockerImage) {
176
+ finalConfig.workspace.dockerImage = 'claude-sandbox';
177
+ }
178
+
179
+ await fs.writeFile(configFilePath, JSON.stringify(finalConfig, null, 2), 'utf-8');
137
180
  } catch (err) {
138
181
  return reply.code(400).send({
139
182
  error: 'Failed to write config file',
@@ -148,7 +191,7 @@ export async function registerInstanceRoutes(fastify) {
148
191
  tags,
149
192
  configPath: finalConfigPath,
150
193
  createConfig: true,
151
- instanceType: instanceType || 'simple-config'
194
+ instanceType: effectiveInstanceType
152
195
  });
153
196
 
154
197
  if (!result.success) {
@@ -108,19 +108,20 @@ export async function registerOperationRoutes(fastify) {
108
108
  };
109
109
 
110
110
  // Check if process already exists in PM2
111
- const { getProcess } = await import('../../core/instance/pm2-bridge.js');
111
+ const { getProcess, deleteProcess } = await import('../../core/instance/pm2-bridge.js');
112
112
  const existingProc = await getProcess(botName);
113
113
 
114
- let result;
115
- if (existingProc && existingProc.status !== 'stopped') {
116
- // Process is already running or in errored state - restart it
117
- const { restartProcess } = await import('../../core/instance/pm2-bridge.js');
118
- result = await restartProcess(botName);
119
- } else {
120
- // Process doesn't exist or is stopped - start it
121
- result = await startProcess(scriptPath, botName, options);
114
+ // Always delete existing process before starting to ensure:
115
+ // 1. Fresh configuration (environment variables)
116
+ // 2. No duplicate instances
117
+ // 3. Clean state (no stale resurrected processes)
118
+ if (existingProc) {
119
+ await deleteProcess(botName);
122
120
  }
123
121
 
122
+ // Start with fresh configuration
123
+ const result = await startProcess(scriptPath, botName, options);
124
+
124
125
  if (!result.success) {
125
126
  return reply.code(400).send({
126
127
  error: result.error,
@@ -202,8 +203,37 @@ export async function registerOperationRoutes(fastify) {
202
203
  });
203
204
  }
204
205
 
206
+ // Normalize instance type
207
+ const normalizedType = normalizeInstanceType(instance.instanceType);
208
+
209
+ // Determine script path
210
+ let scriptPath;
211
+ const cwd = instance.projectPath;
212
+
213
+ switch (normalizedType) {
214
+ case 'bmad-plugin':
215
+ scriptPath = path.join(instance.projectPath, '_agent-bridge', 'src', 'bot.js');
216
+ break;
217
+ case 'simple-config':
218
+ default:
219
+ scriptPath = path.join(PACKAGE_ROOT, 'src', 'bot.js');
220
+ break;
221
+ }
222
+
205
223
  const botName = instance.botName || `bot-${name}`;
206
- const result = await restartProcess(botName);
224
+
225
+ // For restart, delete and start fresh to update env vars
226
+ const { deleteProcess, startProcess } = await import('../../core/instance/pm2-bridge.js');
227
+ await deleteProcess(botName);
228
+
229
+ const options = {
230
+ cwd,
231
+ env: {
232
+ CONFIG_PATH: instance.configPath
233
+ }
234
+ };
235
+
236
+ const result = await startProcess(scriptPath, botName, options);
207
237
 
208
238
  if (!result.success) {
209
239
  return reply.code(400).send({