agent-window 1.0.0 β 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -8
- package/README.zh-CN.md +151 -0
- package/bin/cli.js +45 -0
- package/docs/WEB_UI_GUIDE.md +249 -0
- package/package.json +15 -3
- package/scripts/test-platform.js +109 -0
- package/src/api/routes/index.js +25 -0
- package/src/api/routes/instances.js +252 -0
- package/src/api/routes/operations.js +118 -0
- package/src/api/routes/system.js +42 -0
- package/src/api/server.js +147 -0
- package/src/api/websocket/index.js +16 -0
- package/src/api/websocket/logs.js +127 -0
- package/src/cli/commands/add.js +80 -0
- package/src/cli/commands/config.js +192 -0
- package/src/cli/commands/index.js +89 -0
- package/src/cli/commands/info.js +94 -0
- package/src/cli/commands/list.js +72 -0
- package/src/cli/commands/logs.js +67 -0
- package/src/cli/commands/remove.js +97 -0
- package/src/cli/commands/restart.js +67 -0
- package/src/cli/commands/start.js +101 -0
- package/src/cli/commands/status.js +95 -0
- package/src/cli/commands/stop.js +53 -0
- package/src/cli/commands/ui.js +51 -0
- package/src/cli/index.js +110 -0
- package/src/core/config.js +5 -10
- package/src/core/instance/backup-manager.js +172 -0
- package/src/core/instance/config-manager.js +279 -0
- package/src/core/instance/index.js +62 -0
- package/src/core/instance/manager.js +220 -0
- package/src/core/instance/pm2-bridge.js +205 -0
- package/src/core/instance/validator.js +161 -0
- package/src/core/platform/detector.js +142 -0
- package/src/core/platform/docker-bridge.js +372 -0
- package/src/core/platform/index.js +27 -0
- package/src/core/platform/paths.js +112 -0
- package/src/core/platform/pm2-bridge.js +314 -0
- package/web/dist/assets/Dashboard-C1smB9Nj.js +1 -0
- package/web/dist/assets/Dashboard-ezbZMSpZ.css +1 -0
- package/web/dist/assets/InstanceDetail-CRPMV7rg.css +1 -0
- package/web/dist/assets/InstanceDetail-C_Ddtrog.js +3 -0
- package/web/dist/assets/Instances-CvnH8iDv.css +1 -0
- package/web/dist/assets/Instances-_u2__M83.js +1 -0
- package/web/dist/assets/Settings-CAu3R9RW.css +1 -0
- package/web/dist/assets/Settings-CIa9MX7m.js +1 -0
- package/web/dist/assets/_plugin-vue_export-helper-DlAUqK2U.js +1 -0
- package/web/dist/assets/element-plus-Jr6qTeY5.js +37 -0
- package/web/dist/assets/main-CalRvcyG.css +1 -0
- package/web/dist/assets/main-D3cdXAiV.js +7 -0
- package/web/dist/assets/vue-vendor-CGSlMM3Y.js +29 -0
- package/web/dist/index.html +16 -0
- package/SECURITY.md +0 -31
- package/docs/legacy/DEVELOPMENT.md +0 -174
- package/docs/legacy/HANDOVER.md +0 -149
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PM2 Bridge Module
|
|
3
|
+
*
|
|
4
|
+
* Cross-platform abstraction for PM2 process manager commands.
|
|
5
|
+
* Supports:
|
|
6
|
+
* - Native PM2 on Linux/macOS
|
|
7
|
+
* - PM2 on Windows (via npm install -g pm2)
|
|
8
|
+
* - PM2 on WSL2
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { spawn } from 'child_process';
|
|
12
|
+
import { isWindows, isWSLAvailable } from './detector.js';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Execute PM2 command with platform abstraction
|
|
16
|
+
*/
|
|
17
|
+
async function execPM2Command(args, options = {}) {
|
|
18
|
+
let command = 'pm2';
|
|
19
|
+
let cmdArgs = args;
|
|
20
|
+
let execOptions = {
|
|
21
|
+
timeout: options.timeout || 30000,
|
|
22
|
+
windowsHide: true
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
// On Windows, try WSL2 if available
|
|
26
|
+
if (isWindows() && options.wsl !== false) {
|
|
27
|
+
const wslAvailable = await isWSLAvailable();
|
|
28
|
+
if (wslAvailable) {
|
|
29
|
+
command = 'wsl.exe';
|
|
30
|
+
cmdArgs = ['pm2', ...args];
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return new Promise((resolve, reject) => {
|
|
35
|
+
const stdoutChunks = [];
|
|
36
|
+
const stderrChunks = [];
|
|
37
|
+
|
|
38
|
+
const child = spawn(command, cmdArgs, {
|
|
39
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
40
|
+
...execOptions
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
child.stdout.on('data', (chunk) => {
|
|
44
|
+
stdoutChunks.push(chunk);
|
|
45
|
+
if (!options.silent) {
|
|
46
|
+
process.stdout.write(chunk);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
child.stderr.on('data', (chunk) => {
|
|
51
|
+
stderrChunks.push(chunk);
|
|
52
|
+
if (!options.silent) {
|
|
53
|
+
process.stderr.write(chunk);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
child.on('close', (code) => {
|
|
58
|
+
const stdout = Buffer.concat(stdoutChunks).toString('utf8').trim();
|
|
59
|
+
const stderr = Buffer.concat(stderrChunks).toString('utf8').trim();
|
|
60
|
+
|
|
61
|
+
if (code === 0) {
|
|
62
|
+
resolve({ stdout, stderr, code });
|
|
63
|
+
} else {
|
|
64
|
+
reject(new Error(`PM2 command failed (exit ${code}): ${stderr || stdout}`));
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
child.on('error', (err) => {
|
|
69
|
+
reject(new Error(`Failed to execute PM2 command: ${err.message}`));
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Get list of PM2 processes
|
|
76
|
+
*/
|
|
77
|
+
async function list(options = {}) {
|
|
78
|
+
try {
|
|
79
|
+
const result = await execPM2Command(['jlist'], { ...options, silent: true });
|
|
80
|
+
const processes = JSON.parse(result.stdout || '[]');
|
|
81
|
+
return processes.map(p => ({
|
|
82
|
+
pid: p.pid,
|
|
83
|
+
name: p.name,
|
|
84
|
+
pm_id: p.pm_id,
|
|
85
|
+
status: p.pm2_env?.status || 'unknown',
|
|
86
|
+
uptime: p.pm2_env?.pm_uptime || null,
|
|
87
|
+
memory: p.monit?.memory || 0,
|
|
88
|
+
cpu: p.monit?.cpu || 0,
|
|
89
|
+
restarts: p.pm2_env?.restart_time || 0,
|
|
90
|
+
cwd: p.pm2_env?.cwd || null,
|
|
91
|
+
script: p.pm2_env?.pm_cwd || null
|
|
92
|
+
}));
|
|
93
|
+
} catch {
|
|
94
|
+
return [];
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Get process by name
|
|
100
|
+
*/
|
|
101
|
+
async function getProcess(name, options = {}) {
|
|
102
|
+
const processes = await list(options);
|
|
103
|
+
return processes.find(p => p.name === name) || null;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Start a process with PM2
|
|
108
|
+
*/
|
|
109
|
+
async function start(scriptPath, options = {}) {
|
|
110
|
+
const args = ['start', scriptPath];
|
|
111
|
+
|
|
112
|
+
if (options.name) {
|
|
113
|
+
args.push('--name', options.name);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (options.cwd) {
|
|
117
|
+
args.push('--cwd', options.cwd);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Environment variables
|
|
121
|
+
if (options.env) {
|
|
122
|
+
// PM2 expects env via --env or JSON config
|
|
123
|
+
// For simple vars, we can use --env name=value format
|
|
124
|
+
for (const [key, value] of Object.entries(options.env)) {
|
|
125
|
+
args.push('--env', `${key}=${value}`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (options.instances) {
|
|
130
|
+
args.push('-i', String(options.instances));
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (options.watch) {
|
|
134
|
+
args.push('--watch');
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (options.maxMemoryRestart) {
|
|
138
|
+
args.push('--max-memory-restart', options.maxMemoryRestart);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return execPM2Command(args, options);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Stop a PM2 process
|
|
146
|
+
*/
|
|
147
|
+
async function stop(nameOrId, options = {}) {
|
|
148
|
+
return execPM2Command(['stop', String(nameOrId)], options);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Restart a PM2 process
|
|
153
|
+
*/
|
|
154
|
+
async function restart(nameOrId, options = {}) {
|
|
155
|
+
return execPM2Command(['restart', String(nameOrId)], options);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Delete a PM2 process
|
|
160
|
+
*/
|
|
161
|
+
async function deleteProcess(nameOrId, options = {}) {
|
|
162
|
+
return execPM2Command(['delete', String(nameOrId)], options);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Reload a process (zero-downtime reload)
|
|
167
|
+
*/
|
|
168
|
+
async function reload(nameOrId, options = {}) {
|
|
169
|
+
return execPM2Command(['reload', String(nameOrId)], options);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Reset process restart counter
|
|
174
|
+
*/
|
|
175
|
+
async function reset(nameOrId, options = {}) {
|
|
176
|
+
return execPM2Command(['reset', String(nameOrId)], options);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Get process logs
|
|
181
|
+
*/
|
|
182
|
+
async function logs(nameOrId, options = {}) {
|
|
183
|
+
const args = ['logs'];
|
|
184
|
+
|
|
185
|
+
if (options.lines) {
|
|
186
|
+
args.push('--lines', String(options.lines));
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (options.nostream) {
|
|
190
|
+
args.push('--nostream');
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
args.push(String(nameOrId));
|
|
194
|
+
|
|
195
|
+
return execPM2Command(args, { ...options, silent: options.silent || false });
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Flush process logs
|
|
200
|
+
*/
|
|
201
|
+
async function flush(nameOrId, options = {}) {
|
|
202
|
+
const args = ['flush'];
|
|
203
|
+
if (nameOrId) {
|
|
204
|
+
args.push(String(nameOrId));
|
|
205
|
+
}
|
|
206
|
+
return execPM2Command(args, options);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Get process info
|
|
211
|
+
*/
|
|
212
|
+
async function describe(nameOrId, options = {}) {
|
|
213
|
+
try {
|
|
214
|
+
const result = await execPM2Command(['show', String(nameOrId)], { ...options, silent: true });
|
|
215
|
+
return result.stdout;
|
|
216
|
+
} catch {
|
|
217
|
+
return null;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Save PM2 process list
|
|
223
|
+
*/
|
|
224
|
+
async function save(options = {}) {
|
|
225
|
+
return execPM2Command(['save'], options);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Resurrect PM2 processes from dump
|
|
230
|
+
*/
|
|
231
|
+
async function resurrect(options = {}) {
|
|
232
|
+
return execPM2Command(['resurrect'], options);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Check if PM2 is available
|
|
237
|
+
*/
|
|
238
|
+
async function isAvailable() {
|
|
239
|
+
try {
|
|
240
|
+
await execPM2Command(['--version'], { silent: true, timeout: 5000 });
|
|
241
|
+
return true;
|
|
242
|
+
} catch {
|
|
243
|
+
return false;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Get PM2 version
|
|
249
|
+
*/
|
|
250
|
+
async function version(options = {}) {
|
|
251
|
+
try {
|
|
252
|
+
const result = await execPM2Command(['--version'], { ...options, silent: true });
|
|
253
|
+
return result.stdout.trim();
|
|
254
|
+
} catch {
|
|
255
|
+
return null;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Start PM2 daemon (if not running)
|
|
261
|
+
*/
|
|
262
|
+
async function daemon(options = {}) {
|
|
263
|
+
try {
|
|
264
|
+
// Just running list will start daemon if needed
|
|
265
|
+
await list({ ...options, silent: true });
|
|
266
|
+
return true;
|
|
267
|
+
} catch {
|
|
268
|
+
return false;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Kill PM2 daemon
|
|
274
|
+
*/
|
|
275
|
+
async function kill(options = {}) {
|
|
276
|
+
return execPM2Command(['kill'], options);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Update PM2 to latest version
|
|
281
|
+
*/
|
|
282
|
+
async function update(options = {}) {
|
|
283
|
+
return execPM2Command(['update'], options);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Generate PM2 startup script
|
|
288
|
+
*/
|
|
289
|
+
async function startup(options = {}) {
|
|
290
|
+
const platform = options.platform || (isWindows() ? 'windows' : 'systemd');
|
|
291
|
+
return execPM2Command(['startup', platform], options);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
export default {
|
|
295
|
+
list,
|
|
296
|
+
getProcess,
|
|
297
|
+
start,
|
|
298
|
+
stop,
|
|
299
|
+
restart,
|
|
300
|
+
delete: deleteProcess,
|
|
301
|
+
reload,
|
|
302
|
+
reset,
|
|
303
|
+
logs,
|
|
304
|
+
flush,
|
|
305
|
+
describe,
|
|
306
|
+
save,
|
|
307
|
+
resurrect,
|
|
308
|
+
isAvailable,
|
|
309
|
+
version,
|
|
310
|
+
daemon,
|
|
311
|
+
kill,
|
|
312
|
+
update,
|
|
313
|
+
startup
|
|
314
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{aA as Q,j as E,ab as m,y as u,z as U,D as n,E as s,R as d,G as H,B as _,P as R,J as z,a5 as G,c as x,r as w,C as a,Q as M,u as q,am as X}from"./vue-vendor-CGSlMM3Y.js";import{p as T}from"./element-plus-Jr6qTeY5.js";import{a as k,u as K}from"./main-D3cdXAiV.js";import{_ as L}from"./_plugin-vue_export-helper-DlAUqK2U.js";const Y={class:"card-header"},Z={class:"header-left"},tt={class:"instance-info"},st={class:"instance-name"},et={class:"instance-alias"},at={class:"status-label"},nt={class:"card-body"},ot={class:"info-row"},lt={class:"value"},it={key:0,class:"stats-row"},rt={class:"stat"},dt={class:"stat-value"},ut={class:"stat"},ct={class:"stat-value"},pt={key:0,class:"stat"},mt={class:"stat-value"},vt={key:1,class:"tags-row"},ft={class:"card-actions"},_t={class:"action-buttons"},ht=["disabled"],gt=["disabled"],yt=["disabled"],bt={__name:"InstanceCard",props:{instance:{type:Object,required:!0}},setup(y,{expose:B}){const r=y,h=Q(),{success:b,error:c}=K(),l=w({status:"unknown",exists:!1,memory:0,cpu:0,uptime:0}),$=x(()=>{const e=l.value.status;return e==="online"?"online":e==="stopped"?"stopped":e==="errored"?"error":e==="restarting"?"restarting":"stopped"}),o=x(()=>{const e=l.value.status;return{online:"Running",stopped:"Stopped",errored:"Error",restarting:"Restarting",unknown:"Unknown"}[e]||"Unknown"}),S=x(()=>{const e=r.instance.projectPath;return e.length>35?"..."+e.slice(-32):e});async function v(){try{const e=await k.getInstanceStatus(r.instance.name);l.value=e}catch{l.value={status:"unknown",exists:!1,memory:0,cpu:0,uptime:0}}}async function A(){try{await k.startInstance(r.instance.name),b("Started",`${r.instance.name} has been started`),await v()}catch(e){c("Failed to start",e.message)}}async function D(){try{await k.stopInstance(r.instance.name),b("Stopped",`${r.instance.name} has been stopped`),await v()}catch(e){c("Failed to stop",e.message)}}async function C(){try{await k.restartInstance(r.instance.name),b("Restarted",`${r.instance.name} has been restarted`),await v()}catch(e){c("Failed to restart",e.message)}}function I(){h.push(`/instances/${r.instance.name}`)}function V(e){const t=e/1024/1024;return t>=1024?(t/1024).toFixed(1)+" GB":Math.round(t)+" MB"}function P(e){if(!e)return"-";const t=Math.floor((Date.now()-e)/1e3);return t<60?`${t}s`:t<3600?`${Math.floor(t/60)}m`:t<86400?`${Math.floor(t/3600)}h`:`${Math.floor(t/86400)}d`}return E(()=>{v();const e=setInterval(v,1e4);return()=>clearInterval(e)}),B({fetchStatus:v}),(e,t)=>{const p=m("el-card");return u(),U(p,{class:"instance-card"},{default:n(()=>{var f;return[s("div",Y,[s("div",Z,[t[0]||(t[0]=s("div",{class:"instance-icon"},[s("svg",{width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"1.5"},[s("rect",{x:"3",y:"3",width:"18",height:"18",rx:"4"}),s("circle",{cx:"12",cy:"12",r:"3"})])],-1)),s("div",tt,[s("h3",st,d(y.instance.displayName||y.instance.name),1),s("span",et,d(y.instance.name),1)])]),s("div",{class:H(["status-indicator",$.value])},[t[1]||(t[1]=s("span",{class:"status-dot"},null,-1)),s("span",at,d(o.value),1)],2)]),s("div",nt,[s("div",ot,[t[2]||(t[2]=s("span",{class:"label"},"Path",-1)),s("span",lt,d(S.value),1)]),l.value.exists?(u(),_("div",it,[s("div",rt,[t[3]||(t[3]=s("span",{class:"stat-label"},"Memory",-1)),s("span",dt,d(V(l.value.memory)),1)]),s("div",ut,[t[4]||(t[4]=s("span",{class:"stat-label"},"CPU",-1)),s("span",ct,d(l.value.cpu)+"%",1)]),l.value.status==="online"?(u(),_("div",pt,[t[5]||(t[5]=s("span",{class:"stat-label"},"Uptime",-1)),s("span",mt,d(P(l.value.uptime)),1)])):R("",!0)])):R("",!0),(f=y.instance.tags)!=null&&f.length?(u(),_("div",vt,[(u(!0),_(z,null,G(y.instance.tags,g=>(u(),_("span",{key:g,class:"tag"},d(g),1))),128))])):R("",!0)]),s("div",ft,[s("div",_t,[s("button",{class:"action-btn",disabled:l.value.status==="online",title:"Start",onClick:A},[...t[6]||(t[6]=[s("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2"},[s("polygon",{points:"5 3 19 12 5 21 5 3"})],-1)])],8,ht),s("button",{class:"action-btn",disabled:l.value.status!=="online",title:"Stop",onClick:D},[...t[7]||(t[7]=[s("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2"},[s("rect",{x:"6",y:"4",width:"4",height:"16"}),s("rect",{x:"14",y:"4",width:"4",height:"16"})],-1)])],8,gt),s("button",{class:"action-btn",disabled:l.value.status==="unknown",title:"Restart",onClick:C},[...t[8]||(t[8]=[s("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2"},[s("polyline",{points:"23 4 23 10 17 10"}),s("polyline",{points:"1 20 1 14 7 14"}),s("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,yt)]),s("button",{class:"details-btn",onClick:I}," Details ")])]}),_:1})}}},wt=L(bt,[["__scopeId","data-v-bbbabd13"]]),kt={class:"dashboard-view"},xt={class:"dashboard-header"},$t={class:"stat-content"},Ct={class:"stat-info"},It={class:"stat-value"},Vt={class:"stat-content"},Pt={class:"stat-info"},Nt={class:"stat-value"},jt={class:"stat-content"},Mt={class:"stat-info"},Bt={class:"stat-value"},St={class:"stat-content"},At={class:"stat-info"},Dt={class:"stat-value"},Rt={key:0,class:"loading-state"},Ut={key:1,class:"empty-state"},Ft={__name:"Dashboard",setup(y){const{success:B,error:r}=K(),h=w([]),b=w(!0),c=w(!1),l=w(!1),$=w(null),o=w({name:"",displayName:"",projectPath:"",tagsInput:""}),S={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"}]},v=x(()=>h.value.filter(e=>e.enabled).length),A=x(()=>h.value.length-v.value),D=x(()=>0);async function C(){b.value=!0;try{h.value=await k.getInstances()}catch(e){r("Failed to load",e.message)}finally{b.value=!1}}async function I(){var t;if(await((t=$.value)==null?void 0:t.validate().catch(()=>!1))){l.value=!0;try{const p=o.value.tagsInput?o.value.tagsInput.split(",").map(f=>f.trim()).filter(Boolean):[];await k.addInstance({name:o.value.name,displayName:o.value.displayName||o.value.name,projectPath:o.value.projectPath,tags:p}),B("Added",`Instance "${o.value.name}" has been added`),c.value=!1,P(),await C()}catch(p){r("Failed to add",p.message)}finally{l.value=!1}}}function V(){c.value=!1,P()}function P(){var e;o.value={name:"",displayName:"",projectPath:"",tagsInput:""},(e=$.value)==null||e.clearValidation()}return E(()=>{C();const e=setInterval(C,3e4);return()=>clearInterval(e)}),(e,t)=>{const p=m("el-button"),f=m("el-card"),g=m("el-col"),F=m("el-row"),O=m("el-skeleton"),N=m("el-input"),j=m("el-form-item"),W=m("el-form"),J=m("el-dialog");return u(),_("div",kt,[s("div",xt,[t[8]||(t[8]=s("div",null,[s("h1",null,"Dashboard"),s("p",{class:"subtitle"},"Manage your AgentWindow bot instances")],-1)),a(p,{type:"primary",icon:q(T),onClick:t[0]||(t[0]=i=>c.value=!0)},{default:n(()=>[...t[7]||(t[7]=[M(" Add Instance ",-1)])]),_:1},8,["icon"])]),a(F,{gutter:16,class:"stats-row"},{default:n(()=>[a(g,{xs:12,sm:6},{default:n(()=>[a(f,{class:"stat-card"},{default:n(()=>[s("div",$t,[t[10]||(t[10]=s("span",{class:"stat-icon"},"π¦",-1)),s("div",Ct,[s("span",It,d(h.value.length),1),t[9]||(t[9]=s("span",{class:"stat-label"},"Total",-1))])])]),_:1})]),_:1}),a(g,{xs:12,sm:6},{default:n(()=>[a(f,{class:"stat-card success"},{default:n(()=>[s("div",Vt,[t[12]||(t[12]=s("span",{class:"stat-icon"},"π’",-1)),s("div",Pt,[s("span",Nt,d(v.value),1),t[11]||(t[11]=s("span",{class:"stat-label"},"Running",-1))])])]),_:1})]),_:1}),a(g,{xs:12,sm:6},{default:n(()=>[a(f,{class:"stat-card warning"},{default:n(()=>[s("div",jt,[t[14]||(t[14]=s("span",{class:"stat-icon"},"βΈοΈ",-1)),s("div",Mt,[s("span",Bt,d(A.value),1),t[13]||(t[13]=s("span",{class:"stat-label"},"Stopped",-1))])])]),_:1})]),_:1}),a(g,{xs:12,sm:6},{default:n(()=>[a(f,{class:"stat-card danger"},{default:n(()=>[s("div",St,[t[16]||(t[16]=s("span",{class:"stat-icon"},"β οΈ",-1)),s("div",At,[s("span",Dt,d(D.value),1),t[15]||(t[15]=s("span",{class:"stat-label"},"Errors",-1))])])]),_:1})]),_:1})]),_:1}),b.value?(u(),_("div",Rt,[a(O,{rows:3,animated:""})])):h.value.length===0?(u(),_("div",Ut,[t[18]||(t[18]=s("div",{class:"empty-icon"},"πͺ",-1)),t[19]||(t[19]=s("h3",null,"No instances yet",-1)),t[20]||(t[20]=s("p",null,"Add your first AgentWindow bot instance to get started",-1)),a(p,{type:"primary",icon:q(T),onClick:t[1]||(t[1]=i=>c.value=!0)},{default:n(()=>[...t[17]||(t[17]=[M(" Add Instance ",-1)])]),_:1},8,["icon"])])):(u(),U(F,{key:2,gutter:16,class:"instances-grid"},{default:n(()=>[(u(!0),_(z,null,G(h.value,i=>(u(),U(g,{key:i.name,xs:24,sm:12,lg:8},{default:n(()=>[a(wt,{instance:i},null,8,["instance"])]),_:2},1024))),128))]),_:1})),a(J,{modelValue:c.value,"onUpdate:modelValue":t[6]||(t[6]=i=>c.value=i),title:"Add Instance",width:"500px","before-close":V},{footer:n(()=>[a(p,{onClick:V},{default:n(()=>[...t[22]||(t[22]=[M("Cancel",-1)])]),_:1}),a(p,{type:"primary",loading:l.value,onClick:I},{default:n(()=>[...t[23]||(t[23]=[M(" Add Instance ",-1)])]),_:1},8,["loading"])]),default:n(()=>[a(W,{ref_key:"formRef",ref:$,model:o.value,rules:S,"label-width":"100px"},{default:n(()=>[a(j,{label:"Name",prop:"name"},{default:n(()=>[a(N,{modelValue:o.value.name,"onUpdate:modelValue":t[2]||(t[2]=i=>o.value.name=i),placeholder:"my-bot",onKeyup:X(I,["enter"])},null,8,["modelValue"])]),_:1}),a(j,{label:"Display Name",prop:"displayName"},{default:n(()=>[a(N,{modelValue:o.value.displayName,"onUpdate:modelValue":t[3]||(t[3]=i=>o.value.displayName=i),placeholder:"My Bot"},null,8,["modelValue"])]),_:1}),a(j,{label:"Project Path",prop:"projectPath"},{default:n(()=>[a(N,{modelValue:o.value.projectPath,"onUpdate:modelValue":t[4]||(t[4]=i=>o.value.projectPath=i),placeholder:"/path/to/project"},null,8,["modelValue"]),t[21]||(t[21]=s("div",{class:"form-hint"},"Path to the bot project directory",-1))]),_:1}),a(j,{label:"Tags",prop:"tags"},{default:n(()=>[a(N,{modelValue:o.value.tagsInput,"onUpdate:modelValue":t[5]||(t[5]=i=>o.value.tagsInput=i),placeholder:"prod, staging (comma separated)"},null,8,["modelValue"])]),_:1})]),_:1},8,["model"])]),_:1},8,["modelValue"])])}}},Gt=L(Ft,[["__scopeId","data-v-8cc433c7"]]);export{Gt as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.instance-card[data-v-bbbabd13]{height:100%;transition:all var(--aw-transition-base)}.instance-card[data-v-bbbabd13]:hover{transform:translateY(-2px)}.card-header[data-v-bbbabd13]{display:flex;justify-content:space-between;align-items:center;margin-bottom:16px}.header-left[data-v-bbbabd13]{display:flex;align-items:center;gap:12px}.header-left .instance-icon[data-v-bbbabd13]{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-bbbabd13]{margin:0;font-size:15px;font-weight:600;color:var(--aw-text-primary);letter-spacing:-.01em}.header-left .instance-alias[data-v-bbbabd13]{font-size:12px;color:var(--aw-text-secondary)}.status-indicator[data-v-bbbabd13]{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-bbbabd13]{width:6px;height:6px;border-radius:50%;background:currentColor}.status-indicator.online[data-v-bbbabd13]{background:#34c7591a;color:var(--aw-status-online)}.status-indicator.stopped[data-v-bbbabd13]{background:#8e8e931a;color:var(--aw-status-stopped)}.status-indicator.error[data-v-bbbabd13]{background:#ff3b301a;color:var(--aw-status-error)}.status-indicator.restarting[data-v-bbbabd13]{background:#ff95001a;color:var(--aw-status-restarting)}.card-body[data-v-bbbabd13]{display:flex;flex-direction:column;gap:12px;margin-bottom:16px}.info-row[data-v-bbbabd13]{display:flex;justify-content:space-between;align-items:center}.info-row .label[data-v-bbbabd13]{font-size:12px;color:var(--aw-text-secondary)}.info-row .value[data-v-bbbabd13]{font-size:12px;font-family:SF Mono,Monaco,Cascadia Code,monospace;color:var(--aw-text-primary)}.stats-row[data-v-bbbabd13]{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-bbbabd13]{display:flex;flex-direction:column;align-items:center;gap:4px}.stat .stat-label[data-v-bbbabd13]{font-size:10px;color:var(--aw-text-secondary);text-transform:uppercase;letter-spacing:.05em}.stat .stat-value[data-v-bbbabd13]{font-size:14px;font-weight:600;color:var(--aw-text-primary)}.tags-row[data-v-bbbabd13]{display:flex;gap:6px;flex-wrap:wrap}.tags-row .tag[data-v-bbbabd13]{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-bbbabd13]{display:flex;justify-content:space-between;align-items:center;padding-top:12px;border-top:1px solid var(--aw-bg-tertiary)}.action-buttons[data-v-bbbabd13]{display:flex;gap:4px}.action-btn[data-v-bbbabd13]{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-bbbabd13]:hover:not(:disabled){background:var(--aw-bg-secondary);color:var(--aw-text-primary)}.action-btn[data-v-bbbabd13]:disabled{opacity:.4;cursor:not-allowed}.action-btn[data-v-bbbabd13]:active:not(:disabled){transform:scale(.95)}.details-btn[data-v-bbbabd13]{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-bbbabd13]:hover{background:#0071e31a}.dashboard-view[data-v-8cc433c7]{display:flex;flex-direction:column;gap:24px}.dashboard-header[data-v-8cc433c7]{display:flex;justify-content:space-between;align-items:flex-start}.dashboard-header h1[data-v-8cc433c7]{margin:0;font-size:28px;font-weight:600}.dashboard-header .subtitle[data-v-8cc433c7]{margin:4px 0 0;color:var(--el-text-color-secondary)}.stats-row .stat-card[data-v-8cc433c7]{background:linear-gradient(135deg,var(--el-bg-color) 0%,var(--el-bg-color-page) 100%)}.stats-row .stat-card.success[data-v-8cc433c7]{border-left:3px solid var(--aw-success)}.stats-row .stat-card.warning[data-v-8cc433c7]{border-left:3px solid var(--aw-warning)}.stats-row .stat-card.danger[data-v-8cc433c7]{border-left:3px solid var(--aw-danger)}.stats-row .stat-content[data-v-8cc433c7]{display:flex;align-items:center;gap:16px}.stats-row .stat-content .stat-icon[data-v-8cc433c7]{font-size:32px}.stats-row .stat-content .stat-info[data-v-8cc433c7]{display:flex;flex-direction:column}.stats-row .stat-content .stat-info .stat-value[data-v-8cc433c7]{font-size:24px;font-weight:600;line-height:1}.stats-row .stat-content .stat-info .stat-label[data-v-8cc433c7]{font-size:12px;color:var(--el-text-color-secondary)}.loading-state[data-v-8cc433c7]{padding:40px 0}.empty-state[data-v-8cc433c7]{display:flex;flex-direction:column;align-items:center;gap:16px;padding:80px 0}.empty-state .empty-icon[data-v-8cc433c7]{font-size:64px;opacity:.5}.empty-state h3[data-v-8cc433c7]{margin:0;font-size:20px}.empty-state p[data-v-8cc433c7]{margin:0;color:var(--el-text-color-secondary)}.instances-grid [class*=el-col][data-v-8cc433c7]{margin-bottom:16px}.form-hint[data-v-8cc433c7]{font-size:12px;color:var(--el-text-color-secondary);margin-top:4px}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.log-viewer[data-v-d564c329]{display:flex;flex-direction:column;height:400px;border:1px solid var(--el-border-color);border-radius:4px;background:var(--el-bg-color)}.log-viewer.expanded[data-v-d564c329]{position:fixed;top:0;left:0;right:0;bottom:0;height:100vh;z-index:9999;border-radius:0}.log-toolbar[data-v-d564c329]{display:flex;justify-content:space-between;align-items:center;padding:8px 12px;border-bottom:1px solid var(--el-border-color);background:var(--el-bg-color-page)}.log-toolbar .toolbar-left[data-v-d564c329],.log-toolbar .toolbar-right[data-v-d564c329]{display:flex;align-items:center;gap:8px}.log-content[data-v-d564c329]{flex:1;overflow-y:auto;padding:12px;font-family:Monaco,Menlo,Ubuntu Mono,monospace;font-size:13px;line-height:1.6;background:#1a1a1a;color:#e0e0e0}.empty-logs[data-v-d564c329]{display:flex;align-items:center;justify-content:center;height:100%;color:var(--el-text-color-secondary)}.log-line[data-v-d564c329]{display:flex;gap:8px;padding:2px 0}.log-line[data-v-d564c329]:hover{background:#ffffff0d}.log-line .log-timestamp[data-v-d564c329]{color:#888;flex-shrink:0}.log-line .log-type[data-v-d564c329]{color:var(--el-color-warning);flex-shrink:0;font-weight:600}.log-line .log-message[data-v-d564c329]{flex:1;word-break:break-all}.log-line.log-error[data-v-d564c329]{color:#f56c6c}.log-line.log-warn[data-v-d564c329]{color:#e6a23c}.log-line.log-info[data-v-d564c329]{color:#409eff}.loading-logs[data-v-d564c329]{display:flex;justify-content:center;padding:20px}.instance-detail-view[data-v-f1b6dde0]{display:flex;flex-direction:column;gap:20px}.detail-header[data-v-f1b6dde0]{display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:16px}.detail-header .header-content[data-v-f1b6dde0]{display:flex;align-items:center;gap:12px}.detail-header .header-content .instance-icon[data-v-f1b6dde0]{font-size:32px}.detail-header .header-content h2[data-v-f1b6dde0]{margin:0;font-size:20px}.detail-header .header-content .instance-name[data-v-f1b6dde0]{font-size:12px;color:var(--el-text-color-secondary)}.detail-header .header-actions[data-v-f1b6dde0]{display:flex;gap:8px}.detail-content .status-panel .status-indicator[data-v-f1b6dde0]{display:flex;align-items:center;gap:8px}.detail-content .status-panel .status-indicator .status-dot[data-v-f1b6dde0]{width:12px;height:12px;border-radius:50%}.detail-content .status-panel .status-indicator .status-dot.online[data-v-f1b6dde0]{background:var(--aw-status-online)}.detail-content .status-panel .status-indicator .status-dot.stopped[data-v-f1b6dde0]{background:var(--aw-status-stopped)}.detail-content .status-panel .status-indicator .status-dot.error[data-v-f1b6dde0]{background:var(--aw-status-error)}.detail-content .status-panel .status-indicator .status-text[data-v-f1b6dde0]{font-size:16px;font-weight:500}.detail-content .status-panel .status-stats[data-v-f1b6dde0]{display:grid;grid-template-columns:1fr 1fr;gap:16px}.detail-content .status-panel .status-stats .stat-item[data-v-f1b6dde0]{display:flex;flex-direction:column;gap:4px}.detail-content .status-panel .status-stats .stat-item .stat-label[data-v-f1b6dde0]{font-size:11px;color:var(--el-text-color-secondary);text-transform:uppercase}.detail-content .status-panel .status-stats .stat-item .stat-value[data-v-f1b6dde0]{font-size:14px;font-weight:600}.logs-card[data-v-f1b6dde0] .el-card__body{padding:0}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{r as b,j as Y,W as se,f as le,ab as u,y as p,B as w,E as a,C as t,D as s,Q as v,u as k,z as H,P as z,J as M,a5 as Z,G as K,R as r,c as E,n as oe,aB as ie,aA as ue}from"./vue-vendor-CGSlMM3Y.js";import{d as re,b as de,f as ce,c as pe,l as me,v as _e,e as fe,r as ve,m as ge,a as we}from"./element-plus-Jr6qTeY5.js";import{a as V,u as ye}from"./main-D3cdXAiV.js";import{_ as ee}from"./_plugin-vue_export-helper-DlAUqK2U.js";const he={class:"log-toolbar"},be={class:"toolbar-left"},ke={class:"toolbar-right"},xe={key:0,class:"empty-logs"},Ce={class:"log-timestamp"},Se={key:0,class:"log-type"},$e={class:"log-message"},Le={key:1,class:"loading-logs"},De={__name:"LogViewer",props:{instanceName:{type:String,required:!0},expanded:{type:Boolean,default:!1}},emits:["expand","collapse"],setup(j,{emit:F}){const C=j,S=F,_=b([]),l=b(!1),m=b(!1),x=b(C.expanded),f=b("all"),L=b(""),D=b(null);let y=null;const N=E(()=>{let i=_.value;if(f.value!=="all"&&(i=i.filter(n=>String(n.data||n).toLowerCase().includes(f.value==="out"?"stdout":"stderr"))),L.value){const n=L.value.toLowerCase();i=i.filter(d=>String(d.data||d).toLowerCase().includes(n))}return i});function I(i){const n=String(i.data||i).toLowerCase();return n.includes("error")||n.includes("err")||i.type==="error"?"log-error":n.includes("warn")||i.type==="warning"?"log-warn":n.includes("info")?"log-info":""}function A(i){return i?new Date(i).toLocaleTimeString("en-US",{hour12:!1}):""}function W(i){i?B():U()}function B(){if(y)return;const i=window.location.protocol==="https:"?"wss:":"ws:",n=window.location.host,d=`${i}//${n}/ws/logs/${C.instanceName}`;y=new WebSocket(d),y.onopen=()=>{l.value=!1},y.onmessage=g=>{try{const h=JSON.parse(g.data);h.type==="log"&&(_.value.push(h),_.value.length>1e3&&(_.value=_.value.slice(-1e3)),oe(()=>{D.value&&(D.value.scrollTop=D.value.scrollHeight)}))}catch{_.value.push({data:g.data,timestamp:Date.now()})}},y.onerror=()=>{l.value=!1},y.onclose=()=>{y=null,m.value&&setTimeout(B,3e3)}}function U(){y&&(y.close(),y=null)}async function q(){l.value=!0;try{const n=await(await fetch(`/api/instances/${C.instanceName}/logs?lines=100`)).json();n.logs&&(_.value=n.logs.split(`
|
|
2
|
+
`).filter(d=>d.trim()).map(d=>({data:d,timestamp:Date.now()})))}catch{}finally{l.value=!1}}function O(){_.value=[]}function o(){const i=_.value.map(h=>h.data||h).join(`
|
|
3
|
+
`),n=new Blob([i],{type:"text/plain"}),d=URL.createObjectURL(n),g=document.createElement("a");g.href=d,g.download=`${C.instanceName}-logs-${Date.now()}.txt`,g.click(),URL.revokeObjectURL(d)}function e(){x.value=!0,S("expand")}function G(){x.value=!1,S("collapse")}return Y(()=>{q()}),se(()=>{U()}),le(()=>C.expanded,i=>{x.value=i}),(i,n)=>{const d=u("el-checkbox"),g=u("el-option"),h=u("el-select"),J=u("el-input"),R=u("el-button"),Q=u("el-icon");return p(),w("div",{class:K(["log-viewer",{expanded:x.value}])},[a("div",he,[a("div",be,[t(d,{modelValue:m.value,"onUpdate:modelValue":n[0]||(n[0]=c=>m.value=c),onChange:W},{default:s(()=>[...n[3]||(n[3]=[a("span",null,"Live",-1)])]),_:1},8,["modelValue"]),t(h,{modelValue:f.value,"onUpdate:modelValue":n[1]||(n[1]=c=>f.value=c),size:"small",style:{width:"100px"}},{default:s(()=>[t(g,{label:"All",value:"all"}),t(g,{label:"Stdout",value:"out"}),t(g,{label:"Stderr",value:"err"})]),_:1},8,["modelValue"]),t(J,{modelValue:L.value,"onUpdate:modelValue":n[2]||(n[2]=c=>L.value=c),size:"small",placeholder:"Search logs...","prefix-icon":"Search",style:{width:"200px"},clearable:""},null,8,["modelValue"])]),a("div",ke,[t(R,{size:"small",icon:k(re),onClick:o},{default:s(()=>[...n[4]||(n[4]=[v(" Export ",-1)])]),_:1},8,["icon"]),t(R,{size:"small",icon:k(de),onClick:O},{default:s(()=>[...n[5]||(n[5]=[v(" Clear ",-1)])]),_:1},8,["icon"]),j.expanded?(p(),H(R,{key:1,size:"small",icon:k(pe),onClick:G},null,8,["icon"])):(p(),H(R,{key:0,size:"small",icon:k(ce),onClick:e},null,8,["icon"]))])]),a("div",{class:"log-content",ref_key:"logContentRef",ref:D},[N.value.length===0?(p(),w("div",xe,[...n[6]||(n[6]=[a("span",null,"No logs to display",-1)])])):z("",!0),(p(!0),w(M,null,Z(N.value,(c,P)=>(p(),w("div",{key:P,class:K(["log-line",I(c)])},[a("span",Ce,r(A(c.timestamp)),1),c.type!=="log"?(p(),w("span",Se,r(c.type),1)):z("",!0),a("span",$e,r(c.data||c),1)],2))),128)),l.value?(p(),w("div",Le,[t(Q,{class:"is-loading"},{default:s(()=>[t(k(me))]),_:1})])):z("",!0)],512)],2)}}},Ie=ee(De,[["__scopeId","data-v-d564c329"]]),Re={class:"instance-detail-view"},Ve={key:0,class:"loading-state"},Ne={key:1,class:"error-state"},Be={class:"detail-header"},Ue={class:"header-content"},Pe={class:"instance-icon"},Te={class:"instance-name"},ze={class:"header-actions"},Me={class:"status-panel"},Ee={class:"status-indicator"},je={class:"status-text"},Fe={class:"status-stats"},Ae={class:"stat-item"},We={class:"stat-value"},qe={class:"stat-item"},Oe={class:"stat-value"},Ge={class:"stat-item"},Je={class:"stat-value"},Qe={class:"stat-item"},He={class:"stat-value"},Ke={key:1},Xe={__name:"InstanceDetail",setup(j){const F=ie(),C=ue(),{success:S,error:_}=ye(),l=b(null),m=b({status:"unknown",exists:!1}),x=b(!0),f=b(null),L=E(()=>{var o,e;return(e=(o=l.value)==null?void 0:o.tags)!=null&&e.includes("prod")?"π’":"π€"}),D=E(()=>{const o=m.value.status;return o==="online"?"online":o==="stopped"?"stopped":o==="errored"?"error":""}),y=E(()=>{const o=m.value.status;return{online:"Running",stopped:"Stopped",errored:"Error",restarting:"Restarting"}[o]||"Unknown"});async function N(){x.value=!0;try{const o=F.params.name;l.value=await V.getInstance(o),await I()}catch{l.value=null}finally{x.value=!1}}async function I(){try{m.value=await V.getInstanceStatus(l.value.name)}catch{m.value={status:"unknown",exists:!1}}}async function A(){f.value="start";try{await V.startInstance(l.value.name),S("Started",`${l.value.name} has been started`),await I()}catch(o){_("Failed to start",o.message)}finally{f.value=null}}async function W(){f.value="stop";try{await V.stopInstance(l.value.name),S("Stopped",`${l.value.name} has been stopped`),await I()}catch(o){_("Failed to stop",o.message)}finally{f.value=null}}async function B(){f.value="restart";try{await V.restartInstance(l.value.name),S("Restarted",`${l.value.name} has been restarted`),await I()}catch(o){_("Failed to restart",o.message)}finally{f.value=null}}async function U(o){switch(o){case"delete":try{await we.confirm(`Are you sure you want to delete "${l.value.name}"?`,"Confirm Delete",{type:"warning"}),await V.removeInstance(l.value.name),S("Deleted","Instance has been removed"),C.push("/")}catch(e){err!=="cancel"&&_("Failed",e.message)}break}}function q(o){if(!o)return"-";const e=o/1024/1024;return e>=1024?(e/1024).toFixed(1)+" GB":Math.round(e)+" MB"}function O(o){return o?new Date(o).toLocaleString():"-"}return Y(N),(o,e)=>{const G=u("el-skeleton"),i=u("el-button"),n=u("el-result"),d=u("el-page-header"),g=u("el-button-group"),h=u("el-dropdown-item"),J=u("el-dropdown-menu"),R=u("el-dropdown"),Q=u("el-divider"),c=u("el-card"),P=u("el-col"),$=u("el-descriptions-item"),te=u("el-tag"),ae=u("el-descriptions"),ne=u("el-row");return p(),w("div",Re,[x.value?(p(),w("div",Ve,[t(G,{rows:5,animated:""})])):l.value?(p(),w(M,{key:2},[a("div",Be,[t(d,{onBack:e[1]||(e[1]=T=>o.$router.push("/"))},{content:s(()=>[a("div",Ue,[a("span",Pe,r(L.value),1),a("div",null,[a("h2",null,r(l.value.displayName||l.value.name),1),a("span",Te,r(l.value.name),1)])])]),_:1}),a("div",ze,[t(g,null,{default:s(()=>[t(i,{icon:k(_e),disabled:m.value.status==="online",loading:f.value==="start",onClick:A},{default:s(()=>[...e[3]||(e[3]=[v(" Start ",-1)])]),_:1},8,["icon","disabled","loading"]),t(i,{icon:k(fe),disabled:m.value.status!=="online",loading:f.value==="stop",onClick:W},{default:s(()=>[...e[4]||(e[4]=[v(" Stop ",-1)])]),_:1},8,["icon","disabled","loading"]),t(i,{icon:k(ve),loading:f.value==="restart",onClick:B},{default:s(()=>[...e[5]||(e[5]=[v(" Restart ",-1)])]),_:1},8,["icon","loading"])]),_:1}),t(R,{onCommand:U},{dropdown:s(()=>[t(J,null,{default:s(()=>[t(h,{command:"logs"},{default:s(()=>[...e[7]||(e[7]=[v("View Logs",-1)])]),_:1}),t(h,{command:"config"},{default:s(()=>[...e[8]||(e[8]=[v("Edit Config",-1)])]),_:1}),t(h,{command:"delete",divided:""},{default:s(()=>[...e[9]||(e[9]=[v("Delete Instance",-1)])]),_:1})]),_:1})]),default:s(()=>[t(i,{icon:k(ge)},{default:s(()=>[...e[6]||(e[6]=[v(" More ",-1)])]),_:1},8,["icon"])]),_:1})])]),t(ne,{gutter:20,class:"detail-content"},{default:s(()=>[t(P,{xs:24,lg:8},{default:s(()=>[t(c,{header:"Status"},{default:s(()=>[a("div",Me,[a("div",Ee,[a("span",{class:K(["status-dot",D.value])},null,2),a("span",je,r(y.value),1)]),m.value.exists?(p(),w(M,{key:0},[t(Q),a("div",Fe,[a("div",Ae,[e[10]||(e[10]=a("span",{class:"stat-label"},"PID",-1)),a("span",We,r(m.value.pid||"-"),1)]),a("div",qe,[e[11]||(e[11]=a("span",{class:"stat-label"},"Memory",-1)),a("span",Oe,r(q(m.value.memory)),1)]),a("div",Ge,[e[12]||(e[12]=a("span",{class:"stat-label"},"CPU",-1)),a("span",Je,r(m.value.cpu)+"%",1)]),a("div",Qe,[e[13]||(e[13]=a("span",{class:"stat-label"},"Restarts",-1)),a("span",He,r(m.value.restarts),1)])])],64)):z("",!0)])]),_:1})]),_:1}),t(P,{xs:24,lg:16},{default:s(()=>[t(c,{header:"Information"},{default:s(()=>[t(ae,{column:1,border:""},{default:s(()=>[t($,{label:"Name"},{default:s(()=>[v(r(l.value.name),1)]),_:1}),t($,{label:"Display Name"},{default:s(()=>[v(r(l.value.displayName||"-"),1)]),_:1}),t($,{label:"Project Path"},{default:s(()=>[a("code",null,r(l.value.projectPath),1)]),_:1}),t($,{label:"Plugin Path"},{default:s(()=>[a("code",null,r(l.value.pluginPath||"-"),1)]),_:1}),t($,{label:"Config Path"},{default:s(()=>[a("code",null,r(l.value.configPath||"Default"),1)]),_:1}),t($,{label:"Added"},{default:s(()=>[v(r(O(l.value.addedAt)),1)]),_:1}),t($,{label:"Tags"},{default:s(()=>{var T;return[(T=l.value.tags)!=null&&T.length?(p(!0),w(M,{key:0},Z(l.value.tags,X=>(p(),H(te,{key:X,size:"small",style:{"margin-right":"4px"}},{default:s(()=>[v(r(X),1)]),_:2},1024))),128)):(p(),w("span",Ke,"-"))]}),_:1})]),_:1})]),_:1})]),_:1})]),_:1}),t(c,{header:"Recent Logs",class:"logs-card"},{default:s(()=>[t(Ie,{"instance-name":l.value.name,expanded:!1},null,8,["instance-name"])]),_:1})],64)):(p(),w("div",Ne,[t(n,{icon:"error",title:"Instance not found","sub-title":"The requested instance does not exist"},{extra:s(()=>[t(i,{type:"primary",onClick:e[0]||(e[0]=T=>o.$router.push("/"))},{default:s(()=>[...e[2]||(e[2]=[v("Back to Dashboard",-1)])]),_:1})]),_:1})]))])}}},at=ee(Xe,[["__scopeId","data-v-f1b6dde0"]]);export{at as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.instances-view[data-v-b1513f53]{display:flex;flex-direction:column;gap:20px}.view-header h1[data-v-b1513f53]{margin:0;font-size:24px}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{a as p,u as B}from"./main-D3cdXAiV.js";import{_ as I}from"./_plugin-vue_export-helper-DlAUqK2U.js";import{a as k}from"./element-plus-Jr6qTeY5.js";import{j as x,y as _,B as N,E as f,C as a,D as n,M as $,z,Q as i,R as E,ac as T,r as b,ab as o}from"./vue-vendor-CGSlMM3Y.js";const V={class:"instances-view"},j={__name:"Instances",setup(M){const{success:v,error:r}=B(),d=b([]),c=b(!0);async function u(){c.value=!0;try{d.value=await p.getInstances()}catch(t){r("Failed to load",t.message)}finally{c.value=!1}}async function y(t){try{await k.confirm(`Are you sure you want to delete instance "${t.name}"?`,"Confirm Delete",{type:"warning",confirmButtonText:"Delete",cancelButtonText:"Cancel"}),await p.removeInstance(t.name),v("Deleted",`Instance "${t.name}" has been removed`),await u()}catch(e){e!=="cancel"&&r("Failed to delete",e.message)}}return x(u),(t,e)=>{const s=o("el-table-column"),g=o("el-tag"),m=o("el-button"),h=o("el-table"),w=o("el-card"),D=T("loading");return _(),N("div",V,[e[2]||(e[2]=f("div",{class:"view-header"},[f("h1",null,"Instances")],-1)),a(w,null,{default:n(()=>[$((_(),z(h,{data:d.value,stripe:""},{default:n(()=>[a(s,{prop:"name",label:"Name",width:"180"}),a(s,{prop:"displayName",label:"Display Name"}),a(s,{prop:"projectPath",label:"Project Path"}),a(s,{prop:"enabled",label:"Status",width:"100"},{default:n(({row:l})=>[a(g,{type:l.enabled?"success":"info",size:"small"},{default:n(()=>[i(E(l.enabled?"Enabled":"Disabled"),1)]),_:2},1032,["type"])]),_:1}),a(s,{label:"Actions",width:"200",align:"right"},{default:n(({row:l})=>[a(m,{size:"small",onClick:C=>t.$router.push(`/instances/${l.name}`)},{default:n(()=>[...e[0]||(e[0]=[i(" View ",-1)])]),_:1},8,["onClick"]),a(m,{size:"small",type:"danger",plain:"",onClick:C=>y(l)},{default:n(()=>[...e[1]||(e[1]=[i(" Delete ",-1)])]),_:1},8,["onClick"])]),_:1})]),_:1},8,["data"])),[[D,c.value]])]),_:1})])}}},Q=I(j,[["__scopeId","data-v-b1513f53"]]);export{Q as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.settings-view[data-v-a16409cb]{display:flex;flex-direction:column;gap:20px}.view-header h1[data-v-a16409cb]{margin:0;font-size:24px}.setting-item[data-v-a16409cb]{display:flex;justify-content:space-between;align-items:center}.about-text[data-v-a16409cb]{color:var(--el-text-color-secondary);font-size:14px;line-height:1.6}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{b as M}from"./main-D3cdXAiV.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-Jr6qTeY5.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};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const s=(t,r)=>{const o=t.__vccOpts||t;for(const[c,e]of r)o[c]=e;return o};export{s as _};
|