chore(panel): fleet-aware shell footer + drop dead vuefinder dep
All checks were successful
CI / backend-types (push) Successful in 9s
CI / frontend-build (push) Successful in 14s
CI / agent-tests (push) Successful in 49s
CI / integration (push) Successful in 22s

COA-B cleanup:
- Sidebar agent-health footer now reads the fleet store (host count / online
  count / per-host status + last heartbeat) instead of the single legacy
  server.connection row, which disagreed with the multi-host fleet. Removed the
  legacy useServerStore dependency from the shell.
- Removed the unused 'vuefinder' dependency (replaced by the native file
  manager): dep + main.ts plugin/CSS registration. Main JS chunk 588kB -> 165kB.

Recon reclassified the 'dead cmd.server v1' item: it is the LIVE license-level
command path (module config applies, plugin install, schedules, legacy
start/stop) served only by the Go agent — a Rust-agent parity gap, not dead
code. Left intact.

Build-green (vue-tsc) + boots clean in-browser (0 console errors).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Vantz Stockwell
2026-06-11 21:04:09 -04:00
parent 4ef5db5b0d
commit 0715492ddf
5 changed files with 41 additions and 613 deletions

View File

@@ -1,20 +1,19 @@
{
"name": "frontend",
"version": "0.0.0",
"version": "1.0.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "frontend",
"version": "0.0.0",
"version": "1.0.1",
"dependencies": {
"echarts": "^6.0.0",
"lucide-vue-next": "^0.564.0",
"pinia": "^3.0.4",
"pinia-plugin-persistedstate": "^4.7.1",
"vue": "^3.5.25",
"vue-router": "^5.0.2",
"vuefinder": "^4.1.1"
"vue-router": "^5.0.2"
},
"devDependencies": {
"@tailwindcss/vite": "^4.1.18",
@@ -531,31 +530,6 @@
"node": ">=18"
}
},
"node_modules/@floating-ui/core": {
"version": "1.7.4",
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.4.tgz",
"integrity": "sha512-C3HlIdsBxszvm5McXlB8PeOEWfBhcGBTZGkGlWc2U0KFY5IwG5OQEuQ8rq52DZmcHDlPLd+YFBK+cZcytwIFWg==",
"license": "MIT",
"dependencies": {
"@floating-ui/utils": "^0.2.10"
}
},
"node_modules/@floating-ui/dom": {
"version": "1.7.5",
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.5.tgz",
"integrity": "sha512-N0bD2kIPInNHUHehXhMke1rBGs1dwqvC9O9KYMyyjK7iXt7GAhnro7UlcuYcGdS/yYOlq0MAVgrow8IbWJwyqg==",
"license": "MIT",
"dependencies": {
"@floating-ui/core": "^1.7.4",
"@floating-ui/utils": "^0.2.10"
}
},
"node_modules/@floating-ui/utils": {
"version": "0.2.10",
"resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz",
"integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==",
"license": "MIT"
},
"node_modules/@jridgewell/gen-mapping": {
"version": "0.3.13",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
@@ -601,71 +575,6 @@
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
"node_modules/@nanostores/i18n": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/@nanostores/i18n/-/i18n-1.2.2.tgz",
"integrity": "sha512-5LLxl95+ZI46MrM/Kn7YjORKsD7+Xy2tgjZ7/oDT/BGPEiaBM9lK89/afeK+BqaQL0Xd9Xaa5MPuuVSyWAo+/w==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"engines": {
"node": "^20.0.0 || >=22.0.0"
},
"peerDependencies": {
"nanostores": "^0.9.0 || ^0.10.0 || ^0.11.0 || ^1.0.0"
}
},
"node_modules/@nanostores/persistent": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/@nanostores/persistent/-/persistent-1.3.3.tgz",
"integrity": "sha512-+b4I8xrmjhKE3hQ9V7/b4Xa+MBMkM2P4Ulv33zFEF/+2Hucsb24vTjYiWR8R97y8YdRptmRKlL5Qwy0q1Jj5nQ==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"engines": {
"node": "^20.0.0 || >=22.0.0"
},
"peerDependencies": {
"nanostores": "^0.9.0 || ^0.10.0 || ^0.11.0 || ^1.0.0"
}
},
"node_modules/@nanostores/vue": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@nanostores/vue/-/vue-1.0.1.tgz",
"integrity": "sha512-0VwubMTMvEdWQhVN4BAvDZ+vHQH3O1G9BaOfgrjfF4erqBsWScoK/zyaBeRfFjptNOb25947EFPHBZwEf9JcMg==",
"funding": [
{
"type": "buymeacoffee",
"url": "https://buymeacoffee.com/euaaaio"
}
],
"license": "MIT",
"engines": {
"node": "^20.0.0 || >=22.0.0"
},
"peerDependencies": {
"@nanostores/logger": "^0.4.0 || ^1.0.0",
"@vue/devtools-api": ">=7.6.2",
"nanostores": "^0.11.3 || ^1.0.0",
"vue": ">=3.3.1"
},
"peerDependenciesMeta": {
"@nanostores/logger": {
"optional": true
},
"@vue/devtools-api": {
"optional": true
}
}
},
"node_modules/@rolldown/pluginutils": {
"version": "1.0.0-rc.2",
"resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.2.tgz",
@@ -1295,95 +1204,6 @@
"vite": "^5.2.0 || ^6 || ^7"
}
},
"node_modules/@tanstack/match-sorter-utils": {
"version": "8.19.4",
"resolved": "https://registry.npmjs.org/@tanstack/match-sorter-utils/-/match-sorter-utils-8.19.4.tgz",
"integrity": "sha512-Wo1iKt2b9OT7d+YGhvEPD3DXvPv2etTusIMhMUoG7fbhmxcXCtIjJDEygy91Y2JFlwGyjqiBPRozme7UD8hoqg==",
"license": "MIT",
"dependencies": {
"remove-accents": "0.5.0"
},
"engines": {
"node": ">=12"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
}
},
"node_modules/@tanstack/query-core": {
"version": "5.90.20",
"resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.90.20.tgz",
"integrity": "sha512-OMD2HLpNouXEfZJWcKeVKUgQ5n+n3A2JFmBaScpNDUqSrQSjiveC7dKMe53uJUg1nDG16ttFPz2xfilz6i2uVg==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
}
},
"node_modules/@tanstack/vue-query": {
"version": "5.92.9",
"resolved": "https://registry.npmjs.org/@tanstack/vue-query/-/vue-query-5.92.9.tgz",
"integrity": "sha512-jjAZcqKveyX0C4w/6zUqbnqk/XzuxNWaFsWjGTJWULVFizUNeLGME2gf9vVSDclIyiBhR13oZJPPs6fJgfpIJQ==",
"license": "MIT",
"dependencies": {
"@tanstack/match-sorter-utils": "^8.19.4",
"@tanstack/query-core": "5.90.20",
"@vue/devtools-api": "^6.6.3",
"vue-demi": "^0.14.10"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
},
"peerDependencies": {
"@vue/composition-api": "^1.1.2",
"vue": "^2.6.0 || ^3.3.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
}
}
},
"node_modules/@tanstack/vue-query/node_modules/@vue/devtools-api": {
"version": "6.6.4",
"resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.4.tgz",
"integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==",
"license": "MIT"
},
"node_modules/@tanstack/vue-query/node_modules/vue-demi": {
"version": "0.14.10",
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz",
"integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==",
"hasInstallScript": true,
"license": "MIT",
"bin": {
"vue-demi-fix": "bin/vue-demi-fix.js",
"vue-demi-switch": "bin/vue-demi-switch.js"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@vue/composition-api": "^1.0.0-rc.1",
"vue": "^3.0.0-0 || ^2.6.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
}
}
},
"node_modules/@transloadit/prettier-bytes": {
"version": "0.3.5",
"resolved": "https://registry.npmjs.org/@transloadit/prettier-bytes/-/prettier-bytes-0.3.5.tgz",
"integrity": "sha512-xF4A3d/ZyX2LJWeQZREZQw+qFX4TGQ8bGVP97OLRt6sPO6T0TNHBFTuRHOJh7RNmYOBmQ9MHxpolD9bXihpuVA==",
"license": "MIT"
},
"node_modules/@types/estree": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
@@ -1401,166 +1221,6 @@
"undici-types": "~7.16.0"
}
},
"node_modules/@types/retry": {
"version": "0.12.2",
"resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz",
"integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==",
"license": "MIT"
},
"node_modules/@uppy/companion-client": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/@uppy/companion-client/-/companion-client-5.1.1.tgz",
"integrity": "sha512-DzrOWTbIZHvtgAFXBMYHk2wD27NjpBSVhY2tEiEIUhPd2CxbFRZjHM/N3HOt3VwZEAP471QWFLlJRWPcIY3A2Q==",
"license": "MIT",
"dependencies": {
"@uppy/utils": "^7.1.1",
"namespace-emitter": "^2.0.1",
"p-retry": "^6.1.0"
},
"peerDependencies": {
"@uppy/core": "^5.1.1"
}
},
"node_modules/@uppy/components": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@uppy/components/-/components-1.2.0.tgz",
"integrity": "sha512-rtIr+77Rw/q5Vw++xazF1dCg2d4A4zT9CV+ZyN8Rsx8xiIr2CxCR4TaHHBy+WeC0b7Mk6yNuJ0wUa34tFJ6pKg==",
"license": "MIT",
"dependencies": {
"clsx": "^2.1.1",
"dequal": "^2.0.3",
"preact": "^10.26.10",
"pretty-bytes": "^6.1.1"
},
"peerDependencies": {
"@uppy/core": "^5.2.0",
"@uppy/image-editor": "^4.2.0",
"@uppy/screen-capture": "^5.1.0",
"@uppy/webcam": "^5.1.0"
},
"peerDependenciesMeta": {
"@uppy/image-editor": {
"optional": true
},
"@uppy/screen-capture": {
"optional": true
},
"@uppy/webcam": {
"optional": true
}
}
},
"node_modules/@uppy/core": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/@uppy/core/-/core-5.2.0.tgz",
"integrity": "sha512-uvfNyz4cnaplt7LYJmEZHuqOuav0tKp4a9WKJIaH6iIj7XiqYvS2J5SEByexAlUFlzefOAyjzj4Ja2dd/8aMrw==",
"license": "MIT",
"dependencies": {
"@transloadit/prettier-bytes": "^0.3.4",
"@uppy/store-default": "^5.0.0",
"@uppy/utils": "^7.1.4",
"lodash": "^4.17.21",
"mime-match": "^1.0.2",
"namespace-emitter": "^2.0.1",
"nanoid": "^5.0.9",
"preact": "^10.5.13"
}
},
"node_modules/@uppy/core/node_modules/nanoid": {
"version": "5.1.6",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.6.tgz",
"integrity": "sha512-c7+7RQ+dMB5dPwwCp4ee1/iV/q2P6aK1mTZcfr1BTuVlyW9hJYiMPybJCcnBlQtuSmTIWNeazm/zqNoZSSElBg==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"bin": {
"nanoid": "bin/nanoid.js"
},
"engines": {
"node": "^18 || >=20"
}
},
"node_modules/@uppy/locales": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/@uppy/locales/-/locales-5.1.1.tgz",
"integrity": "sha512-zSbDU27JzfdssRJoa5/xmGOsrEtS+2Z9j41weaoCa/NoK4wqZzkFNQ0Z44etbTg3PDVFakZVDu/Z+c+vsJCfdQ==",
"license": "MIT",
"dependencies": {
"@uppy/utils": "^7.1.5"
}
},
"node_modules/@uppy/store-default": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/@uppy/store-default/-/store-default-5.0.0.tgz",
"integrity": "sha512-hQtCSQ1yGiaval/wVYUWquYGDJ+bpQ7e4FhUUAsRQz1x1K+o7NBtjfp63O9I4Ks1WRoKunpkarZ+as09l02cPw==",
"license": "MIT"
},
"node_modules/@uppy/utils": {
"version": "7.1.5",
"resolved": "https://registry.npmjs.org/@uppy/utils/-/utils-7.1.5.tgz",
"integrity": "sha512-Vz4WGTjef6WebECGur4clWjpkET4o3bdvPMj1m2sD5cL+dTt69m+FIE5h5JD3HBMLEPTXPVkrXGMIFcbOYC12Q==",
"license": "MIT",
"dependencies": {
"lodash": "^4.17.21",
"preact": "^10.5.13"
}
},
"node_modules/@uppy/vue": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/@uppy/vue/-/vue-3.2.0.tgz",
"integrity": "sha512-BZiyUZxpadf3uUp8YzgwRZTIde/m9Ne4ILFygJg7ilFq/Qfb1pBVspG9FJoG23RbOiRuxd4JixwFh0gaFdfL+w==",
"license": "MIT",
"dependencies": {
"@uppy/components": "^1.2.0",
"preact": "^10.26.10",
"shallow-equal": "^3.0.0"
},
"peerDependencies": {
"@uppy/core": "^5.2.0",
"@uppy/dashboard": "^5.1.1",
"@uppy/screen-capture": "^5.1.0",
"@uppy/status-bar": "^5.1.0",
"@uppy/webcam": "^5.1.0",
"vue": ">=3.0.0"
},
"peerDependenciesMeta": {
"@uppy/dashboard": {
"optional": true
},
"@uppy/screen-capture": {
"optional": true
},
"@uppy/status-bar": {
"optional": true
},
"@uppy/webcam": {
"optional": true
}
}
},
"node_modules/@uppy/xhr-upload": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/@uppy/xhr-upload/-/xhr-upload-5.1.1.tgz",
"integrity": "sha512-Vp0HWVA8o+niC2uISxPt0pZ+95bHHkk9HzNaUTrff/vq+20Ln68BS2auJhc9ecJzI6SKAlGZ342dcTQ/onw0nA==",
"license": "MIT",
"dependencies": {
"@uppy/companion-client": "^5.1.1",
"@uppy/utils": "^7.1.5"
},
"peerDependencies": {
"@uppy/core": "^5.2.0"
}
},
"node_modules/@viselect/vanilla": {
"version": "3.9.0",
"resolved": "https://registry.npmjs.org/@viselect/vanilla/-/vanilla-3.9.0.tgz",
"integrity": "sha512-E9eBgoi/crJ0SlZMAc+Yst7nU324LZ5LLvcXjzWEcrfllscdpTml2OLOKHC7O8Bbz19OybSLv6VexxnjlJrLxQ==",
"license": "MIT"
},
"node_modules/@vitejs/plugin-vue": {
"version": "6.0.4",
"resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-6.0.4.tgz",
@@ -1877,21 +1537,6 @@
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/classnames": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz",
"integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==",
"license": "MIT"
},
"node_modules/clsx": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
"integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/confbox": {
"version": "0.2.4",
"resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.4.tgz",
@@ -1919,27 +1564,12 @@
"integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
"license": "MIT"
},
"node_modules/debounce": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz",
"integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==",
"license": "MIT"
},
"node_modules/defu": {
"version": "6.1.4",
"resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz",
"integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==",
"license": "MIT"
},
"node_modules/dequal": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
"integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/detect-libc": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
@@ -1950,12 +1580,6 @@
"node": ">=8"
}
},
"node_modules/easy-bem": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/easy-bem/-/easy-bem-1.1.1.tgz",
"integrity": "sha512-GJRqdiy2h+EXy6a8E6R+ubmqUM08BK0FWNq41k24fup6045biQ8NXxoXimiwegMQvFFV3t1emADdGNL1TlS61A==",
"license": "MIT"
},
"node_modules/echarts": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/echarts/-/echarts-6.0.0.tgz",
@@ -2091,18 +1715,6 @@
"integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==",
"license": "MIT"
},
"node_modules/is-network-error": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.3.0.tgz",
"integrity": "sha512-6oIwpsgRfnDiyEDLMay/GqCl3HoAtH5+RUKW29gYkL0QA+ipzpDLA16yQs7/RHCSu+BwgbJaOUqa4A99qNVQVw==",
"license": "MIT",
"engines": {
"node": ">=16"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/is-what": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/is-what/-/is-what-5.5.0.tgz",
@@ -2427,12 +2039,6 @@
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/lodash": {
"version": "4.17.23",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz",
"integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==",
"license": "MIT"
},
"node_modules/lucide-vue-next": {
"version": "0.564.0",
"resolved": "https://registry.npmjs.org/lucide-vue-next/-/lucide-vue-next-0.564.0.tgz",
@@ -2466,15 +2072,6 @@
"url": "https://github.com/sponsors/sxzz"
}
},
"node_modules/mime-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/mime-match/-/mime-match-1.0.2.tgz",
"integrity": "sha512-VXp/ugGDVh3eCLOBCiHZMYWQaTNUHv2IJrut+yXA6+JbLPXHglHwfS/5A5L0ll+jkCY7fIzRJcH6OIunF+c6Cg==",
"license": "ISC",
"dependencies": {
"wildcard": "^1.1.0"
}
},
"node_modules/mitt": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz",
@@ -2516,12 +2113,6 @@
"integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==",
"license": "MIT"
},
"node_modules/namespace-emitter": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/namespace-emitter/-/namespace-emitter-2.0.1.tgz",
"integrity": "sha512-N/sMKHniSDJBjfrkbS/tpkPj4RAbvW3mr8UAzvlMHyun93XEm83IAvhWtJVHo+RHn/oO8Job5YN4b+wRjSVp5g==",
"license": "MIT"
},
"node_modules/nanoid": {
"version": "3.3.11",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
@@ -2540,44 +2131,6 @@
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
"node_modules/nanostores": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/nanostores/-/nanostores-1.1.0.tgz",
"integrity": "sha512-yJBmDJr18xy47dbNVlHcgdPrulSn1nhSE6Ns9vTG+Nx9VPT6iV1MD6aQFp/t52zpf82FhLLTXAXr30NuCnxvwA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"engines": {
"node": "^20.0.0 || >=22.0.0"
}
},
"node_modules/overlayscrollbars": {
"version": "2.14.0",
"resolved": "https://registry.npmjs.org/overlayscrollbars/-/overlayscrollbars-2.14.0.tgz",
"integrity": "sha512-RjV0pqc79kYhQLC3vTcLRb5GLpI1n6qh0Oua3g+bGH4EgNOJHVBGP7u0zZtxoAa0dkHlAqTTSYRb9MMmxNLjig==",
"license": "MIT"
},
"node_modules/p-retry": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.1.tgz",
"integrity": "sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ==",
"license": "MIT",
"dependencies": {
"@types/retry": "0.12.2",
"is-network-error": "^1.0.0",
"retry": "^0.13.1"
},
"engines": {
"node": ">=16.17"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/path-browserify": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz",
@@ -2700,28 +2253,6 @@
"node": "^10 || ^12 || >=14"
}
},
"node_modules/preact": {
"version": "10.28.4",
"resolved": "https://registry.npmjs.org/preact/-/preact-10.28.4.tgz",
"integrity": "sha512-uKFfOHWuSNpRFVTnljsCluEFq57OKT+0QdOiQo8XWnQ/pSvg7OpX5eNOejELXJMWy+BwM2nobz0FkvzmnpCNsQ==",
"license": "MIT",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/preact"
}
},
"node_modules/pretty-bytes": {
"version": "6.1.1",
"resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-6.1.1.tgz",
"integrity": "sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==",
"license": "MIT",
"engines": {
"node": "^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/quansync": {
"version": "0.2.11",
"resolved": "https://registry.npmjs.org/quansync/-/quansync-0.2.11.tgz",
@@ -2751,21 +2282,6 @@
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/remove-accents": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.5.0.tgz",
"integrity": "sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A==",
"license": "MIT"
},
"node_modules/retry": {
"version": "0.13.1",
"resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz",
"integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==",
"license": "MIT",
"engines": {
"node": ">= 4"
}
},
"node_modules/rfdc": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz",
@@ -2823,12 +2339,6 @@
"integrity": "sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==",
"license": "MIT"
},
"node_modules/shallow-equal": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/shallow-equal/-/shallow-equal-3.1.0.tgz",
"integrity": "sha512-pfVOw8QZIXpMbhBWvzBISicvToTiM5WBF1EeAUZDDSb5Dt29yl4AYbyywbJFSEsRUMr7gJaxqCdr4L3tQf9wVg==",
"license": "MIT"
},
"node_modules/source-map-js": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
@@ -2959,16 +2469,6 @@
"url": "https://github.com/sponsors/sxzz"
}
},
"node_modules/vanilla-lazyload": {
"version": "19.1.3",
"resolved": "https://registry.npmjs.org/vanilla-lazyload/-/vanilla-lazyload-19.1.3.tgz",
"integrity": "sha512-bBMERPu2AFJc35krS+8BOhq++c6dRfL6q368lJPnkS5U92fRQagTR3FsNta69/GukfZzDwDEjD5M3U7VuSiCDw==",
"license": "MIT",
"funding": {
"type": "individual",
"url": "https://ko-fi.com/verlok"
}
},
"node_modules/vite": {
"version": "7.3.1",
"resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz",
@@ -3072,24 +2572,6 @@
}
}
},
"node_modules/vue-advanced-cropper": {
"version": "2.8.9",
"resolved": "https://registry.npmjs.org/vue-advanced-cropper/-/vue-advanced-cropper-2.8.9.tgz",
"integrity": "sha512-1jc5gO674kVGpJKekoaol6ZlwaF5VYDLSBwBOUpViW0IOrrRsyLw6XNszjEqgbavvqinlKNS6Kqlom3B5M72Tw==",
"license": "MIT",
"dependencies": {
"classnames": "^2.2.6",
"debounce": "^1.2.0",
"easy-bem": "^1.0.2"
},
"engines": {
"node": ">=8",
"npm": ">=5"
},
"peerDependencies": {
"vue": "^3.0.0"
}
},
"node_modules/vue-router": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-5.0.2.tgz",
@@ -3174,28 +2656,6 @@
"integrity": "sha512-LjgdTytVFXeUgtHZr9WYViYSM/g8MkcTPYDlPa3cDqMirHjKiSZPYd6DoL7pK8AJQr+uWkQvCjHNdiMqsrJs+g==",
"license": "MIT"
},
"node_modules/vue-sonner": {
"version": "2.0.9",
"resolved": "https://registry.npmjs.org/vue-sonner/-/vue-sonner-2.0.9.tgz",
"integrity": "sha512-i6BokNlNDL93fpzNxN/LZSn6D6MzlO+i3qXt6iVZne3x1k7R46d5HlFB4P8tYydhgqOrRbIZEsnRd3kG7qGXyw==",
"license": "MIT",
"peerDependencies": {
"@nuxt/kit": "^4.0.3",
"@nuxt/schema": "^4.0.3",
"nuxt": "^4.0.3"
},
"peerDependenciesMeta": {
"@nuxt/kit": {
"optional": true
},
"@nuxt/schema": {
"optional": true
},
"nuxt": {
"optional": true
}
}
},
"node_modules/vue-tsc": {
"version": "3.2.4",
"resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-3.2.4.tgz",
@@ -3213,57 +2673,12 @@
"typescript": ">=5.0.0"
}
},
"node_modules/vuefinder": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/vuefinder/-/vuefinder-4.1.1.tgz",
"integrity": "sha512-sRrDj7+jrSN4CCQCkBDhc4Z3ZEP2CHa3HibPsByy/yEj2BVH6G7Fn9fSJ3IjGEivYTdURc6DbusidU6Rg6/SqQ==",
"license": "MIT",
"dependencies": {
"@floating-ui/dom": "^1.7.4",
"@nanostores/i18n": "^1.2.2",
"@nanostores/persistent": "^1.1.0",
"@nanostores/vue": "^1.0.1",
"@tanstack/vue-query": "^5.90.2",
"@uppy/core": "^5.0.2",
"@uppy/locales": "^5.0.1",
"@uppy/vue": "^3.1.0",
"@uppy/xhr-upload": "^5.0.1",
"@viselect/vanilla": "^3.9.0",
"mitt": "^3.0.1",
"nanostores": "^1.0.1",
"overlayscrollbars": "^2.12.0",
"vanilla-lazyload": "^19.1.3",
"vue-advanced-cropper": "^2.8.9",
"vue-sonner": "^2.0.9"
},
"engines": {
"node": "^20.19.0 || >=22.12.0"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/n1crack"
},
"peerDependencies": {
"vue": "^3.5.22"
},
"peerDependenciesMeta": {
"vue": {
"optional": false
}
}
},
"node_modules/webpack-virtual-modules": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz",
"integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==",
"license": "MIT"
},
"node_modules/wildcard": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/wildcard/-/wildcard-1.1.2.tgz",
"integrity": "sha512-DXukZJxpHA8LuotRwL0pP1+rS6CS7FF2qStDDE1C7DDg2rLud2PXRMuEDYIPhgEezwnlHNL4c+N6MfMTjCGTng==",
"license": "MIT"
},
"node_modules/yaml": {
"version": "2.8.2",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz",

View File

@@ -14,8 +14,7 @@
"pinia": "^3.0.4",
"pinia-plugin-persistedstate": "^4.7.1",
"vue": "^3.5.25",
"vue-router": "^5.0.2",
"vuefinder": "^4.1.1"
"vue-router": "^5.0.2"
},
"devDependencies": {
"@tailwindcss/vite": "^4.1.18",

View File

@@ -9,7 +9,6 @@
import { ref, computed, watch, onMounted } from 'vue'
import { RouterView, useRoute, useRouter } from 'vue-router'
import { useAuthStore } from '@/stores/auth'
import { useServerStore } from '@/stores/server'
import { useFleetStore } from '@/stores/fleet'
import { useThemeGame, syncActiveGameFromFleet } from '@/composables/useThemeGame'
import { useGameProfile } from '@/config/gameProfiles'
@@ -31,7 +30,6 @@ import type { ActiveGame } from '@/composables/useThemeGame'
const route = useRoute()
const router = useRouter()
const auth = useAuthStore()
const server = useServerStore()
const fleet = useFleetStore()
const { theme, activeGame, setActiveGame, toggleTheme } = useThemeGame()
@@ -106,32 +104,43 @@ function hasVisibleItems(section: NavSection): boolean {
return section.items.some(canShowNavItem)
}
// ---- Agent health ----
const hasAgent = computed(() => server.connection !== null)
// ---- Agent health — driven by the fleet, not the legacy single connection ----
// Real hosts only (the fleet response appends a synthetic '__unassigned__'
// bucket for orphaned instances; summary counts already exclude it).
const realHosts = computed(() => fleet.hosts.filter((h) => h.id !== '__unassigned__'))
const hostCount = computed(() => fleet.summary.host_count)
const onlineHosts = computed(() => fleet.summary.online_host_count)
const instanceCount = computed(() => fleet.summary.instance_count)
const hasAgent = computed(() => hostCount.value > 0)
const agentTone = computed(() => {
const cs = server.connection?.connection_status
if (cs === 'connected') return 'online' as const
if (cs === 'degraded') return 'warn' as const
return 'offline' as const
if (onlineHosts.value === 0) return 'offline' as const
if (onlineHosts.value < hostCount.value) return 'warn' as const
return 'online' as const
})
const agentLabel = computed(() => {
const cs = server.connection?.connection_status
if (cs === 'connected') return 'Healthy'
if (cs === 'degraded') return 'Degraded'
return 'Offline'
if (onlineHosts.value === 0) return 'Offline'
if (onlineHosts.value < hostCount.value) return 'Degraded'
return 'Healthy'
})
const agentName = computed(() => server.connection?.server_ip ?? 'Host agent')
// One host → its hostname; multiple → fleet count.
const agentName = computed(() =>
hostCount.value === 1 ? (realHosts.value[0]?.hostname ?? 'Host agent') : `${hostCount.value} hosts`,
)
const agentMetaLine = computed(() => {
const cs = server.connection?.connection_status
let line = cs === 'connected' ? 'Connected' : server.connection?.companion_last_seen
? `Last seen ${safeDate(server.connection.companion_last_seen)}`
: 'Awaiting first heartbeat'
if (server.stats) {
line += ` · ${server.stats.player_count}/${server.stats.max_players} players`
const insts = `${instanceCount.value} ${instanceCount.value === 1 ? 'instance' : 'instances'}`
if (hostCount.value === 1) {
const h = realHosts.value[0]
const state = h?.status === 'connected'
? 'Connected'
: h?.last_heartbeat_at
? `Last seen ${safeDate(h.last_heartbeat_at)}`
: 'Awaiting first heartbeat'
return `${state} · ${insts}`
}
return line
return `${onlineHosts.value}/${hostCount.value} online · ${insts}`
})
// ---- Topbar ----

View File

@@ -2,12 +2,10 @@ import { createApp } from 'vue'
import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
import { VueFinderPlugin } from 'vuefinder'
import App from './App.vue'
import router from './router'
import { initThemeGame } from './composables/useThemeGame'
import './style.css'
import 'vuefinder/dist/vuefinder.css'
const app = createApp(App)
@@ -16,7 +14,6 @@ pinia.use(piniaPluginPersistedstate)
app.use(pinia)
app.use(router)
app.use(VueFinderPlugin)
// Apply the design-system theming contract (data-theme/data-game on <html>).
initThemeGame()