agent-window 1.3.9 → 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.
- package/hooks/settings.json +67 -0
- package/install-bmad-automated.exp +91 -0
- package/install-bmad-interactive.sh +22 -0
- package/install-bmad.js +148 -0
- package/package.json +6 -20
- package/src/api/routes/instances.js +58 -15
- package/src/api/routes/operations.js +40 -10
- package/src/bmad/experts.js +165 -0
- package/src/bmad/formatter.js +238 -0
- package/src/bmad/index.js +10 -0
- package/src/bmad/nlp.js +189 -0
- package/src/bmad/participants.js +148 -0
- package/src/bot.js +252 -15
- package/src/core/config.js +18 -2
- package/src/core/instance/manager.js +59 -1
- package/src/core/mcp-sync.js +114 -0
- package/src/core/perf-monitor.js +1 -1
- package/src/core/platform/pm2-bridge.js +50 -24
- package/src/module-help.csv +4 -0
- package/src/module.yaml +46 -0
- package/web/dist/assets/{Dashboard-323Iwz70.css → Dashboard-Db69RRgS.css} +1 -1
- package/web/dist/assets/Dashboard-jlJe-uLN.js +1 -0
- package/web/dist/assets/{InstanceDetail-d8jMzT8_.js → InstanceDetail-BwYesO8h.js} +1 -1
- package/web/dist/assets/{Instances-B9UMgfY_.js → Instances-eF1JJARO.js} +1 -1
- package/web/dist/assets/{Settings-CxVYMUOR.js → Settings-BFnkGSaK.js} +1 -1
- package/web/dist/assets/{main-dB-FsGdD.js → main-D6Y4CFNn.js} +2 -2
- package/web/dist/index.html +1 -1
- package/web/dist/assets/Dashboard-CkSgP5p6.js +0 -1
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Configuration Sync Module
|
|
3
|
+
*
|
|
4
|
+
* Handles synchronization of MCP server configuration from host to container
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { readFileSync, writeFileSync, existsSync, unlinkSync } from 'fs';
|
|
8
|
+
import { join } from 'path';
|
|
9
|
+
import { homedir } from 'os';
|
|
10
|
+
import { execSync } from 'child_process';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Sync MCP configuration from host to container
|
|
14
|
+
*
|
|
15
|
+
* @param {string} containerName - Docker container name
|
|
16
|
+
* @param {string} pendingDir - Host pending directory path
|
|
17
|
+
* @param {string} containerPendingDir - Container pending directory path
|
|
18
|
+
* @param {number} timeout - Command timeout in milliseconds
|
|
19
|
+
* @returns {object} Sync result { success, servers, error }
|
|
20
|
+
*/
|
|
21
|
+
export function syncMCPConfig(containerName, pendingDir, containerPendingDir, timeout = 5000) {
|
|
22
|
+
const hostClaudeConfig = join(homedir(), '.claude.json');
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
// Check if host config exists
|
|
26
|
+
if (!existsSync(hostClaudeConfig)) {
|
|
27
|
+
return {
|
|
28
|
+
success: false,
|
|
29
|
+
servers: [],
|
|
30
|
+
reason: 'No host Claude config found'
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Read host config and extract mcpServers
|
|
35
|
+
const hostConfig = JSON.parse(readFileSync(hostClaudeConfig, 'utf-8'));
|
|
36
|
+
const mcpServers = hostConfig.mcpServers || {};
|
|
37
|
+
|
|
38
|
+
if (Object.keys(mcpServers).length === 0) {
|
|
39
|
+
return {
|
|
40
|
+
success: true,
|
|
41
|
+
servers: [],
|
|
42
|
+
reason: 'No MCP servers configured on host'
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const serverNames = Object.keys(mcpServers);
|
|
47
|
+
|
|
48
|
+
// Create sync script for container
|
|
49
|
+
const syncScript = `
|
|
50
|
+
const fs = require('fs');
|
|
51
|
+
const path = require('path');
|
|
52
|
+
const configPath = path.join(process.env.HOME, '.claude.json');
|
|
53
|
+
let config = {};
|
|
54
|
+
try {
|
|
55
|
+
const existing = fs.readFileSync(configPath, 'utf8');
|
|
56
|
+
config = JSON.parse(existing);
|
|
57
|
+
} catch (e) {}
|
|
58
|
+
config.mcpServers = ${JSON.stringify(mcpServers)};
|
|
59
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
60
|
+
console.log('MCP config synced: ${serverNames.join(', ')}');
|
|
61
|
+
`;
|
|
62
|
+
|
|
63
|
+
// Copy and run sync script in container
|
|
64
|
+
const tempScript = join(pendingDir, '.sync-mcp.js');
|
|
65
|
+
writeFileSync(tempScript, syncScript);
|
|
66
|
+
|
|
67
|
+
execSync(`docker exec ${containerName} node ${containerPendingDir}/.sync-mcp.js`, {
|
|
68
|
+
stdio: 'pipe',
|
|
69
|
+
timeout
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// Cleanup
|
|
73
|
+
unlinkSync(tempScript);
|
|
74
|
+
try {
|
|
75
|
+
execSync(`docker exec ${containerName} rm -f ${containerPendingDir}/.sync-mcp.js`, { stdio: 'ignore' });
|
|
76
|
+
} catch (e) {}
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
success: true,
|
|
80
|
+
servers: serverNames
|
|
81
|
+
};
|
|
82
|
+
} catch (e) {
|
|
83
|
+
return {
|
|
84
|
+
success: false,
|
|
85
|
+
servers: [],
|
|
86
|
+
error: e.message
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Sync MCP configuration with console logging (for bot startup)
|
|
93
|
+
*
|
|
94
|
+
* @param {string} containerName - Docker container name
|
|
95
|
+
* @param {string} pendingDir - Host pending directory path
|
|
96
|
+
* @param {string} containerPendingDir - Container pending directory path
|
|
97
|
+
* @param {number} timeout - Command timeout in milliseconds
|
|
98
|
+
*/
|
|
99
|
+
export function syncMCPConfigLogged(containerName, pendingDir, containerPendingDir, timeout = 5000) {
|
|
100
|
+
const result = syncMCPConfig(containerName, pendingDir, containerPendingDir, timeout);
|
|
101
|
+
|
|
102
|
+
if (result.success) {
|
|
103
|
+
if (result.servers.length > 0) {
|
|
104
|
+
console.log(`[MCP] Syncing ${result.servers.length} MCP servers to container...`);
|
|
105
|
+
console.log(`[MCP] Sync complete: ${result.servers.join(', ')}`);
|
|
106
|
+
} else {
|
|
107
|
+
console.log(`[MCP] ${result.reason || 'No MCP servers configured on host'}`);
|
|
108
|
+
}
|
|
109
|
+
} else {
|
|
110
|
+
console.error(`[MCP] Sync failed: ${result.error || result.reason}`);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return result;
|
|
114
|
+
}
|
package/src/core/perf-monitor.js
CHANGED
|
@@ -10,6 +10,9 @@
|
|
|
10
10
|
|
|
11
11
|
import { spawn } from 'child_process';
|
|
12
12
|
import { isWindows, isWSLAvailable } from './detector.js';
|
|
13
|
+
import { writeFileSync, unlinkSync, existsSync } from 'fs';
|
|
14
|
+
import { join } from 'path';
|
|
15
|
+
import { tmpdir } from 'os';
|
|
13
16
|
|
|
14
17
|
/**
|
|
15
18
|
* Execute PM2 command with platform abstraction
|
|
@@ -121,7 +124,10 @@ async function list(options = {}) {
|
|
|
121
124
|
let processes = JSON.parse(result.stdout || '[]');
|
|
122
125
|
|
|
123
126
|
// If list is empty but daemon is running, try resurrect
|
|
124
|
-
// This handles the case where
|
|
127
|
+
// This handles the case where:
|
|
128
|
+
// 1. PM2 daemon is running but dump file is out of sync
|
|
129
|
+
// 2. BMAD plugins started bots via other methods without pm2 save
|
|
130
|
+
// 3. Need to detect actual running processes for accurate status display
|
|
125
131
|
if (processes.length === 0 && await isDaemonRunning(options)) {
|
|
126
132
|
try {
|
|
127
133
|
await execPM2Command(['resurrect'], { ...options, silent: true, timeout: 5000 });
|
|
@@ -177,32 +183,52 @@ async function start(scriptPath, options = {}) {
|
|
|
177
183
|
args.push('--cwd', options.cwd);
|
|
178
184
|
}
|
|
179
185
|
|
|
180
|
-
// Environment variables
|
|
181
|
-
if (options.env) {
|
|
182
|
-
//
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
+
// Environment variables - use temporary ecosystem file for proper env support
|
|
187
|
+
if (options.env && Object.keys(options.env).length > 0) {
|
|
188
|
+
// Create temporary ecosystem config file
|
|
189
|
+
const ecosystemFile = join(tmpdir(), `pm2-${options.name || 'temp'}-${Date.now()}.config.js`);
|
|
190
|
+
const ecosystemConfig = {
|
|
191
|
+
apps: [{
|
|
192
|
+
name: options.name,
|
|
193
|
+
script: scriptPath,
|
|
194
|
+
cwd: options.cwd,
|
|
195
|
+
env: options.env,
|
|
196
|
+
autorestart: true,
|
|
197
|
+
max_restarts: 10,
|
|
198
|
+
min_uptime: 10000,
|
|
199
|
+
}]
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
writeFileSync(ecosystemFile, `module.exports = ${JSON.stringify(ecosystemConfig, null, 2)};`);
|
|
203
|
+
|
|
204
|
+
try {
|
|
205
|
+
// Start with ecosystem file
|
|
206
|
+
const result = await execPM2Command(['start', ecosystemFile], options);
|
|
207
|
+
// Clean up ecosystem file after a longer delay (PM2 needs time to read it)
|
|
208
|
+
setTimeout(() => {
|
|
209
|
+
try {
|
|
210
|
+
if (existsSync(ecosystemFile)) {
|
|
211
|
+
unlinkSync(ecosystemFile);
|
|
212
|
+
}
|
|
213
|
+
} catch (e) {
|
|
214
|
+
// Ignore cleanup errors
|
|
215
|
+
}
|
|
216
|
+
}, 30000); // 30 seconds
|
|
217
|
+
return result;
|
|
218
|
+
} catch (err) {
|
|
219
|
+
// Clean up on error
|
|
220
|
+
try {
|
|
221
|
+
if (existsSync(ecosystemFile)) {
|
|
222
|
+
unlinkSync(ecosystemFile);
|
|
223
|
+
}
|
|
224
|
+
} catch (e) {
|
|
225
|
+
// Ignore cleanup errors
|
|
226
|
+
}
|
|
227
|
+
throw err;
|
|
186
228
|
}
|
|
187
229
|
}
|
|
188
230
|
|
|
189
|
-
//
|
|
190
|
-
// These must be set via ecosystem config file or app configuration
|
|
191
|
-
// For now, we skip these to avoid errors
|
|
192
|
-
// Users can configure restart behavior in ecosystem.config.js
|
|
193
|
-
|
|
194
|
-
if (options.instances) {
|
|
195
|
-
args.push('-i', String(options.instances));
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
if (options.watch) {
|
|
199
|
-
args.push('--watch');
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
if (options.maxMemoryRestart) {
|
|
203
|
-
args.push('--max-memory-restart', options.maxMemoryRestart);
|
|
204
|
-
}
|
|
205
|
-
|
|
231
|
+
// No env vars, use simple start
|
|
206
232
|
return execPM2Command(args, options);
|
|
207
233
|
}
|
|
208
234
|
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
module,phase,name,code,sequence,workflow-file,command,required,agent,options,description,output-location,outputs
|
|
2
|
+
bmd,,Discord Setup,DS,10,_bmad/bmd/workflows/discord-setup.md,bmad_discord_setup,false,system,,Initial Discord bot setup and configuration,{output_folder}/discord-setup/,
|
|
3
|
+
bmd,,Channel Context,CC,20,_bmad/bmd/workflows/channel-context.md,bmad_channel_context,false,ux-designer,,Configure per-channel expert assignments and context,{output_folder}/channel-context/,
|
|
4
|
+
bmd,,Session Management,SM,30,_bmad/bmd/workflows/session-management.md,bmad_session_mgmt,false,pm,,Manage Discord conversation sessions and persistence,{output_folder}/sessions/,
|
package/src/module.yaml
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
code: bmd
|
|
2
|
+
name: "AgentWindow - Discord AI Meeting Room"
|
|
3
|
+
header: "Discord becomes your AI expert meeting room"
|
|
4
|
+
subheader: "AI-powered Discord bot platform for BMAD experts"
|
|
5
|
+
description: "BMAD 模块,将 Discord 转换为 AI 专家会议室。支持多专家协作、频道上下文隔离、Docker 沙箱代码执行"
|
|
6
|
+
default_selected: false
|
|
7
|
+
|
|
8
|
+
# Variables from Core Config inserted:
|
|
9
|
+
## user_name
|
|
10
|
+
## communication_language
|
|
11
|
+
## document_output_language
|
|
12
|
+
## output_folder
|
|
13
|
+
|
|
14
|
+
# AgentWindow Configuration
|
|
15
|
+
discord_bot_token:
|
|
16
|
+
prompt: "Enter your Discord Bot Token (from Discord Developer Portal)"
|
|
17
|
+
default: ""
|
|
18
|
+
result: "{value}"
|
|
19
|
+
sensitive: true
|
|
20
|
+
|
|
21
|
+
claude_oauth_token:
|
|
22
|
+
prompt: "Enter your Claude Code OAuth Token"
|
|
23
|
+
default: ""
|
|
24
|
+
result: "{value}"
|
|
25
|
+
sensitive: true
|
|
26
|
+
|
|
27
|
+
project_workspace:
|
|
28
|
+
prompt: "Which project directory should the AI agents work on?"
|
|
29
|
+
default: "{project-root}"
|
|
30
|
+
result: "{value}"
|
|
31
|
+
|
|
32
|
+
allowed_channels:
|
|
33
|
+
prompt: "Which Discord channels can use this bot? (comma-separated channel IDs, empty = all)"
|
|
34
|
+
default: ""
|
|
35
|
+
result: "{value}"
|
|
36
|
+
|
|
37
|
+
# Artifacts output
|
|
38
|
+
transcript_output:
|
|
39
|
+
prompt: "Where should Discord conversation transcripts be saved?"
|
|
40
|
+
default: "{output_folder}/transcripts"
|
|
41
|
+
result: "{project-root}/{value}"
|
|
42
|
+
|
|
43
|
+
session_data:
|
|
44
|
+
prompt: "Where should session data be stored?"
|
|
45
|
+
default: ".discord-sessions"
|
|
46
|
+
result: "{project-root}/{value}"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
.instance-card[data-v-6450d163]{height:100%;transition:all var(--aw-transition-base)}.instance-card[data-v-6450d163]:hover{transform:translateY(-2px)}.card-header[data-v-6450d163]{display:flex;justify-content:space-between;align-items:center;margin-bottom:16px}.header-left[data-v-6450d163]{display:flex;align-items:center;gap:12px}.header-left .instance-icon[data-v-6450d163]{display:flex;align-items:center;justify-content:center;width:40px;height:40px;background:var(--aw-bg-secondary);border-radius:var(--aw-radius-md);color:var(--aw-accent)}.header-left .instance-name[data-v-6450d163]{margin:0;font-size:15px;font-weight:600;color:var(--aw-text-primary);letter-spacing:-.01em}.header-left .instance-alias[data-v-6450d163]{font-size:12px;color:var(--aw-text-secondary)}.status-indicator[data-v-6450d163]{display:inline-flex;align-items:center;gap:6px;padding:4px 10px;border-radius:12px;font-size:12px;font-weight:500}.status-indicator .status-dot[data-v-6450d163]{width:6px;height:6px;border-radius:50%;background:currentColor}.status-indicator.online[data-v-6450d163]{background:#34c7591a;color:var(--aw-status-online)}.status-indicator.stopped[data-v-6450d163]{background:#8e8e931a;color:var(--aw-status-stopped)}.status-indicator.loading[data-v-6450d163]{background:#5c5c611a;color:var(--aw-status-stopped);animation:pulse-6450d163 1.5s ease-in-out infinite}.status-indicator.error[data-v-6450d163]{background:#ff3b301a;color:var(--aw-status-error)}.status-indicator.restarting[data-v-6450d163]{background:#ff95001a;color:var(--aw-status-restarting)}.status-indicator.degraded[data-v-6450d163]{background:#ff95001a;color:#ff9500}.status-indicator.warning[data-v-6450d163]{background:#ffcc001a;color:#fc0}@keyframes pulse-6450d163{0%,to{opacity:1}50%{opacity:.5}}.card-body[data-v-6450d163]{display:flex;flex-direction:column;gap:12px;margin-bottom:16px}.info-row[data-v-6450d163]{display:flex;justify-content:space-between;align-items:center}.info-row .label[data-v-6450d163]{font-size:12px;color:var(--aw-text-secondary)}.info-row .value[data-v-6450d163]{font-size:12px;font-family:SF Mono,Monaco,Cascadia Code,monospace;color:var(--aw-text-primary)}.info-row .value.instance-type[data-v-6450d163]{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;font-weight:500;padding:2px 8px;border-radius:4px;font-size:11px}.info-row .value.instance-type.type-bmad-plugin[data-v-6450d163]{background:#34c75926;color:#34c759}.info-row .value.instance-type.type-simple-config[data-v-6450d163]{background:#5e5ce626;color:#5e5ce6}.info-row .value.instance-type.type-bmad-plugin[data-v-6450d163]{background:#0984e326;color:#0984e3}.stats-row[data-v-6450d163]{display:flex;justify-content:space-around;padding:12px 0;border-top:1px solid var(--aw-bg-tertiary);border-bottom:1px solid var(--aw-bg-tertiary)}.stat[data-v-6450d163]{display:flex;flex-direction:column;align-items:center;gap:4px}.stat .stat-label[data-v-6450d163]{font-size:10px;color:var(--aw-text-secondary);text-transform:uppercase;letter-spacing:.05em}.stat .stat-value[data-v-6450d163]{font-size:14px;font-weight:600;color:var(--aw-text-primary)}.tags-row[data-v-6450d163]{display:flex;gap:6px;flex-wrap:wrap}.tags-row .tag[data-v-6450d163]{padding:3px 8px;font-size:11px;font-weight:500;background:var(--aw-bg-secondary);color:var(--aw-text-secondary);border-radius:6px}.card-actions[data-v-6450d163]{display:flex;justify-content:space-between;align-items:center;padding-top:12px;border-top:1px solid var(--aw-bg-tertiary)}.action-buttons[data-v-6450d163]{display:flex;gap:4px}.action-btn[data-v-6450d163]{display:flex;align-items:center;justify-content:center;width:36px;height:36px;border:none;background:transparent;border-radius:var(--aw-radius-sm);color:var(--aw-text-secondary);cursor:pointer;transition:all var(--aw-transition-fast)}.action-btn[data-v-6450d163]:hover:not(:disabled){background:var(--aw-bg-secondary);color:var(--aw-text-primary)}.action-btn[data-v-6450d163]:disabled{opacity:.4;cursor:not-allowed}.action-btn[data-v-6450d163]:active:not(:disabled){transform:scale(.95)}.details-btn[data-v-6450d163]{padding:8px 14px;font-size:13px;font-weight:500;color:var(--aw-accent);background:transparent;border:none;border-radius:var(--aw-radius-sm);cursor:pointer;transition:background var(--aw-transition-fast)}.details-btn[data-v-6450d163]:hover{background:#0071e31a}.dashboard-view[data-v-
|
|
1
|
+
.instance-card[data-v-6450d163]{height:100%;transition:all var(--aw-transition-base)}.instance-card[data-v-6450d163]:hover{transform:translateY(-2px)}.card-header[data-v-6450d163]{display:flex;justify-content:space-between;align-items:center;margin-bottom:16px}.header-left[data-v-6450d163]{display:flex;align-items:center;gap:12px}.header-left .instance-icon[data-v-6450d163]{display:flex;align-items:center;justify-content:center;width:40px;height:40px;background:var(--aw-bg-secondary);border-radius:var(--aw-radius-md);color:var(--aw-accent)}.header-left .instance-name[data-v-6450d163]{margin:0;font-size:15px;font-weight:600;color:var(--aw-text-primary);letter-spacing:-.01em}.header-left .instance-alias[data-v-6450d163]{font-size:12px;color:var(--aw-text-secondary)}.status-indicator[data-v-6450d163]{display:inline-flex;align-items:center;gap:6px;padding:4px 10px;border-radius:12px;font-size:12px;font-weight:500}.status-indicator .status-dot[data-v-6450d163]{width:6px;height:6px;border-radius:50%;background:currentColor}.status-indicator.online[data-v-6450d163]{background:#34c7591a;color:var(--aw-status-online)}.status-indicator.stopped[data-v-6450d163]{background:#8e8e931a;color:var(--aw-status-stopped)}.status-indicator.loading[data-v-6450d163]{background:#5c5c611a;color:var(--aw-status-stopped);animation:pulse-6450d163 1.5s ease-in-out infinite}.status-indicator.error[data-v-6450d163]{background:#ff3b301a;color:var(--aw-status-error)}.status-indicator.restarting[data-v-6450d163]{background:#ff95001a;color:var(--aw-status-restarting)}.status-indicator.degraded[data-v-6450d163]{background:#ff95001a;color:#ff9500}.status-indicator.warning[data-v-6450d163]{background:#ffcc001a;color:#fc0}@keyframes pulse-6450d163{0%,to{opacity:1}50%{opacity:.5}}.card-body[data-v-6450d163]{display:flex;flex-direction:column;gap:12px;margin-bottom:16px}.info-row[data-v-6450d163]{display:flex;justify-content:space-between;align-items:center}.info-row .label[data-v-6450d163]{font-size:12px;color:var(--aw-text-secondary)}.info-row .value[data-v-6450d163]{font-size:12px;font-family:SF Mono,Monaco,Cascadia Code,monospace;color:var(--aw-text-primary)}.info-row .value.instance-type[data-v-6450d163]{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;font-weight:500;padding:2px 8px;border-radius:4px;font-size:11px}.info-row .value.instance-type.type-bmad-plugin[data-v-6450d163]{background:#34c75926;color:#34c759}.info-row .value.instance-type.type-simple-config[data-v-6450d163]{background:#5e5ce626;color:#5e5ce6}.info-row .value.instance-type.type-bmad-plugin[data-v-6450d163]{background:#0984e326;color:#0984e3}.stats-row[data-v-6450d163]{display:flex;justify-content:space-around;padding:12px 0;border-top:1px solid var(--aw-bg-tertiary);border-bottom:1px solid var(--aw-bg-tertiary)}.stat[data-v-6450d163]{display:flex;flex-direction:column;align-items:center;gap:4px}.stat .stat-label[data-v-6450d163]{font-size:10px;color:var(--aw-text-secondary);text-transform:uppercase;letter-spacing:.05em}.stat .stat-value[data-v-6450d163]{font-size:14px;font-weight:600;color:var(--aw-text-primary)}.tags-row[data-v-6450d163]{display:flex;gap:6px;flex-wrap:wrap}.tags-row .tag[data-v-6450d163]{padding:3px 8px;font-size:11px;font-weight:500;background:var(--aw-bg-secondary);color:var(--aw-text-secondary);border-radius:6px}.card-actions[data-v-6450d163]{display:flex;justify-content:space-between;align-items:center;padding-top:12px;border-top:1px solid var(--aw-bg-tertiary)}.action-buttons[data-v-6450d163]{display:flex;gap:4px}.action-btn[data-v-6450d163]{display:flex;align-items:center;justify-content:center;width:36px;height:36px;border:none;background:transparent;border-radius:var(--aw-radius-sm);color:var(--aw-text-secondary);cursor:pointer;transition:all var(--aw-transition-fast)}.action-btn[data-v-6450d163]:hover:not(:disabled){background:var(--aw-bg-secondary);color:var(--aw-text-primary)}.action-btn[data-v-6450d163]:disabled{opacity:.4;cursor:not-allowed}.action-btn[data-v-6450d163]:active:not(:disabled){transform:scale(.95)}.details-btn[data-v-6450d163]{padding:8px 14px;font-size:13px;font-weight:500;color:var(--aw-accent);background:transparent;border:none;border-radius:var(--aw-radius-sm);cursor:pointer;transition:background var(--aw-transition-fast)}.details-btn[data-v-6450d163]:hover{background:#0071e31a}.dashboard-view[data-v-221ba7f2]{display:flex;flex-direction:column;gap:24px}.dashboard-header[data-v-221ba7f2]{display:flex;justify-content:space-between;align-items:flex-start}.dashboard-header .header-actions[data-v-221ba7f2]{display:flex;gap:12px}.dashboard-header h1[data-v-221ba7f2]{margin:0;font-size:28px;font-weight:600}.dashboard-header .subtitle[data-v-221ba7f2]{margin:4px 0 0;color:var(--el-text-color-secondary)}.discover-info[data-v-221ba7f2]{padding:0 0 16px;color:var(--el-text-color-secondary);font-size:14px}.empty-discovered[data-v-221ba7f2]{padding:40px 0;text-align:center;color:var(--el-text-color-secondary)}.stats-row .stat-card[data-v-221ba7f2]{background:linear-gradient(135deg,var(--el-bg-color) 0%,var(--el-bg-color-page) 100%)}.stats-row .stat-card.success[data-v-221ba7f2]{border-left:3px solid var(--aw-success)}.stats-row .stat-card.warning[data-v-221ba7f2]{border-left:3px solid var(--aw-warning)}.stats-row .stat-card.danger[data-v-221ba7f2]{border-left:3px solid var(--aw-danger)}.stats-row .stat-content[data-v-221ba7f2]{display:flex;align-items:center;gap:16px}.stats-row .stat-content .stat-icon[data-v-221ba7f2]{display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;color:var(--el-text-color-regular)}.stats-row .stat-content .stat-icon svg[data-v-221ba7f2]{width:24px;height:24px}.stats-row .stat-content .stat-info[data-v-221ba7f2]{display:flex;flex-direction:column}.stats-row .stat-content .stat-info .stat-value[data-v-221ba7f2]{font-size:24px;font-weight:600;line-height:1}.stats-row .stat-content .stat-info .stat-label[data-v-221ba7f2]{font-size:12px;color:var(--el-text-color-secondary)}.loading-state[data-v-221ba7f2]{padding:40px 0}.empty-state[data-v-221ba7f2]{display:flex;flex-direction:column;align-items:center;gap:16px;padding:80px 0}.empty-state .empty-icon[data-v-221ba7f2]{display:inline-flex;align-items:center;justify-content:center;width:64px;height:64px;opacity:.5}.empty-state .empty-icon svg[data-v-221ba7f2]{width:64px;height:64px}.empty-state h3[data-v-221ba7f2]{margin:0;font-size:20px}.empty-state p[data-v-221ba7f2]{margin:0;color:var(--el-text-color-secondary)}.instances-grid [class*=el-col][data-v-221ba7f2]{margin-bottom:16px}.form-hint[data-v-221ba7f2]{font-size:12px;color:var(--el-text-color-secondary);margin-top:4px}.dialog-footer[data-v-221ba7f2]{display:flex;justify-content:space-between;align-items:center;width:100%}.dialog-footer .footer-left[data-v-221ba7f2]{display:flex;align-items:center;gap:12px}.dialog-footer .footer-right[data-v-221ba7f2]{display:flex;gap:8px}.validation-summary[data-v-221ba7f2]{display:flex;align-items:center}.check-item .check-name[data-v-221ba7f2]{font-weight:600;margin-bottom:4px}.check-item .check-message[data-v-221ba7f2]{font-size:13px;color:var(--el-text-color-secondary)}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{aA as Ne,j as re,ab as p,y as d,z as C,D as a,E as t,R as u,G as oe,B as y,P as R,J as G,a5 as Q,c as w,r as f,Q as h,u as J,C as s,aw as Te,am as Ve}from"./vue-vendor-CGSlMM3Y.js";import{d as $e,p as ie,r as De}from"./element-plus-CSm40ime.js";import{a as x,u as de}from"./main-D6Y4CFNn.js";import{_ as ue}from"./_plugin-vue_export-helper-DlAUqK2U.js";const Ie={class:"card-header"},Pe={class:"header-left"},je={class:"instance-info"},Ae={class:"instance-name"},Me={class:"instance-alias"},Re={class:"status-label"},Be={class:"card-body"},Ee={class:"info-row"},Se={class:"info-row"},Ue={class:"value"},Oe={key:0,class:"stats-row"},Fe={class:"stat"},Le={class:"stat-value"},qe={class:"stat"},ze={class:"stat-value"},He={key:0,class:"stat"},Ke={class:"stat-value"},We={key:1,class:"tags-row"},Je={class:"card-actions"},Ge={class:"action-buttons"},Qe=["disabled"],Ye=["disabled"],Xe=["disabled"],Ze={__name:"InstanceCard",props:{instance:{type:Object,required:!0}},setup(I,{expose:O}){const v=I,T=Ne(),{success:P,error:_}=de(),c=f({status:"loading",exists:!1,memory:0,cpu:0,uptime:0}),B=f(null),j=f(!1),E=w(()=>{const o=c.value.status,n=c.value.health;return o==="loading"?"loading":o==="error"||o==="errored"?"error":(n==null?void 0:n.overall)==="degraded"?"degraded":(n==null?void 0:n.overall)==="error"?"error":(n==null?void 0:n.overall)==="healthy"&&(o==="running"||o==="online")?"online":o==="degraded"?"degraded":o==="running"||o==="online"?"online":o==="stopped"?"stopped":o==="restarting"?"restarting":"stopped"}),S=w(()=>{const o=c.value.status,n=c.value.health;return o==="loading"?"Loading...":(n==null?void 0:n.overall)==="degraded"?"Degraded (Docker Down)":(n==null?void 0:n.overall)==="error"?"Error":{running:"Running",online:"Running",degraded:"Degraded (Docker Down)",stopped:"Stopped",error:"Error",errored:"Error",restarting:"Restarting"}[o]||o||"Unknown"}),g=w(()=>{const o=c.value.status;return o==="running"||o==="online"||o==="degraded"}),A=w(()=>{const o=v.instance.projectPath;return o.length>35?"..."+o.slice(-32):o}),N=w(()=>({"bmad-plugin":"BMAD 插件","simple-config":"基础版"})[v.instance.instanceType]||"基础版"),F=w(()=>`type-${v.instance.instanceType}`);async function k(){if(!j.value){j.value=!0;try{const o=await x.getInstanceStatus(v.instance.name);o&&o.status&&(c.value=o,B.value=o)}catch(o){B.value?console.debug("[InstanceCard] API error, using cached status:",o.message):console.debug("[InstanceCard] Failed to load initial status:",o.message)}finally{j.value=!1}}}async function M(){try{await x.startInstance(v.instance.name),P("Started",`${v.instance.name} has been started`),await k()}catch(o){_("Failed to start",o.message)}}async function i(){try{await x.stopInstance(v.instance.name),P("Stopped",`${v.instance.name} has been stopped`),await k()}catch(o){_("Failed to stop",o.message)}}async function Y(){try{await x.restartInstance(v.instance.name),P("Restarted",`${v.instance.name} has been restarted`),await k()}catch(o){_("Failed to restart",o.message)}}function z(){T.push(`/instances/${v.instance.name}`)}function X(o){const n=o/1024/1024;return n>=1024?(n/1024).toFixed(1)+" GB":Math.round(n)+" MB"}function Z(o){if(!o)return"-";const n=Math.floor((Date.now()-o)/1e3);return n<60?`${n}s`:n<3600?`${Math.floor(n/60)}m`:n<86400?`${Math.floor(n/3600)}h`:`${Math.floor(n/86400)}d`}return re(()=>{k();const o=setInterval(k,1e4);return()=>clearInterval(o)}),O({fetchStatus:k}),(o,n)=>{const H=p("el-card");return d(),C(H,{class:"instance-card"},{default:a(()=>{var U;return[t("div",Ie,[t("div",Pe,[n[0]||(n[0]=t("div",{class:"instance-icon"},[t("svg",{width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"1.5"},[t("rect",{x:"3",y:"3",width:"18",height:"18",rx:"4"}),t("circle",{cx:"12",cy:"12",r:"3"})])],-1)),t("div",je,[t("h3",Ae,u(I.instance.displayName||I.instance.name),1),t("span",Me,u(I.instance.name),1)])]),t("div",{class:oe(["status-indicator",E.value])},[n[1]||(n[1]=t("span",{class:"status-dot"},null,-1)),t("span",Re,u(S.value),1)],2)]),t("div",Be,[t("div",Ee,[n[2]||(n[2]=t("span",{class:"label"},"Type",-1)),t("span",{class:oe(["value instance-type",F.value])},u(N.value),3)]),t("div",Se,[n[3]||(n[3]=t("span",{class:"label"},"Path",-1)),t("span",Ue,u(A.value),1)]),c.value.exists?(d(),y("div",Oe,[t("div",Fe,[n[4]||(n[4]=t("span",{class:"stat-label"},"Memory",-1)),t("span",Le,u(X(c.value.memory)),1)]),t("div",qe,[n[5]||(n[5]=t("span",{class:"stat-label"},"CPU",-1)),t("span",ze,u(c.value.cpu)+"%",1)]),c.value.status==="online"?(d(),y("div",He,[n[6]||(n[6]=t("span",{class:"stat-label"},"Uptime",-1)),t("span",Ke,u(Z(c.value.uptime)),1)])):R("",!0)])):R("",!0),(U=I.instance.tags)!=null&&U.length?(d(),y("div",We,[(d(!0),y(G,null,Q(I.instance.tags,L=>(d(),y("span",{key:L,class:"tag"},u(L),1))),128))])):R("",!0)]),t("div",Je,[t("div",Ge,[t("button",{class:"action-btn",disabled:g.value||c.value.status==="loading",title:"Start",onClick:M},[...n[7]||(n[7]=[t("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2"},[t("polygon",{points:"5 3 19 12 5 21 5 3"})],-1)])],8,Qe),t("button",{class:"action-btn",disabled:!g.value||c.value.status==="loading",title:"Stop",onClick:i},[...n[8]||(n[8]=[t("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2"},[t("rect",{x:"6",y:"4",width:"4",height:"16"}),t("rect",{x:"14",y:"4",width:"4",height:"16"})],-1)])],8,Ye),t("button",{class:"action-btn",disabled:c.value.status==="loading",title:"Restart",onClick:Y},[...n[9]||(n[9]=[t("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2"},[t("polyline",{points:"23 4 23 10 17 10"}),t("polyline",{points:"1 20 1 14 7 14"}),t("path",{d:"M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"})],-1)])],8,Xe)]),t("button",{class:"details-btn",onClick:z}," Details ")])]}),_:1})}}},et=ue(Ze,[["__scopeId","data-v-6450d163"]]),tt={class:"dashboard-view"},at={class:"dashboard-header"},st={class:"header-actions"},nt={class:"stat-content"},lt={class:"stat-info"},ot={class:"stat-value"},it={class:"stat-content"},rt={class:"stat-info"},dt={class:"stat-value"},ut={class:"stat-content"},ct={class:"stat-info"},pt={class:"stat-value"},vt={class:"stat-content"},mt={class:"stat-info"},ft={class:"stat-value"},gt={key:0,class:"loading-state"},ht={key:1,class:"empty-state"},yt={key:0,class:"loading-state"},wt={key:1,class:"empty-discovered"},_t={style:{display:"flex","align-items":"center",gap:"8px"}},kt={class:"dialog-footer"},bt={class:"footer-left"},Ct={key:0,class:"validation-summary"},xt={class:"footer-right"},Nt={key:0},Tt={class:"check-item"},Vt={class:"check-name"},$t={class:"check-message"},Dt={__name:"Dashboard",setup(I){const{success:O,error:v}=de(),T=f([]),P=f(!0),_=f(!1),c=f(!1),B=f(!1),j=f(!1),E=f(null),S=f(!1),g=f(null),A=f([]),N=f([]),F=f(!1),k=f(null),M=f([]),i=f({name:"",displayName:"",projectPath:"",botToken:"",oauthToken:"",allowedChannels:"",containerName:"",tagsInput:""}),Y={name:[{required:!0,message:"Name is required"},{pattern:/^[a-z0-9-]+$/,message:"Only lowercase letters, numbers, and hyphens"}],projectPath:[{required:!0,message:"Project path is required"}],botToken:[{required:!0,message:"Discord Bot Token is required"}],oauthToken:[{required:!0,message:"Claude OAuth Token is required"},{pattern:/^sk-ant-/,message:"Token must start with sk-ant-"}],allowedChannels:[{required:!0,message:"Allowed Channels is required"}]},z=w(()=>T.value.filter(r=>r.enabled).length),X=w(()=>T.value.length-z.value),Z=w(()=>0),o=w(()=>N.value.length>0),n=w(()=>N.value.length),H=w(()=>g.value?g.value.checks.filter(r=>r.status==="passed"):[]);async function U(){P.value=!0;try{T.value=await x.getInstances(),await L()}catch(r){v("Failed to load",r.message)}finally{P.value=!1}}async function L(){try{const r=await x.discoverInstances();N.value=r.discovered||[]}catch{N.value=[]}}async function ce(){F.value=!0;try{await L()}catch(r){v("Discovery failed",r.message)}finally{F.value=!1}}async function pe(r){k.value=r.name;try{await x.importInstance({name:r.name,botName:r.botName,displayName:r.displayName,projectPath:r.projectPath}),M.value.push(r.name),O("Imported",`Instance "${r.displayName}" has been imported`),await U(),M.value.length>=N.value.length&&(c.value=!1,M.value=[])}catch(e){v("Import failed",e.message)}finally{k.value=null}}async function te(){var e;if(await((e=E.value)==null?void 0:e.validate().catch(()=>!1))){B.value=!0;try{const m=i.value.tagsInput?i.value.tagsInput.split(",").map(K=>K.trim()).filter(Boolean):[],V=i.value.containerName||`bot-${i.value.name}`,b={BOT_TOKEN:i.value.botToken,CLAUDE_CODE_OAUTH_TOKEN:i.value.oauthToken,PROJECT_DIR:i.value.projectPath,ALLOWED_CHANNELS:i.value.allowedChannels,workspace:{containerName:V}};await x.addInstance({name:i.value.name,displayName:i.value.displayName||i.value.name,projectPath:i.value.projectPath,tags:m,config:b,createConfig:!0,instanceType:"simple-config"}),O("Added",`Instance "${i.value.name}" has been added`),_.value=!1,se(),await U()}catch(m){v("Failed to add",m.message)}finally{B.value=!1}}}function ae(){_.value=!1,se()}function se(){var r;i.value={name:"",displayName:"",projectPath:"",botToken:"",oauthToken:"",allowedChannels:"",containerName:"",tagsInput:""},(r=E.value)==null||r.clearValidate(),g.value=null}async function ve(r){if(r&&A.value.length===0)try{const e=await x.getClaudeTokens();e.success&&(A.value=e.tokens||[])}catch(e){console.error("Failed to load tokens:",e),A.value=[]}}function me(r){i.value.oauthToken=r.token,O("Token Copied",`Claude token from "${r.displayName}" has been applied`)}async function fe(){var e;if(!await((e=E.value)==null?void 0:e.validate().catch(()=>!1))){v("Validation Failed","Please fix form errors first");return}j.value=!0;try{const m=i.value.containerName||`bot-${i.value.name}`,V={BOT_TOKEN:i.value.botToken,CLAUDE_CODE_OAUTH_TOKEN:i.value.oauthToken,PROJECT_DIR:i.value.projectPath,ALLOWED_CHANNELS:i.value.allowedChannels,workspace:{containerName:m}},b=await x.validateConfig({config:V,projectPath:i.value.projectPath});g.value=b,S.value=!0,b.success||v("Validation Failed","Some checks did not pass. Please review the results.")}catch(m){v("Validation Error",m.message)}finally{j.value=!1}}return re(()=>{U()}),(r,e)=>{const m=p("el-button"),V=p("el-card"),b=p("el-col"),K=p("el-row"),ne=p("el-skeleton"),q=p("el-table-column"),W=p("el-tag"),ge=p("el-table"),ee=p("el-dialog"),$=p("el-input"),D=p("el-form-item"),he=p("el-divider"),le=p("el-dropdown-item"),ye=p("el-dropdown-menu"),we=p("el-dropdown"),_e=p("el-form"),ke=p("el-alert"),be=p("el-timeline-item"),Ce=p("el-timeline");return d(),y("div",tt,[t("div",at,[e[17]||(e[17]=t("div",null,[t("h1",null,"Dashboard"),t("p",{class:"subtitle"},"Manage your AgentWindow bot instances")],-1)),t("div",st,[o.value?(d(),C(m,{key:0,type:"info",icon:J($e),onClick:e[0]||(e[0]=l=>c.value=!0)},{default:a(()=>[h(" Import "+u(n.value)+" Running ",1)]),_:1},8,["icon"])):R("",!0),s(m,{type:"primary",icon:J(ie),onClick:e[1]||(e[1]=l=>_.value=!0)},{default:a(()=>[...e[16]||(e[16]=[h(" Add Instance ",-1)])]),_:1},8,["icon"])])]),s(K,{gutter:16,class:"stats-row"},{default:a(()=>[s(b,{xs:12,sm:6},{default:a(()=>[s(V,{class:"stat-card"},{default:a(()=>[t("div",nt,[e[19]||(e[19]=t("span",{class:"stat-icon"},[t("svg",{width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg"},[t("rect",{x:"3",y:"3",width:"18",height:"18",rx:"2",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"}),t("path",{d:"M8 12H16M12 8V16",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"})])],-1)),t("div",lt,[t("span",ot,u(T.value.length),1),e[18]||(e[18]=t("span",{class:"stat-label"},"Total",-1))])])]),_:1})]),_:1}),s(b,{xs:12,sm:6},{default:a(()=>[s(V,{class:"stat-card success"},{default:a(()=>[t("div",it,[e[21]||(e[21]=t("span",{class:"stat-icon"},[t("svg",{width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg"},[t("circle",{cx:"12",cy:"12",r:"8",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"}),t("circle",{cx:"12",cy:"12",r:"3",fill:"currentColor"})])],-1)),t("div",rt,[t("span",dt,u(z.value),1),e[20]||(e[20]=t("span",{class:"stat-label"},"Running",-1))])])]),_:1})]),_:1}),s(b,{xs:12,sm:6},{default:a(()=>[s(V,{class:"stat-card warning"},{default:a(()=>[t("div",ut,[e[23]||(e[23]=t("span",{class:"stat-icon"},[t("svg",{width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg"},[t("rect",{x:"6",y:"6",width:"12",height:"12",rx:"1",fill:"currentColor"})])],-1)),t("div",ct,[t("span",pt,u(X.value),1),e[22]||(e[22]=t("span",{class:"stat-label"},"Stopped",-1))])])]),_:1})]),_:1}),s(b,{xs:12,sm:6},{default:a(()=>[s(V,{class:"stat-card danger"},{default:a(()=>[t("div",vt,[e[25]||(e[25]=t("span",{class:"stat-icon"},[t("svg",{width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg"},[t("path",{d:"M12 9V12M12 16H12.01M5.29289 5.29289C2.99071 7.59508 2.19023 11.0184 3.27489 14.1236C4.35955 17.2288 7.19773 19.3613 10.4872 19.8428C13.7766 20.3242 17.0854 19.0828 19.0841 16.5841C21.0828 14.0854 21.4793 10.6367 20.1277 7.74488C18.7761 4.85303 15.8963 3.01887 12.7108 3.09219C9.52524 3.16552 6.73669 5.13405 5.51838 8.08105",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"})])],-1)),t("div",mt,[t("span",ft,u(Z.value),1),e[24]||(e[24]=t("span",{class:"stat-label"},"Errors",-1))])])]),_:1})]),_:1})]),_:1}),P.value?(d(),y("div",gt,[s(ne,{rows:3,animated:""})])):T.value.length===0?(d(),y("div",ht,[e[27]||(e[27]=Te('<div class="empty-icon" data-v-221ba7f2><svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg" data-v-221ba7f2><rect x="8" y="8" width="48" height="48" rx="4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="0.2" data-v-221ba7f2></rect><rect x="16" y="16" width="16" height="16" rx="2" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="0.3" data-v-221ba7f2></rect><path d="M32 32L48 48" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="0.2" data-v-221ba7f2></path><circle cx="48" cy="16" r="3" fill="currentColor" fill-opacity="0.2" data-v-221ba7f2></circle></svg></div><h3 data-v-221ba7f2>No instances yet</h3><p data-v-221ba7f2>Add your first AgentWindow bot instance to get started</p>',3)),s(m,{type:"primary",icon:J(ie),onClick:e[2]||(e[2]=l=>_.value=!0)},{default:a(()=>[...e[26]||(e[26]=[h(" Add Instance ",-1)])]),_:1},8,["icon"])])):(d(),C(K,{key:2,gutter:16,class:"instances-grid"},{default:a(()=>[(d(!0),y(G,null,Q(T.value,l=>(d(),C(b,{key:l.name,xs:24,sm:12,lg:8},{default:a(()=>[s(et,{instance:l},null,8,["instance"])]),_:2},1024))),128))]),_:1})),s(ee,{modelValue:c.value,"onUpdate:modelValue":e[4]||(e[4]=l=>c.value=l),title:"Import Running Instances",width:"600px"},{footer:a(()=>[s(m,{onClick:e[3]||(e[3]=l=>c.value=!1)},{default:a(()=>[...e[30]||(e[30]=[h("Close",-1)])]),_:1}),s(m,{type:"primary",icon:J(De),onClick:ce},{default:a(()=>[...e[31]||(e[31]=[h("Refresh",-1)])]),_:1},8,["icon"])]),default:a(()=>[e[32]||(e[32]=t("div",{class:"discover-info"},[t("p",null,"The following bot instances are running in PM2 but not yet registered:")],-1)),F.value?(d(),y("div",yt,[s(ne,{rows:2,animated:""})])):N.value.length===0?(d(),y("div",wt,[...e[28]||(e[28]=[t("p",null,"No unregistered instances found.",-1)])])):(d(),C(ge,{key:2,data:N.value,stripe:"",style:{width:"100%"}},{default:a(()=>[s(q,{prop:"displayName",label:"Name",width:"140"}),s(q,{prop:"botName",label:"PM2 Name",width:"130"}),s(q,{label:"Status",width:"90"},{default:a(({row:l})=>[l.isRunning?(d(),C(W,{key:0,type:"success",size:"small"},{default:a(()=>[...e[29]||(e[29]=[h("Running",-1)])]),_:1})):(d(),C(W,{key:1,type:"info",size:"small"},{default:a(()=>[h(u(l.status),1)]),_:2},1024))]),_:1}),s(q,{prop:"projectPath",label:"Path","show-overflow-tooltip":""}),s(q,{label:"Action",width:"80",align:"center"},{default:a(({row:l})=>[s(m,{type:"primary",size:"small",loading:k.value===l.name,disabled:M.value.includes(l.name),onClick:xe=>pe(l)},{default:a(()=>[h(u(M.value.includes(l.name)?"Done":"Import"),1)]),_:2},1032,["loading","disabled","onClick"])]),_:1})]),_:1},8,["data"]))]),_:1},8,["modelValue"]),s(ee,{modelValue:_.value,"onUpdate:modelValue":e[13]||(e[13]=l=>_.value=l),title:"Add Instance",width:"500px","before-close":ae},{footer:a(()=>[t("div",kt,[t("div",bt,[s(m,{loading:j.value,onClick:fe},{default:a(()=>[...e[39]||(e[39]=[h(" Test Config ",-1)])]),_:1},8,["loading"]),g.value?(d(),y("div",Ct,[s(W,{type:g.value.success?"success":"danger",size:"small"},{default:a(()=>[h(u(g.value.success?"Ready":"Issues Found"),1)]),_:1},8,["type"])])):R("",!0)]),t("div",xt,[s(m,{onClick:ae},{default:a(()=>[...e[40]||(e[40]=[h("Cancel",-1)])]),_:1}),s(m,{type:"primary",loading:B.value,disabled:g.value&&!g.value.success,onClick:te},{default:a(()=>[...e[41]||(e[41]=[h(" Add Instance ",-1)])]),_:1},8,["loading","disabled"])])])]),default:a(()=>[s(_e,{ref_key:"formRef",ref:E,model:i.value,rules:Y,"label-width":"100px"},{default:a(()=>[s(D,{label:"Name",prop:"name"},{default:a(()=>[s($,{modelValue:i.value.name,"onUpdate:modelValue":e[5]||(e[5]=l=>i.value.name=l),placeholder:"my-bot",onKeyup:Ve(te,["enter"])},null,8,["modelValue"])]),_:1}),s(D,{label:"Display Name",prop:"displayName"},{default:a(()=>[s($,{modelValue:i.value.displayName,"onUpdate:modelValue":e[6]||(e[6]=l=>i.value.displayName=l),placeholder:"My Bot"},null,8,["modelValue"])]),_:1}),s(D,{label:"Project Path",prop:"projectPath"},{default:a(()=>[s($,{modelValue:i.value.projectPath,"onUpdate:modelValue":e[7]||(e[7]=l=>i.value.projectPath=l),placeholder:"/path/to/project"},null,8,["modelValue"]),e[33]||(e[33]=t("div",{class:"form-hint"},"Directory where bot config will be stored",-1))]),_:1}),s(he,{"content-position":"left"},{default:a(()=>[...e[34]||(e[34]=[h("Bot Configuration",-1)])]),_:1}),s(D,{label:"Discord Bot Token",prop:"botToken"},{default:a(()=>[s($,{modelValue:i.value.botToken,"onUpdate:modelValue":e[8]||(e[8]=l=>i.value.botToken=l),type:"password",placeholder:"Your Discord bot token","show-password":""},null,8,["modelValue"])]),_:1}),s(D,{label:"Claude OAuth Token",prop:"oauthToken"},{default:a(()=>[s($,{modelValue:i.value.oauthToken,"onUpdate:modelValue":e[9]||(e[9]=l=>i.value.oauthToken=l),type:"password",placeholder:"sk-ant-...","show-password":""},{append:a(()=>[s(we,{trigger:"click",onVisibleChange:ve},{dropdown:a(()=>[s(ye,null,{default:a(()=>[A.value.length===0?(d(),C(le,{key:0,disabled:""},{default:a(()=>[...e[36]||(e[36]=[h(" No tokens available ",-1)])]),_:1})):R("",!0),(d(!0),y(G,null,Q(A.value,l=>(d(),C(le,{key:l.instanceName,onClick:xe=>me(l)},{default:a(()=>[t("div",_t,[t("span",null,u(l.displayName),1),s(W,{size:"small",type:"info"},{default:a(()=>[h(u(l.maskedToken),1)]),_:2},1024)])]),_:2},1032,["onClick"]))),128))]),_:1})]),default:a(()=>[s(m,null,{default:a(()=>[...e[35]||(e[35]=[h(" Copy from... ",-1)])]),_:1})]),_:1})]),_:1},8,["modelValue"]),e[37]||(e[37]=t("div",{class:"form-hint"},"Reuse token from existing instances",-1))]),_:1}),s(D,{label:"Allowed Channels",prop:"allowedChannels"},{default:a(()=>[s($,{modelValue:i.value.allowedChannels,"onUpdate:modelValue":e[10]||(e[10]=l=>i.value.allowedChannels=l),placeholder:"channel-id-1,channel-id-2"},null,8,["modelValue"]),e[38]||(e[38]=t("div",{class:"form-hint"},"Comma-separated Discord channel IDs",-1))]),_:1}),s(D,{label:"Container Name",prop:"containerName"},{default:a(()=>[s($,{modelValue:i.value.containerName,"onUpdate:modelValue":e[11]||(e[11]=l=>i.value.containerName=l),placeholder:"bot-my-bot (auto-generated if empty)"},null,8,["modelValue"])]),_:1}),s(D,{label:"Tags",prop:"tags"},{default:a(()=>[s($,{modelValue:i.value.tagsInput,"onUpdate:modelValue":e[12]||(e[12]=l=>i.value.tagsInput=l),placeholder:"prod, staging (comma separated)"},null,8,["modelValue"])]),_:1})]),_:1},8,["model"])]),_:1},8,["modelValue"]),s(ee,{modelValue:S.value,"onUpdate:modelValue":e[15]||(e[15]=l=>S.value=l),title:"Configuration Validation Results",width:"600px"},{footer:a(()=>[s(m,{onClick:e[14]||(e[14]=l=>S.value=!1)},{default:a(()=>[...e[42]||(e[42]=[h("Close",-1)])]),_:1})]),default:a(()=>[g.value?(d(),y("div",Nt,[s(ke,{type:g.value.success?"success":"warning",title:g.value.success?"All checks passed!":"Some checks failed",closable:!1,style:{"margin-bottom":"20px"}},{default:a(()=>[t("div",null," Passed: "+u(H.value.length)+" / "+u(g.value.checks.length),1)]),_:1},8,["type","title"]),s(Ce,null,{default:a(()=>[(d(!0),y(G,null,Q(g.value.checks,l=>(d(),C(be,{key:l.name,type:l.status==="passed"?"success":l.status==="failed"?"danger":"warning"},{default:a(()=>[t("div",Tt,[t("div",Vt,u(l.name),1),t("div",$t,u(l.message),1)])]),_:2},1032,["type"]))),128))]),_:1})])):R("",!0)]),_:1},8,["modelValue"])])}}},Mt=ue(Dt,[["__scopeId","data-v-221ba7f2"]]);export{Mt as default};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{r as g,j as ue,W as ke,f as Ce,ab as r,y as u,B as f,E as o,C as t,D as n,Q as c,u as S,z as j,P as U,J as O,a5 as de,G as te,R as d,c as I,n as xe,aB as Se,aA as De}from"./vue-vendor-CGSlMM3Y.js";import{d as $e,b as Le,f as Ve,c as Ie,l as Te,v as Me,e as Ne,g as Be,m as Re,a as Pe}from"./element-plus-CSm40ime.js";import{a as V,u as Ue}from"./main-
|
|
1
|
+
import{r as g,j as ue,W as ke,f as Ce,ab as r,y as u,B as f,E as o,C as t,D as n,Q as c,u as S,z as j,P as U,J as O,a5 as de,G as te,R as d,c as I,n as xe,aB as Se,aA as De}from"./vue-vendor-CGSlMM3Y.js";import{d as $e,b as Le,f as Ve,c as Ie,l as Te,v as Me,e as Ne,g as Be,m as Re,a as Pe}from"./element-plus-CSm40ime.js";import{a as V,u as Ue}from"./main-D6Y4CFNn.js";import{_ as ce}from"./_plugin-vue_export-helper-DlAUqK2U.js";const je={class:"log-toolbar"},Ee={class:"toolbar-left"},ze={class:"toolbar-right"},Fe={key:0,class:"empty-logs"},Ae={class:"log-timestamp"},Oe={key:0,class:"log-type"},Je={class:"log-message"},qe={key:1,class:"loading-logs"},He={__name:"LogViewer",props:{instanceName:{type:String,required:!0},expanded:{type:Boolean,default:!1}},emits:["expand","collapse"],setup(J,{emit:q}){const T=J,D=q,p=g([]),l=g(!1),v=g(!1),$=g(T.expanded),_=g("all"),b=g(""),k=g(null);let y=null;const B=I(()=>{let i=p.value;if(_.value!=="all"&&(i=i.filter(s=>String(s.data||s).toLowerCase().includes(_.value==="out"?"stdout":"stderr"))),b.value){const s=b.value.toLowerCase();i=i.filter(m=>String(m.data||m).toLowerCase().includes(s))}return i});function H(i){const s=String(i.data||i).toLowerCase();return s.includes("error")||s.includes("err")||i.type==="error"?"log-error":s.includes("warn")||i.type==="warning"?"log-warn":s.includes("info")?"log-info":""}function E(i){return i?new Date(i).toLocaleTimeString("en-US",{hour12:!1}):""}function z(i){i?C():F()}function C(){if(y)return;const i=window.location.protocol==="https:"?"wss:":"ws:",s=window.location.host,m=`${i}//${s}/ws/logs/${T.instanceName}`;y=new WebSocket(m),y.onopen=()=>{l.value=!1},y.onmessage=w=>{try{const x=JSON.parse(w.data);x.type==="log"&&(p.value.push(x),p.value.length>1e3&&(p.value=p.value.slice(-1e3)),xe(()=>{k.value&&(k.value.scrollTop=k.value.scrollHeight)}))}catch{p.value.push({data:w.data,timestamp:Date.now()})}},y.onerror=()=>{l.value=!1},y.onclose=()=>{y=null,v.value&&setTimeout(C,3e3)}}function F(){y&&(y.close(),y=null)}async function W(){l.value=!0;try{const s=await(await fetch(`/api/instances/${T.instanceName}/logs?lines=100`)).json();s.logs&&(p.value=s.logs.split(`
|
|
2
2
|
`).filter(m=>m.trim()).map(m=>({data:m,timestamp:Date.now()})))}catch{}finally{l.value=!1}}function A(){p.value=[]}function G(){const i=p.value.map(x=>x.data||x).join(`
|
|
3
3
|
`),s=new Blob([i],{type:"text/plain"}),m=URL.createObjectURL(s),w=document.createElement("a");w.href=m,w.download=`${T.instanceName}-logs-${Date.now()}.txt`,w.click(),URL.revokeObjectURL(m)}function R(){$.value=!0,D("expand")}function Q(){$.value=!1,D("collapse")}return ue(()=>{W()}),ke(()=>{F()}),Ce(()=>T.expanded,i=>{$.value=i}),(i,s)=>{const m=r("el-checkbox"),w=r("el-option"),x=r("el-select"),K=r("el-input"),P=r("el-button"),a=r("el-icon");return u(),f("div",{class:te(["log-viewer",{expanded:$.value}])},[o("div",je,[o("div",Ee,[t(m,{modelValue:v.value,"onUpdate:modelValue":s[0]||(s[0]=e=>v.value=e),onChange:z},{default:n(()=>[...s[3]||(s[3]=[o("span",null,"Live",-1)])]),_:1},8,["modelValue"]),t(x,{modelValue:_.value,"onUpdate:modelValue":s[1]||(s[1]=e=>_.value=e),size:"small",style:{width:"100px"}},{default:n(()=>[t(w,{label:"All",value:"all"}),t(w,{label:"Stdout",value:"out"}),t(w,{label:"Stderr",value:"err"})]),_:1},8,["modelValue"]),t(K,{modelValue:b.value,"onUpdate:modelValue":s[2]||(s[2]=e=>b.value=e),size:"small",placeholder:"Search logs...","prefix-icon":"Search",style:{width:"200px"},clearable:""},null,8,["modelValue"])]),o("div",ze,[t(P,{size:"small",icon:S($e),onClick:G},{default:n(()=>[...s[4]||(s[4]=[c(" Export ",-1)])]),_:1},8,["icon"]),t(P,{size:"small",icon:S(Le),onClick:A},{default:n(()=>[...s[5]||(s[5]=[c(" Clear ",-1)])]),_:1},8,["icon"]),J.expanded?(u(),j(P,{key:1,size:"small",icon:S(Ie),onClick:Q},null,8,["icon"])):(u(),j(P,{key:0,size:"small",icon:S(Ve),onClick:R},null,8,["icon"]))])]),o("div",{class:"log-content",ref_key:"logContentRef",ref:k},[B.value.length===0?(u(),f("div",Fe,[...s[6]||(s[6]=[o("span",null,"No logs to display",-1)])])):U("",!0),(u(!0),f(O,null,de(B.value,(e,M)=>(u(),f("div",{key:M,class:te(["log-line",H(e)])},[o("span",Ae,d(E(e.timestamp)),1),e.type!=="log"?(u(),f("span",Oe,d(e.type),1)):U("",!0),o("span",Je,d(e.data||e),1)],2))),128)),l.value?(u(),f("div",qe,[t(a,{class:"is-loading"},{default:n(()=>[t(S(Te))]),_:1})])):U("",!0)],512)],2)}}},We=ce(He,[["__scopeId","data-v-d564c329"]]),Ge={class:"instance-detail-view"},Qe={key:0,class:"loading-state"},Ke={key:1,class:"error-state"},Xe={class:"detail-header"},Ye={class:"header-content"},Ze={class:"instance-icon"},et={key:0,width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg"},tt={key:1,width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg"},at={class:"instance-name"},nt={class:"header-actions"},lt={class:"status-panel"},ot={class:"status-indicator"},st={class:"status-text"},it={class:"status-stats"},rt={class:"stat-item"},ut={class:"stat-value"},dt={class:"stat-item"},ct={class:"stat-value"},pt={class:"stat-item"},ft={class:"stat-value"},mt={class:"stat-item"},vt={class:"stat-value"},gt={key:1},_t={key:0,class:"loading-state"},yt={key:0,style:{"margin-left":"12px",color:"var(--el-text-color-secondary)","font-size":"13px"}},wt={__name:"InstanceDetail",setup(J){const q=Se(),T=De(),{success:D,error:p}=Ue(),l=g(null),v=g({status:"loading",exists:!1}),$=g(!0),_=g(null),b=g(!1),k=g(""),y=g(!1),B=g(!1),H=I(()=>{var a,e;return(e=(a=l.value)==null?void 0:a.tags)!=null&&e.includes("prod")?"prod":"dev"}),E=I(()=>{var e;return{"bmad-plugin":"BMAD 插件","simple-config":"基础版"}[(e=l.value)==null?void 0:e.instanceType]||"基础版"}),z=I(()=>{var e;return{"bmad-plugin":"success","simple-config":"info"}[(e=l.value)==null?void 0:e.instanceType]||"info"}),C=I(()=>{var a;return((a=l.value)==null?void 0:a.instanceType)==="bmad-plugin"}),F=I(()=>{const a=v.value.status,e=v.value.health;return a==="loading"?"loading":a==="online"?(e==null?void 0:e.overall)==="degraded"?"warning":"online":a==="stopped"?"stopped":a==="errored"?"error":""}),W=I(()=>{const a=v.value.status;return v.value.health,a==="loading"?"Loading...":{running:"Running",online:"Running",degraded:"Degraded (Docker Down)",stopped:"Stopped",error:"Error",errored:"Error",restarting:"Restarting"}[a]||a||"Loading..."}),A=I(()=>{const a=v.value.status;return a==="running"||a==="online"||a==="degraded"});async function G(){$.value=!0;try{const a=q.params.name;l.value=await V.getInstance(a),await R()}catch{l.value=null}finally{$.value=!1}}async function R(){try{v.value=await V.getInstanceStatus(l.value.name)}catch(a){console.debug("[InstanceDetail] Failed to fetch status:",a.message)}}async function Q(){_.value="start";try{await V.startInstance(l.value.name),D("Started",`${l.value.name} has been started`),await R()}catch(a){p("Failed to start",a.message)}finally{_.value=null}}async function i(){_.value="stop";try{await V.stopInstance(l.value.name),D("Stopped",`${l.value.name} has been stopped`),await R()}catch(a){p("Failed to stop",a.message)}finally{_.value=null}}async function s(){_.value="restart";try{await V.restartInstance(l.value.name),D("Restarted",`${l.value.name} has been restarted`),await R()}catch(a){p("Failed to restart",a.message)}finally{_.value=null}}async function m(a){switch(a){case"logs":const e=document.querySelector(".logs-card");e&&e.scrollIntoView({behavior:"smooth"});break;case"config":await w();break;case"delete":try{await Pe.confirm(`Are you sure you want to delete "${l.value.name}"?`,"Confirm Delete",{type:"warning"}),await V.removeInstance(l.value.name),D("Deleted","Instance has been removed"),T.push("/")}catch(M){M!=="cancel"&&p("Failed",M.message)}break}}async function w(){var a;if(!((a=l.value)!=null&&a.configPath)){p("No Config","This instance does not have a config file");return}b.value=!0,y.value=!0;try{const e=await V.getInstanceConfig(l.value.name);k.value=e.config||""}catch(e){p("Failed to load",e.message),b.value=!1}finally{y.value=!1}}async function x(){B.value=!0;try{try{JSON.parse(k.value)}catch(a){throw new Error("Invalid JSON: "+a.message)}await V.updateInstanceConfig(l.value.name,{config:k.value}),D("Saved","Configuration has been updated"),b.value=!1}catch(a){p("Failed to save",a.message)}finally{B.value=!1}}function K(a){if(!a)return"-";const e=a/1024/1024;return e>=1024?(e/1024).toFixed(1)+" GB":Math.round(e)+" MB"}function P(a){return a?new Date(a).toLocaleString():"-"}return ue(G),(a,e)=>{var le,oe,se,ie;const M=r("el-skeleton"),N=r("el-button"),pe=r("el-result"),fe=r("el-page-header"),me=r("el-button-group"),X=r("el-dropdown-item"),ve=r("el-dropdown-menu"),ge=r("el-dropdown"),_e=r("el-divider"),Y=r("el-card"),ae=r("el-col"),L=r("el-descriptions-item"),Z=r("el-tag"),ye=r("el-descriptions"),we=r("el-row"),ee=r("el-form-item"),ne=r("el-input"),he=r("el-form"),be=r("el-dialog");return u(),f("div",Ge,[$.value?(u(),f("div",Qe,[t(M,{rows:5,animated:""})])):l.value?(u(),f(O,{key:2},[o("div",Xe,[t(fe,{onBack:e[1]||(e[1]=h=>a.$router.push("/"))},{content:n(()=>[o("div",Ye,[o("span",Ze,[H.value==="prod"?(u(),f("svg",et,[...e[6]||(e[6]=[o("rect",{x:"3",y:"3",width:"18",height:"18",rx:"2",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"},null,-1),o("path",{d:"M8 12H16M8 8H16M8 16H12",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"},null,-1)])])):(u(),f("svg",tt,[...e[7]||(e[7]=[o("circle",{cx:"12",cy:"8",r:"4",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"},null,-1),o("path",{d:"M6 21C6 17.5 8.5 15 12 15C15.5 15 18 17.5 18 21",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"},null,-1)])]))]),o("div",null,[o("h2",null,d(l.value.displayName||l.value.name),1),o("span",at,d(l.value.name),1)])])]),_:1}),o("div",nt,[t(me,null,{default:n(()=>[t(N,{icon:S(Me),disabled:A.value,loading:_.value==="start",onClick:Q},{default:n(()=>[...e[8]||(e[8]=[c(" Start ",-1)])]),_:1},8,["icon","disabled","loading"]),t(N,{icon:S(Ne),disabled:!A.value,loading:_.value==="stop",onClick:i},{default:n(()=>[...e[9]||(e[9]=[c(" Stop ",-1)])]),_:1},8,["icon","disabled","loading"]),t(N,{icon:S(Be),loading:_.value==="restart",onClick:s},{default:n(()=>[...e[10]||(e[10]=[c(" Restart ",-1)])]),_:1},8,["icon","loading"])]),_:1}),t(ge,{onCommand:m},{dropdown:n(()=>[t(ve,null,{default:n(()=>[t(X,{command:"logs"},{default:n(()=>[...e[12]||(e[12]=[c("View Logs",-1)])]),_:1}),t(X,{command:"config"},{default:n(()=>[...e[13]||(e[13]=[c("Edit Config",-1)])]),_:1}),t(X,{command:"delete",divided:""},{default:n(()=>[...e[14]||(e[14]=[c("Delete Instance",-1)])]),_:1})]),_:1})]),default:n(()=>[t(N,{icon:S(Re)},{default:n(()=>[...e[11]||(e[11]=[c(" More ",-1)])]),_:1},8,["icon"])]),_:1})])]),t(we,{gutter:20,class:"detail-content"},{default:n(()=>[t(ae,{xs:24,lg:8},{default:n(()=>[t(Y,{header:"Status"},{default:n(()=>[o("div",lt,[o("div",ot,[o("span",{class:te(["status-dot",F.value])},null,2),o("span",st,d(W.value),1)]),v.value.exists?(u(),f(O,{key:0},[t(_e),o("div",it,[o("div",rt,[e[15]||(e[15]=o("span",{class:"stat-label"},"PID",-1)),o("span",ut,d(v.value.pid||"-"),1)]),o("div",dt,[e[16]||(e[16]=o("span",{class:"stat-label"},"Memory",-1)),o("span",ct,d(K(v.value.memory)),1)]),o("div",pt,[e[17]||(e[17]=o("span",{class:"stat-label"},"CPU",-1)),o("span",ft,d(v.value.cpu)+"%",1)]),o("div",mt,[e[18]||(e[18]=o("span",{class:"stat-label"},"Restarts",-1)),o("span",vt,d(v.value.restarts),1)])])],64)):U("",!0)])]),_:1})]),_:1}),t(ae,{xs:24,lg:16},{default:n(()=>[t(Y,{header:"Information"},{default:n(()=>[t(ye,{column:1,border:""},{default:n(()=>[t(L,{label:"Name"},{default:n(()=>[c(d(l.value.name),1)]),_:1}),t(L,{label:"Display Name"},{default:n(()=>[c(d(l.value.displayName||"-"),1)]),_:1}),t(L,{label:"Type"},{default:n(()=>[t(Z,{type:z.value},{default:n(()=>[c(d(E.value),1)]),_:1},8,["type"])]),_:1}),t(L,{label:"Project Path"},{default:n(()=>[o("code",null,d(l.value.projectPath),1)]),_:1}),t(L,{label:"Plugin Path"},{default:n(()=>[o("code",null,d(l.value.pluginPath||"-"),1)]),_:1}),t(L,{label:"Config Path"},{default:n(()=>[o("code",null,d(l.value.configPath||"Default"),1)]),_:1}),t(L,{label:"Added"},{default:n(()=>[c(d(P(l.value.addedAt)),1)]),_:1}),t(L,{label:"Tags"},{default:n(()=>{var h;return[(h=l.value.tags)!=null&&h.length?(u(!0),f(O,{key:0},de(l.value.tags,re=>(u(),j(Z,{key:re,size:"small",style:{"margin-right":"4px"}},{default:n(()=>[c(d(re),1)]),_:2},1024))),128)):(u(),f("span",gt,"-"))]}),_:1})]),_:1})]),_:1})]),_:1})]),_:1}),t(Y,{header:"Recent Logs",class:"logs-card"},{default:n(()=>[t(We,{"instance-name":l.value.name,expanded:!1},null,8,["instance-name"])]),_:1})],64)):(u(),f("div",Ke,[t(pe,{icon:"error",title:"Instance not found","sub-title":"The requested instance does not exist"},{extra:n(()=>[t(N,{type:"primary",onClick:e[0]||(e[0]=h=>a.$router.push("/"))},{default:n(()=>[...e[5]||(e[5]=[c("Back to Dashboard",-1)])]),_:1})]),_:1})])),t(be,{modelValue:b.value,"onUpdate:modelValue":e[4]||(e[4]=h=>b.value=h),title:C.value?`View Config - ${((le=l.value)==null?void 0:le.displayName)||((oe=l.value)==null?void 0:oe.name)} (Read Only)`:`Edit Config - ${((se=l.value)==null?void 0:se.displayName)||((ie=l.value)==null?void 0:ie.name)}`,width:"70%",top:"5vh"},{footer:n(()=>[t(N,{onClick:e[3]||(e[3]=h=>b.value=!1)},{default:n(()=>[c(d(C.value?"Close":"Cancel"),1)]),_:1}),C.value?U("",!0):(u(),j(N,{key:0,type:"primary",loading:B.value,onClick:x},{default:n(()=>[...e[19]||(e[19]=[c(" Save ",-1)])]),_:1},8,["loading"]))]),default:n(()=>[y.value?(u(),f("div",_t,[t(M,{rows:5,animated:""})])):(u(),j(he,{key:1,"label-width":"120px"},{default:n(()=>[t(ee,{label:"Instance Type"},{default:n(()=>[t(Z,{type:z.value},{default:n(()=>[c(d(E.value),1)]),_:1},8,["type"]),C.value?(u(),f("span",yt," BMAD plugin instances are read-only. Please edit config files directly in the project directory. ")):U("",!0)]),_:1}),t(ee,{label:"Config Path"},{default:n(()=>{var h;return[t(ne,{value:(h=l.value)==null?void 0:h.configPath,disabled:""},null,8,["value"])]}),_:1}),t(ee,{label:"Config Content"},{default:n(()=>[t(ne,{modelValue:k.value,"onUpdate:modelValue":e[2]||(e[2]=h=>k.value=h),type:"textarea",rows:20,disabled:C.value,placeholder:C.value?"BMAD instance config is read-only":"Configuration JSON content"},null,8,["modelValue","disabled","placeholder"])]),_:1})]),_:1}))]),_:1},8,["modelValue","title"])])}}},xt=ce(wt,[["__scopeId","data-v-3fce17dc"]]);export{xt as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as v,u as F}from"./main-
|
|
1
|
+
import{a as v,u as F}from"./main-D6Y4CFNn.js";import{_ as R}from"./_plugin-vue_export-helper-DlAUqK2U.js";import{a as q}from"./element-plus-CSm40ime.js";import{j as L,y as _,B as k,E as m,C as a,D as l,Q as i,z as A,R as N,M as Q,r as u,ab as r,ac as G}from"./vue-vendor-CGSlMM3Y.js";const H={class:"instances-view"},J={class:"view-header"},K={class:"header-actions"},O={key:0,class:"empty-state"},W={__name:"Instances",setup(X){const{success:b,error:d}=F(),B=u([]),h=u(!0),w=u(!1),D=u(!1),y=u(!1),c=u(!1),f=u([]),o=u({name:"",projectPath:"",displayName:""});async function g(){h.value=!0;try{B.value=await v.getInstances()}catch(n){d("Failed to load instances",n.message)}finally{h.value=!1}}async function $(){w.value=!0;try{const n=await v.discoverInstances();f.value=n.discovered||[],y.value=!0}catch(n){d("Discovery failed",n.message)}finally{w.value=!1}}async function x(n){try{await v.importInstance(n),b("Imported",`Instance "${n.name}" has been imported`),y.value=!1,f.value=f.value.filter(e=>e.name!==n.name),await g()}catch(e){d("Import failed",e.message)}}async function z(){if(!o.value.name){d("Validation Error","Instance name is required");return}if(!o.value.name.match(/^[a-z0-9-]+$/)){d("Validation Error","Name must contain only lowercase letters, numbers, and hyphens");return}if(!o.value.projectPath){d("Validation Error","Project path is required");return}D.value=!0;try{await v.importFromPath(o.value.name,o.value.projectPath,{displayName:o.value.displayName||void 0}),b("Imported",`BMAD plugin "${o.value.name}" has been imported`),c.value=!1,o.value={name:"",projectPath:"",displayName:""},await g()}catch(n){d("Import failed",n.message)}finally{D.value=!1}}async function E(n){try{await q.confirm(`Are you sure you want to delete instance "${n.name}"?`,"Confirm Delete",{type:"warning",confirmButtonText:"Delete",cancelButtonText:"Cancel"}),await v.removeInstance(n.name),b("Deleted",`Instance "${n.name}" has been removed`),await g()}catch(e){e!=="cancel"&&d("Failed to delete",e.message)}}return L(g),(n,e)=>{const p=r("el-button"),s=r("el-table-column"),I=r("el-tag"),C=r("el-table"),M=r("el-dialog"),P=r("el-input"),V=r("el-form-item"),T=r("el-form"),S=r("el-card"),U=G("loading");return _(),k("div",H,[m("div",J,[e[9]||(e[9]=m("h1",null,"Instances",-1)),m("div",K,[a(p,{type:"primary",onClick:e[0]||(e[0]=t=>c.value=!0)},{default:l(()=>[...e[7]||(e[7]=[i(" Add BMAD Plugin ",-1)])]),_:1}),a(p,{onClick:$,loading:w.value},{default:l(()=>[...e[8]||(e[8]=[i(" Discover ",-1)])]),_:1},8,["loading"])])]),a(M,{modelValue:y.value,"onUpdate:modelValue":e[1]||(e[1]=t=>y.value=t),title:"Discover BMAD Plugins",width:"600px"},{default:l(()=>[f.value.length===0?(_(),k("div",O,[...e[10]||(e[10]=[m("p",null,"No BMAD plugins found in PM2.",-1),m("p",{class:"hint"},"BMAD plugins must be running in PM2 to be discovered.",-1)])])):(_(),A(C,{key:1,data:f.value,stripe:"","max-height":"400"},{default:l(()=>[a(s,{prop:"displayName",label:"Name"}),a(s,{prop:"projectPath",label:"Project Path","show-overflow-tooltip":""}),a(s,{label:"Status",width:"100"},{default:l(({row:t})=>[a(I,{type:t.isRunning?"success":"info",size:"small"},{default:l(()=>[i(N(t.isRunning?"Running":"Stopped"),1)]),_:2},1032,["type"])]),_:1}),a(s,{label:"Actions",width:"100"},{default:l(({row:t})=>[a(p,{size:"small",type:"primary",onClick:j=>x(t)},{default:l(()=>[...e[11]||(e[11]=[i(" Import ",-1)])]),_:1},8,["onClick"])]),_:1})]),_:1},8,["data"]))]),_:1},8,["modelValue"]),a(M,{modelValue:c.value,"onUpdate:modelValue":e[6]||(e[6]=t=>c.value=t),title:"Add BMAD Plugin",width:"500px"},{footer:l(()=>[a(p,{onClick:e[5]||(e[5]=t=>c.value=!1)},{default:l(()=>[...e[14]||(e[14]=[i("Cancel",-1)])]),_:1}),a(p,{type:"primary",onClick:z,loading:D.value},{default:l(()=>[...e[15]||(e[15]=[i(" Import ",-1)])]),_:1},8,["loading"])]),default:l(()=>[a(T,{model:o.value,"label-width":"120px"},{default:l(()=>[a(V,{label:"Instance Name"},{default:l(()=>[a(P,{modelValue:o.value.name,"onUpdate:modelValue":e[2]||(e[2]=t=>o.value.name=t),placeholder:"e.g., my-bot",pattern:"[a-z0-9-]+"},null,8,["modelValue"]),e[12]||(e[12]=m("span",{class:"form-hint"},"Lowercase letters, numbers, and hyphens only",-1))]),_:1}),a(V,{label:"Project Path"},{default:l(()=>[a(P,{modelValue:o.value.projectPath,"onUpdate:modelValue":e[3]||(e[3]=t=>o.value.projectPath=t),placeholder:"/path/to/your/project"},null,8,["modelValue"]),e[13]||(e[13]=m("span",{class:"form-hint"},"Path to BMAD project directory",-1))]),_:1}),a(V,{label:"Display Name"},{default:l(()=>[a(P,{modelValue:o.value.displayName,"onUpdate:modelValue":e[4]||(e[4]=t=>o.value.displayName=t),placeholder:"My Bot (optional)"},null,8,["modelValue"])]),_:1})]),_:1},8,["model"])]),_:1},8,["modelValue"]),a(S,null,{default:l(()=>[Q((_(),A(C,{data:B.value,stripe:""},{default:l(()=>[a(s,{prop:"name",label:"Name",width:"180"}),a(s,{prop:"displayName",label:"Display Name"}),a(s,{prop:"instanceType",label:"Type",width:"130"},{default:l(({row:t})=>[a(I,{type:t.instanceType==="bmad-plugin"?"warning":"info",size:"small"},{default:l(()=>[i(N(t.instanceType==="bmad-plugin"?"BMAD Plugin":"Simple Config"),1)]),_:2},1032,["type"])]),_:1}),a(s,{prop:"projectPath",label:"Project Path","show-overflow-tooltip":""}),a(s,{prop:"enabled",label:"Status",width:"100"},{default:l(({row:t})=>[a(I,{type:t.enabled?"success":"info",size:"small"},{default:l(()=>[i(N(t.enabled?"Enabled":"Disabled"),1)]),_:2},1032,["type"])]),_:1}),a(s,{label:"Actions",width:"200",align:"right"},{default:l(({row:t})=>[a(p,{size:"small",onClick:j=>n.$router.push(`/instances/${t.name}`)},{default:l(()=>[...e[16]||(e[16]=[i(" View ",-1)])]),_:1},8,["onClick"]),a(p,{size:"small",type:"danger",plain:"",onClick:j=>E(t)},{default:l(()=>[...e[17]||(e[17]=[i(" Delete ",-1)])]),_:1},8,["onClick"])]),_:1})]),_:1},8,["data"])),[[U,h.value]])]),_:1})])}}},te=R(W,[["__scopeId","data-v-761f2ac7"]]);export{te as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{b as M}from"./main-
|
|
1
|
+
import{b as M}from"./main-D6Y4CFNn.js";import{_ as I}from"./_plugin-vue_export-helper-DlAUqK2U.js";import{r as B,j as W,y as g,B as $,E as r,C as t,D as o,u,z as v,Q as i,R as c,ab as s,c as D}from"./vue-vendor-CGSlMM3Y.js";import"./element-plus-CSm40ime.js";const N={class:"settings-view"},A={class:"setting-item"},C={__name:"Settings",setup(E){const{systemInfo:d,fetchSystemInfo:w}=M(),_=B(localStorage.getItem("darkMode")==="true"),b=D(()=>{var n;const a=(n=d.value)==null?void 0:n.platform;return{darwin:"macOS",linux:"Linux",win32:"Windows"}[a]||a});function k(){localStorage.setItem("darkMode",_.value),document.documentElement.classList.toggle("dark",_.value)}function h(a){if(!a)return"-";const e=Math.floor(a/86400),n=Math.floor(a%86400/3600),m=Math.floor(a%3600/60);return e>0?`${e}d ${n}h ${m}m`:n>0?`${n}h ${m}m`:`${m}m`}return W(()=>{w()}),(a,e)=>{const n=s("el-descriptions-item"),m=s("el-descriptions"),y=s("el-skeleton"),p=s("el-card"),f=s("el-col"),V=s("el-switch"),x=s("el-divider"),S=s("el-row");return g(),$("div",N,[e[4]||(e[4]=r("div",{class:"view-header"},[r("h1",null,"Settings")],-1)),t(S,{gutter:20},{default:o(()=>[t(f,{span:24},{default:o(()=>[t(p,{header:"System Information"},{default:o(()=>[u(d)?(g(),v(m,{key:0,column:2,border:""},{default:o(()=>[t(n,{label:"Platform"},{default:o(()=>[i(c(b.value),1)]),_:1}),t(n,{label:"Node Version"},{default:o(()=>[i(c(u(d).nodeVersion),1)]),_:1}),t(n,{label:"AgentWindow Version"},{default:o(()=>{var l;return[i(c((l=u(d).agentWindow)==null?void 0:l.version),1)]}),_:1}),t(n,{label:"Home Directory"},{default:o(()=>{var l;return[i(c((l=u(d).agentWindow)==null?void 0:l.home),1)]}),_:1}),t(n,{label:"Uptime",span:2},{default:o(()=>[i(c(h(u(d).uptime)),1)]),_:1})]),_:1})):(g(),v(y,{key:1,rows:4,animated:""}))]),_:1})]),_:1}),t(f,{xs:24,md:12},{default:o(()=>[t(p,{header:"Appearance"},{default:o(()=>[r("div",A,[e[1]||(e[1]=r("span",null,"Dark Mode",-1)),t(V,{modelValue:_.value,"onUpdate:modelValue":e[0]||(e[0]=l=>_.value=l),onChange:k},null,8,["modelValue"])])]),_:1})]),_:1}),t(f,{xs:24,md:12},{default:o(()=>[t(p,{header:"About"},{default:o(()=>[e[2]||(e[2]=r("p",null,"AgentWindow Web UI provides a browser-based interface for managing your bot instances.",-1)),t(x),e[3]||(e[3]=r("p",{class:"about-text"},[i(" Version 1.0.0"),r("br"),i(" Built with Vue 3 + Element Plus ")],-1))]),_:1})]),_:1})]),_:1})])}}},z=I(C,[["__scopeId","data-v-a16409cb"]]);export{z as default};
|