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.
Files changed (55) hide show
  1. package/README.md +21 -8
  2. package/README.zh-CN.md +151 -0
  3. package/bin/cli.js +45 -0
  4. package/docs/WEB_UI_GUIDE.md +249 -0
  5. package/package.json +15 -3
  6. package/scripts/test-platform.js +109 -0
  7. package/src/api/routes/index.js +25 -0
  8. package/src/api/routes/instances.js +252 -0
  9. package/src/api/routes/operations.js +118 -0
  10. package/src/api/routes/system.js +42 -0
  11. package/src/api/server.js +147 -0
  12. package/src/api/websocket/index.js +16 -0
  13. package/src/api/websocket/logs.js +127 -0
  14. package/src/cli/commands/add.js +80 -0
  15. package/src/cli/commands/config.js +192 -0
  16. package/src/cli/commands/index.js +89 -0
  17. package/src/cli/commands/info.js +94 -0
  18. package/src/cli/commands/list.js +72 -0
  19. package/src/cli/commands/logs.js +67 -0
  20. package/src/cli/commands/remove.js +97 -0
  21. package/src/cli/commands/restart.js +67 -0
  22. package/src/cli/commands/start.js +101 -0
  23. package/src/cli/commands/status.js +95 -0
  24. package/src/cli/commands/stop.js +53 -0
  25. package/src/cli/commands/ui.js +51 -0
  26. package/src/cli/index.js +110 -0
  27. package/src/core/config.js +5 -10
  28. package/src/core/instance/backup-manager.js +172 -0
  29. package/src/core/instance/config-manager.js +279 -0
  30. package/src/core/instance/index.js +62 -0
  31. package/src/core/instance/manager.js +220 -0
  32. package/src/core/instance/pm2-bridge.js +205 -0
  33. package/src/core/instance/validator.js +161 -0
  34. package/src/core/platform/detector.js +142 -0
  35. package/src/core/platform/docker-bridge.js +372 -0
  36. package/src/core/platform/index.js +27 -0
  37. package/src/core/platform/paths.js +112 -0
  38. package/src/core/platform/pm2-bridge.js +314 -0
  39. package/web/dist/assets/Dashboard-C1smB9Nj.js +1 -0
  40. package/web/dist/assets/Dashboard-ezbZMSpZ.css +1 -0
  41. package/web/dist/assets/InstanceDetail-CRPMV7rg.css +1 -0
  42. package/web/dist/assets/InstanceDetail-C_Ddtrog.js +3 -0
  43. package/web/dist/assets/Instances-CvnH8iDv.css +1 -0
  44. package/web/dist/assets/Instances-_u2__M83.js +1 -0
  45. package/web/dist/assets/Settings-CAu3R9RW.css +1 -0
  46. package/web/dist/assets/Settings-CIa9MX7m.js +1 -0
  47. package/web/dist/assets/_plugin-vue_export-helper-DlAUqK2U.js +1 -0
  48. package/web/dist/assets/element-plus-Jr6qTeY5.js +37 -0
  49. package/web/dist/assets/main-CalRvcyG.css +1 -0
  50. package/web/dist/assets/main-D3cdXAiV.js +7 -0
  51. package/web/dist/assets/vue-vendor-CGSlMM3Y.js +29 -0
  52. package/web/dist/index.html +16 -0
  53. package/SECURITY.md +0 -31
  54. package/docs/legacy/DEVELOPMENT.md +0 -174
  55. 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 _};