refactor(team): store runtime identity structurally
This commit is contained in:
parent
571b7fb0f5
commit
372d744879
8 changed files with 603 additions and 166 deletions
|
|
@ -143,6 +143,7 @@
|
||||||
"motion": "12.38.0",
|
"motion": "12.38.0",
|
||||||
"node-diff3": "^3.2.0",
|
"node-diff3": "^3.2.0",
|
||||||
"node-pty": "^1.1.0",
|
"node-pty": "^1.1.0",
|
||||||
|
"pidusage": "4.0.1",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
"react-grid-layout": "^2.2.2",
|
"react-grid-layout": "^2.2.2",
|
||||||
|
|
@ -174,6 +175,7 @@
|
||||||
"@types/hast": "^3.0.4",
|
"@types/hast": "^3.0.4",
|
||||||
"@types/mdast": "^4.0.4",
|
"@types/mdast": "^4.0.4",
|
||||||
"@types/node": "^25.0.7",
|
"@types/node": "^25.0.7",
|
||||||
|
"@types/pidusage": "2.0.5",
|
||||||
"@types/react": "^19.0.0",
|
"@types/react": "^19.0.0",
|
||||||
"@types/react-dom": "^19.0.0",
|
"@types/react-dom": "^19.0.0",
|
||||||
"@types/ssh2": "^1.15.5",
|
"@types/ssh2": "^1.15.5",
|
||||||
|
|
|
||||||
101
pnpm-lock.yaml
101
pnpm-lock.yaml
|
|
@ -239,6 +239,9 @@ importers:
|
||||||
node-pty:
|
node-pty:
|
||||||
specifier: ^1.1.0
|
specifier: ^1.1.0
|
||||||
version: 1.1.0
|
version: 1.1.0
|
||||||
|
pidusage:
|
||||||
|
specifier: 4.0.1
|
||||||
|
version: 4.0.1
|
||||||
react:
|
react:
|
||||||
specifier: ^19.0.0
|
specifier: ^19.0.0
|
||||||
version: 19.2.4
|
version: 19.2.4
|
||||||
|
|
@ -327,6 +330,9 @@ importers:
|
||||||
'@types/node':
|
'@types/node':
|
||||||
specifier: ^25.0.7
|
specifier: ^25.0.7
|
||||||
version: 25.0.7
|
version: 25.0.7
|
||||||
|
'@types/pidusage':
|
||||||
|
specifier: 2.0.5
|
||||||
|
version: 2.0.5
|
||||||
'@types/react':
|
'@types/react':
|
||||||
specifier: ^19.0.0
|
specifier: ^19.0.0
|
||||||
version: 19.2.14
|
version: 19.2.14
|
||||||
|
|
@ -451,13 +457,13 @@ importers:
|
||||||
version: 0.11.3(magicast@0.5.2)(pinia@3.0.4(typescript@5.9.3)(vue@3.5.30(typescript@5.9.3)))
|
version: 0.11.3(magicast@0.5.2)(pinia@3.0.4(typescript@5.9.3)(vue@3.5.30(typescript@5.9.3)))
|
||||||
'@vueuse/nuxt':
|
'@vueuse/nuxt':
|
||||||
specifier: ^10.11.1
|
specifier: ^10.11.1
|
||||||
version: 10.11.1(magicast@0.5.2)(nuxt@3.21.2(@parcel/watcher@2.5.6)(@types/node@25.0.7)(@vue/compiler-sfc@3.5.30)(cac@6.7.14)(db0@0.3.4)(encoding@0.1.13)(eslint@9.39.2(jiti@2.6.1))(idb-keyval@6.2.2)(ioredis@5.10.1)(magicast@0.5.2)(optionator@0.9.4)(rollup-plugin-visualizer@7.0.1(rollup@4.60.0))(rollup@4.60.0)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.7)(jiti@2.6.1)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(yaml@2.8.2))(vue@3.5.30(typescript@5.9.3))
|
version: 10.11.1(magicast@0.5.2)(nuxt@3.21.2(@parcel/watcher@2.5.6)(@types/node@25.0.7)(@vue/compiler-sfc@3.5.30)(cac@6.7.14)(db0@0.3.4)(encoding@0.1.13)(eslint@9.39.2(jiti@2.6.1))(idb-keyval@6.2.2)(ioredis@5.10.1)(magicast@0.5.2)(optionator@0.9.4)(rollup-plugin-visualizer@7.0.1(rollup@4.60.0))(rollup@4.60.0)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(typescript@5.9.3)(vite@5.4.21(@types/node@25.0.7)(sass@1.98.0)(terser@5.46.0))(yaml@2.8.2))(vue@3.5.30(typescript@5.9.3))
|
||||||
nuxt:
|
nuxt:
|
||||||
specifier: ^3.20.2
|
specifier: ^3.20.2
|
||||||
version: 3.21.2(@parcel/watcher@2.5.6)(@types/node@25.0.7)(@vue/compiler-sfc@3.5.30)(cac@6.7.14)(db0@0.3.4)(encoding@0.1.13)(eslint@9.39.2(jiti@2.6.1))(idb-keyval@6.2.2)(ioredis@5.10.1)(magicast@0.5.2)(optionator@0.9.4)(rollup-plugin-visualizer@7.0.1(rollup@4.60.0))(rollup@4.60.0)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.7)(jiti@2.6.1)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(yaml@2.8.2)
|
version: 3.21.2(@parcel/watcher@2.5.6)(@types/node@25.0.7)(@vue/compiler-sfc@3.5.30)(cac@6.7.14)(db0@0.3.4)(encoding@0.1.13)(eslint@9.39.2(jiti@2.6.1))(idb-keyval@6.2.2)(ioredis@5.10.1)(magicast@0.5.2)(optionator@0.9.4)(rollup-plugin-visualizer@7.0.1(rollup@4.60.0))(rollup@4.60.0)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(typescript@5.9.3)(vite@5.4.21(@types/node@25.0.7)(sass@1.98.0)(terser@5.46.0))(yaml@2.8.2)
|
||||||
nuxt-icon:
|
nuxt-icon:
|
||||||
specifier: ^0.6.10
|
specifier: ^0.6.10
|
||||||
version: 0.6.10(magicast@0.5.2)(vite@7.3.1(@types/node@25.0.7)(jiti@2.6.1)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.30(typescript@5.9.3))
|
version: 0.6.10(magicast@0.5.2)(vite@5.4.21(@types/node@25.0.7)(sass@1.98.0)(terser@5.46.0))(vue@3.5.30(typescript@5.9.3))
|
||||||
pinia:
|
pinia:
|
||||||
specifier: ^3.0.4
|
specifier: ^3.0.4
|
||||||
version: 3.0.4(typescript@5.9.3)(vue@3.5.30(typescript@5.9.3))
|
version: 3.0.4(typescript@5.9.3)(vue@3.5.30(typescript@5.9.3))
|
||||||
|
|
@ -482,7 +488,7 @@ importers:
|
||||||
version: 7.4.47
|
version: 7.4.47
|
||||||
'@nuxt/eslint':
|
'@nuxt/eslint':
|
||||||
specifier: ^1.12.1
|
specifier: ^1.12.1
|
||||||
version: 1.15.2(@typescript-eslint/utils@8.57.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(@vue/compiler-sfc@3.5.30)(eslint-import-resolver-node@0.3.9)(eslint@9.39.2(jiti@2.6.1))(magicast@0.5.2)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.7)(jiti@2.6.1)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))
|
version: 1.15.2(@typescript-eslint/utils@8.57.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(@vue/compiler-sfc@3.5.30)(eslint-import-resolver-node@0.3.9)(eslint@9.39.2(jiti@2.6.1))(magicast@0.5.2)(typescript@5.9.3)(vite@5.4.21(@types/node@25.0.7)(sass@1.98.0)(terser@5.46.0))
|
||||||
eslint:
|
eslint:
|
||||||
specifier: ^9.39.2
|
specifier: ^9.39.2
|
||||||
version: 9.39.2(jiti@2.6.1)
|
version: 9.39.2(jiti@2.6.1)
|
||||||
|
|
@ -494,7 +500,7 @@ importers:
|
||||||
version: 1.98.0
|
version: 1.98.0
|
||||||
vite-plugin-vuetify:
|
vite-plugin-vuetify:
|
||||||
specifier: ^2.1.3
|
specifier: ^2.1.3
|
||||||
version: 2.1.3(vite@7.3.1(@types/node@25.0.7)(jiti@2.6.1)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.30(typescript@5.9.3))(vuetify@3.12.3)
|
version: 2.1.3(vite@5.4.21(@types/node@25.0.7)(sass@1.98.0)(terser@5.46.0))(vue@3.5.30(typescript@5.9.3))(vuetify@3.12.3)
|
||||||
|
|
||||||
mcp-server:
|
mcp-server:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
@ -4353,6 +4359,9 @@ packages:
|
||||||
'@types/pg@8.15.6':
|
'@types/pg@8.15.6':
|
||||||
resolution: {integrity: sha512-NoaMtzhxOrubeL/7UZuNTrejB4MPAJ0RpxZqXQf2qXuVlTPuG6Y8p4u9dKRaue4yjmC7ZhzVO2/Yyyn25znrPQ==}
|
resolution: {integrity: sha512-NoaMtzhxOrubeL/7UZuNTrejB4MPAJ0RpxZqXQf2qXuVlTPuG6Y8p4u9dKRaue4yjmC7ZhzVO2/Yyyn25znrPQ==}
|
||||||
|
|
||||||
|
'@types/pidusage@2.0.5':
|
||||||
|
resolution: {integrity: sha512-MIiyZI4/MK9UGUXWt0jJcCZhVw7YdhBuTOuqP/BjuLDLZ2PmmViMIQgZiWxtaMicQfAz/kMrZ5T7PKxFSkTeUA==}
|
||||||
|
|
||||||
'@types/plist@3.0.5':
|
'@types/plist@3.0.5':
|
||||||
resolution: {integrity: sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA==}
|
resolution: {integrity: sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA==}
|
||||||
|
|
||||||
|
|
@ -8591,6 +8600,10 @@ packages:
|
||||||
engines: {node: '>=0.10'}
|
engines: {node: '>=0.10'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
pidusage@4.0.1:
|
||||||
|
resolution: {integrity: sha512-yCH2dtLHfEBnzlHUJymR/Z1nN2ePG3m392Mv8TFlTP1B0xkpMQNHAnfkY0n2tAi6ceKO6YWhxYfZ96V4vVkh/g==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
pify@2.3.0:
|
pify@2.3.0:
|
||||||
resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==}
|
resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
@ -12589,20 +12602,20 @@ snapshots:
|
||||||
|
|
||||||
'@nuxt/devalue@2.0.2': {}
|
'@nuxt/devalue@2.0.2': {}
|
||||||
|
|
||||||
'@nuxt/devtools-kit@1.7.0(magicast@0.5.2)(vite@7.3.1(@types/node@25.0.7)(jiti@2.6.1)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))':
|
'@nuxt/devtools-kit@1.7.0(magicast@0.5.2)(vite@5.4.21(@types/node@25.0.7)(sass@1.98.0)(terser@5.46.0))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@nuxt/kit': 3.21.2(magicast@0.5.2)
|
'@nuxt/kit': 3.21.2(magicast@0.5.2)
|
||||||
'@nuxt/schema': 3.21.2
|
'@nuxt/schema': 3.21.2
|
||||||
execa: 7.2.0
|
execa: 7.2.0
|
||||||
vite: 7.3.1(@types/node@25.0.7)(jiti@2.6.1)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)
|
vite: 5.4.21(@types/node@25.0.7)(sass@1.98.0)(terser@5.46.0)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- magicast
|
- magicast
|
||||||
|
|
||||||
'@nuxt/devtools-kit@3.2.4(magicast@0.5.2)(vite@7.3.1(@types/node@25.0.7)(jiti@2.6.1)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))':
|
'@nuxt/devtools-kit@3.2.4(magicast@0.5.2)(vite@5.4.21(@types/node@25.0.7)(sass@1.98.0)(terser@5.46.0))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@nuxt/kit': 4.4.2(magicast@0.5.2)
|
'@nuxt/kit': 4.4.2(magicast@0.5.2)
|
||||||
execa: 8.0.1
|
execa: 8.0.1
|
||||||
vite: 7.3.1(@types/node@25.0.7)(jiti@2.6.1)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)
|
vite: 5.4.21(@types/node@25.0.7)(sass@1.98.0)(terser@5.46.0)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- magicast
|
- magicast
|
||||||
|
|
||||||
|
|
@ -12617,9 +12630,9 @@ snapshots:
|
||||||
pkg-types: 2.3.0
|
pkg-types: 2.3.0
|
||||||
semver: 7.7.4
|
semver: 7.7.4
|
||||||
|
|
||||||
'@nuxt/devtools@3.2.4(vite@7.3.1(@types/node@25.0.7)(jiti@2.6.1)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.30(typescript@5.9.3))':
|
'@nuxt/devtools@3.2.4(vite@5.4.21(@types/node@25.0.7)(sass@1.98.0)(terser@5.46.0))(vue@3.5.30(typescript@5.9.3))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@nuxt/devtools-kit': 3.2.4(magicast@0.5.2)(vite@7.3.1(@types/node@25.0.7)(jiti@2.6.1)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))
|
'@nuxt/devtools-kit': 3.2.4(magicast@0.5.2)(vite@5.4.21(@types/node@25.0.7)(sass@1.98.0)(terser@5.46.0))
|
||||||
'@nuxt/devtools-wizard': 3.2.4
|
'@nuxt/devtools-wizard': 3.2.4
|
||||||
'@nuxt/kit': 4.4.2(magicast@0.5.2)
|
'@nuxt/kit': 4.4.2(magicast@0.5.2)
|
||||||
'@vue/devtools-core': 8.1.0(vue@3.5.30(typescript@5.9.3))
|
'@vue/devtools-core': 8.1.0(vue@3.5.30(typescript@5.9.3))
|
||||||
|
|
@ -12647,9 +12660,9 @@ snapshots:
|
||||||
sirv: 3.0.2
|
sirv: 3.0.2
|
||||||
structured-clone-es: 2.0.0
|
structured-clone-es: 2.0.0
|
||||||
tinyglobby: 0.2.15
|
tinyglobby: 0.2.15
|
||||||
vite: 7.3.1(@types/node@25.0.7)(jiti@2.6.1)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)
|
vite: 5.4.21(@types/node@25.0.7)(sass@1.98.0)(terser@5.46.0)
|
||||||
vite-plugin-inspect: 11.3.3(@nuxt/kit@4.4.2(magicast@0.5.2))(vite@7.3.1(@types/node@25.0.7)(jiti@2.6.1)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))
|
vite-plugin-inspect: 11.3.3(@nuxt/kit@4.4.2(magicast@0.5.2))(vite@5.4.21(@types/node@25.0.7)(sass@1.98.0)(terser@5.46.0))
|
||||||
vite-plugin-vue-tracer: 1.3.0(vite@7.3.1(@types/node@25.0.7)(jiti@2.6.1)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.30(typescript@5.9.3))
|
vite-plugin-vue-tracer: 1.3.0(vite@5.4.21(@types/node@25.0.7)(sass@1.98.0)(terser@5.46.0))(vue@3.5.30(typescript@5.9.3))
|
||||||
which: 6.0.1
|
which: 6.0.1
|
||||||
ws: 8.20.0
|
ws: 8.20.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
|
|
@ -12698,10 +12711,10 @@ snapshots:
|
||||||
- supports-color
|
- supports-color
|
||||||
- typescript
|
- typescript
|
||||||
|
|
||||||
'@nuxt/eslint@1.15.2(@typescript-eslint/utils@8.57.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(@vue/compiler-sfc@3.5.30)(eslint-import-resolver-node@0.3.9)(eslint@9.39.2(jiti@2.6.1))(magicast@0.5.2)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.7)(jiti@2.6.1)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))':
|
'@nuxt/eslint@1.15.2(@typescript-eslint/utils@8.57.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(@vue/compiler-sfc@3.5.30)(eslint-import-resolver-node@0.3.9)(eslint@9.39.2(jiti@2.6.1))(magicast@0.5.2)(typescript@5.9.3)(vite@5.4.21(@types/node@25.0.7)(sass@1.98.0)(terser@5.46.0))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@eslint/config-inspector': 1.5.0(eslint@9.39.2(jiti@2.6.1))
|
'@eslint/config-inspector': 1.5.0(eslint@9.39.2(jiti@2.6.1))
|
||||||
'@nuxt/devtools-kit': 3.2.4(magicast@0.5.2)(vite@7.3.1(@types/node@25.0.7)(jiti@2.6.1)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))
|
'@nuxt/devtools-kit': 3.2.4(magicast@0.5.2)(vite@5.4.21(@types/node@25.0.7)(sass@1.98.0)(terser@5.46.0))
|
||||||
'@nuxt/eslint-config': 1.15.2(@typescript-eslint/utils@8.57.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(@vue/compiler-sfc@3.5.30)(eslint-import-resolver-node@0.3.9)(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
|
'@nuxt/eslint-config': 1.15.2(@typescript-eslint/utils@8.57.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(@vue/compiler-sfc@3.5.30)(eslint-import-resolver-node@0.3.9)(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
|
||||||
'@nuxt/eslint-plugin': 1.15.2(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
|
'@nuxt/eslint-plugin': 1.15.2(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
|
||||||
'@nuxt/kit': 4.4.2(magicast@0.5.2)
|
'@nuxt/kit': 4.4.2(magicast@0.5.2)
|
||||||
|
|
@ -12777,7 +12790,7 @@ snapshots:
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- magicast
|
- magicast
|
||||||
|
|
||||||
'@nuxt/nitro-server@3.21.2(db0@0.3.4)(encoding@0.1.13)(idb-keyval@6.2.2)(ioredis@5.10.1)(magicast@0.5.2)(nuxt@3.21.2(@parcel/watcher@2.5.6)(@types/node@25.0.7)(@vue/compiler-sfc@3.5.30)(cac@6.7.14)(db0@0.3.4)(encoding@0.1.13)(eslint@9.39.2(jiti@2.6.1))(idb-keyval@6.2.2)(ioredis@5.10.1)(magicast@0.5.2)(optionator@0.9.4)(rollup-plugin-visualizer@7.0.1(rollup@4.60.0))(rollup@4.60.0)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.7)(jiti@2.6.1)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(yaml@2.8.2))(typescript@5.9.3)':
|
'@nuxt/nitro-server@3.21.2(db0@0.3.4)(encoding@0.1.13)(idb-keyval@6.2.2)(ioredis@5.10.1)(magicast@0.5.2)(nuxt@3.21.2(@parcel/watcher@2.5.6)(@types/node@25.0.7)(@vue/compiler-sfc@3.5.30)(cac@6.7.14)(db0@0.3.4)(encoding@0.1.13)(eslint@9.39.2(jiti@2.6.1))(idb-keyval@6.2.2)(ioredis@5.10.1)(magicast@0.5.2)(optionator@0.9.4)(rollup-plugin-visualizer@7.0.1(rollup@4.60.0))(rollup@4.60.0)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(typescript@5.9.3)(vite@5.4.21(@types/node@25.0.7)(sass@1.98.0)(terser@5.46.0))(yaml@2.8.2))(typescript@5.9.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@nuxt/devalue': 2.0.2
|
'@nuxt/devalue': 2.0.2
|
||||||
'@nuxt/kit': 3.21.2(magicast@0.5.2)
|
'@nuxt/kit': 3.21.2(magicast@0.5.2)
|
||||||
|
|
@ -12795,7 +12808,7 @@ snapshots:
|
||||||
klona: 2.0.6
|
klona: 2.0.6
|
||||||
mocked-exports: 0.1.1
|
mocked-exports: 0.1.1
|
||||||
nitropack: 2.13.2(encoding@0.1.13)(idb-keyval@6.2.2)
|
nitropack: 2.13.2(encoding@0.1.13)(idb-keyval@6.2.2)
|
||||||
nuxt: 3.21.2(@parcel/watcher@2.5.6)(@types/node@25.0.7)(@vue/compiler-sfc@3.5.30)(cac@6.7.14)(db0@0.3.4)(encoding@0.1.13)(eslint@9.39.2(jiti@2.6.1))(idb-keyval@6.2.2)(ioredis@5.10.1)(magicast@0.5.2)(optionator@0.9.4)(rollup-plugin-visualizer@7.0.1(rollup@4.60.0))(rollup@4.60.0)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.7)(jiti@2.6.1)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(yaml@2.8.2)
|
nuxt: 3.21.2(@parcel/watcher@2.5.6)(@types/node@25.0.7)(@vue/compiler-sfc@3.5.30)(cac@6.7.14)(db0@0.3.4)(encoding@0.1.13)(eslint@9.39.2(jiti@2.6.1))(idb-keyval@6.2.2)(ioredis@5.10.1)(magicast@0.5.2)(optionator@0.9.4)(rollup-plugin-visualizer@7.0.1(rollup@4.60.0))(rollup@4.60.0)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(typescript@5.9.3)(vite@5.4.21(@types/node@25.0.7)(sass@1.98.0)(terser@5.46.0))(yaml@2.8.2)
|
||||||
ohash: 2.0.11
|
ohash: 2.0.11
|
||||||
pathe: 2.0.3
|
pathe: 2.0.3
|
||||||
pkg-types: 2.3.0
|
pkg-types: 2.3.0
|
||||||
|
|
@ -12860,7 +12873,7 @@ snapshots:
|
||||||
rc9: 3.0.0
|
rc9: 3.0.0
|
||||||
std-env: 3.10.0
|
std-env: 3.10.0
|
||||||
|
|
||||||
'@nuxt/vite-builder@3.21.2(@types/node@25.0.7)(eslint@9.39.2(jiti@2.6.1))(magicast@0.5.2)(nuxt@3.21.2(@parcel/watcher@2.5.6)(@types/node@25.0.7)(@vue/compiler-sfc@3.5.30)(cac@6.7.14)(db0@0.3.4)(encoding@0.1.13)(eslint@9.39.2(jiti@2.6.1))(idb-keyval@6.2.2)(ioredis@5.10.1)(magicast@0.5.2)(optionator@0.9.4)(rollup-plugin-visualizer@7.0.1(rollup@4.60.0))(rollup@4.60.0)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.7)(jiti@2.6.1)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(yaml@2.8.2))(optionator@0.9.4)(rollup-plugin-visualizer@7.0.1(rollup@4.60.0))(rollup@4.60.0)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(typescript@5.9.3)(vue@3.5.30(typescript@5.9.3))(yaml@2.8.2)':
|
'@nuxt/vite-builder@3.21.2(@types/node@25.0.7)(eslint@9.39.2(jiti@2.6.1))(magicast@0.5.2)(nuxt@3.21.2(@parcel/watcher@2.5.6)(@types/node@25.0.7)(@vue/compiler-sfc@3.5.30)(cac@6.7.14)(db0@0.3.4)(encoding@0.1.13)(eslint@9.39.2(jiti@2.6.1))(idb-keyval@6.2.2)(ioredis@5.10.1)(magicast@0.5.2)(optionator@0.9.4)(rollup-plugin-visualizer@7.0.1(rollup@4.60.0))(rollup@4.60.0)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(typescript@5.9.3)(vite@5.4.21(@types/node@25.0.7)(sass@1.98.0)(terser@5.46.0))(yaml@2.8.2))(optionator@0.9.4)(rollup-plugin-visualizer@7.0.1(rollup@4.60.0))(rollup@4.60.0)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(typescript@5.9.3)(vue@3.5.30(typescript@5.9.3))(yaml@2.8.2)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@nuxt/kit': 3.21.2(magicast@0.5.2)
|
'@nuxt/kit': 3.21.2(magicast@0.5.2)
|
||||||
'@rollup/plugin-replace': 6.0.3(rollup@4.60.0)
|
'@rollup/plugin-replace': 6.0.3(rollup@4.60.0)
|
||||||
|
|
@ -12879,7 +12892,7 @@ snapshots:
|
||||||
magic-string: 0.30.21
|
magic-string: 0.30.21
|
||||||
mlly: 1.8.2
|
mlly: 1.8.2
|
||||||
mocked-exports: 0.1.1
|
mocked-exports: 0.1.1
|
||||||
nuxt: 3.21.2(@parcel/watcher@2.5.6)(@types/node@25.0.7)(@vue/compiler-sfc@3.5.30)(cac@6.7.14)(db0@0.3.4)(encoding@0.1.13)(eslint@9.39.2(jiti@2.6.1))(idb-keyval@6.2.2)(ioredis@5.10.1)(magicast@0.5.2)(optionator@0.9.4)(rollup-plugin-visualizer@7.0.1(rollup@4.60.0))(rollup@4.60.0)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.7)(jiti@2.6.1)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(yaml@2.8.2)
|
nuxt: 3.21.2(@parcel/watcher@2.5.6)(@types/node@25.0.7)(@vue/compiler-sfc@3.5.30)(cac@6.7.14)(db0@0.3.4)(encoding@0.1.13)(eslint@9.39.2(jiti@2.6.1))(idb-keyval@6.2.2)(ioredis@5.10.1)(magicast@0.5.2)(optionator@0.9.4)(rollup-plugin-visualizer@7.0.1(rollup@4.60.0))(rollup@4.60.0)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(typescript@5.9.3)(vite@5.4.21(@types/node@25.0.7)(sass@1.98.0)(terser@5.46.0))(yaml@2.8.2)
|
||||||
nypm: 0.6.5
|
nypm: 0.6.5
|
||||||
ohash: 2.0.11
|
ohash: 2.0.11
|
||||||
pathe: 2.0.3
|
pathe: 2.0.3
|
||||||
|
|
@ -15002,6 +15015,8 @@ snapshots:
|
||||||
pg-protocol: 1.13.0
|
pg-protocol: 1.13.0
|
||||||
pg-types: 2.2.0
|
pg-types: 2.2.0
|
||||||
|
|
||||||
|
'@types/pidusage@2.0.5': {}
|
||||||
|
|
||||||
'@types/plist@3.0.5':
|
'@types/plist@3.0.5':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/node': 25.0.7
|
'@types/node': 25.0.7
|
||||||
|
|
@ -15595,13 +15610,13 @@ snapshots:
|
||||||
|
|
||||||
'@vueuse/metadata@10.11.1': {}
|
'@vueuse/metadata@10.11.1': {}
|
||||||
|
|
||||||
'@vueuse/nuxt@10.11.1(magicast@0.5.2)(nuxt@3.21.2(@parcel/watcher@2.5.6)(@types/node@25.0.7)(@vue/compiler-sfc@3.5.30)(cac@6.7.14)(db0@0.3.4)(encoding@0.1.13)(eslint@9.39.2(jiti@2.6.1))(idb-keyval@6.2.2)(ioredis@5.10.1)(magicast@0.5.2)(optionator@0.9.4)(rollup-plugin-visualizer@7.0.1(rollup@4.60.0))(rollup@4.60.0)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.7)(jiti@2.6.1)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(yaml@2.8.2))(vue@3.5.30(typescript@5.9.3))':
|
'@vueuse/nuxt@10.11.1(magicast@0.5.2)(nuxt@3.21.2(@parcel/watcher@2.5.6)(@types/node@25.0.7)(@vue/compiler-sfc@3.5.30)(cac@6.7.14)(db0@0.3.4)(encoding@0.1.13)(eslint@9.39.2(jiti@2.6.1))(idb-keyval@6.2.2)(ioredis@5.10.1)(magicast@0.5.2)(optionator@0.9.4)(rollup-plugin-visualizer@7.0.1(rollup@4.60.0))(rollup@4.60.0)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(typescript@5.9.3)(vite@5.4.21(@types/node@25.0.7)(sass@1.98.0)(terser@5.46.0))(yaml@2.8.2))(vue@3.5.30(typescript@5.9.3))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@nuxt/kit': 3.21.2(magicast@0.5.2)
|
'@nuxt/kit': 3.21.2(magicast@0.5.2)
|
||||||
'@vueuse/core': 10.11.1(vue@3.5.30(typescript@5.9.3))
|
'@vueuse/core': 10.11.1(vue@3.5.30(typescript@5.9.3))
|
||||||
'@vueuse/metadata': 10.11.1
|
'@vueuse/metadata': 10.11.1
|
||||||
local-pkg: 0.5.1
|
local-pkg: 0.5.1
|
||||||
nuxt: 3.21.2(@parcel/watcher@2.5.6)(@types/node@25.0.7)(@vue/compiler-sfc@3.5.30)(cac@6.7.14)(db0@0.3.4)(encoding@0.1.13)(eslint@9.39.2(jiti@2.6.1))(idb-keyval@6.2.2)(ioredis@5.10.1)(magicast@0.5.2)(optionator@0.9.4)(rollup-plugin-visualizer@7.0.1(rollup@4.60.0))(rollup@4.60.0)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.7)(jiti@2.6.1)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(yaml@2.8.2)
|
nuxt: 3.21.2(@parcel/watcher@2.5.6)(@types/node@25.0.7)(@vue/compiler-sfc@3.5.30)(cac@6.7.14)(db0@0.3.4)(encoding@0.1.13)(eslint@9.39.2(jiti@2.6.1))(idb-keyval@6.2.2)(ioredis@5.10.1)(magicast@0.5.2)(optionator@0.9.4)(rollup-plugin-visualizer@7.0.1(rollup@4.60.0))(rollup@4.60.0)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(typescript@5.9.3)(vite@5.4.21(@types/node@25.0.7)(sass@1.98.0)(terser@5.46.0))(yaml@2.8.2)
|
||||||
vue-demi: 0.14.10(vue@3.5.30(typescript@5.9.3))
|
vue-demi: 0.14.10(vue@3.5.30(typescript@5.9.3))
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@vue/composition-api'
|
- '@vue/composition-api'
|
||||||
|
|
@ -20143,27 +20158,27 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
boolbase: 1.0.0
|
boolbase: 1.0.0
|
||||||
|
|
||||||
nuxt-icon@0.6.10(magicast@0.5.2)(vite@7.3.1(@types/node@25.0.7)(jiti@2.6.1)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.30(typescript@5.9.3)):
|
nuxt-icon@0.6.10(magicast@0.5.2)(vite@5.4.21(@types/node@25.0.7)(sass@1.98.0)(terser@5.46.0))(vue@3.5.30(typescript@5.9.3)):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@iconify/collections': 1.0.665
|
'@iconify/collections': 1.0.665
|
||||||
'@iconify/vue': 4.3.0(vue@3.5.30(typescript@5.9.3))
|
'@iconify/vue': 4.3.0(vue@3.5.30(typescript@5.9.3))
|
||||||
'@nuxt/devtools-kit': 1.7.0(magicast@0.5.2)(vite@7.3.1(@types/node@25.0.7)(jiti@2.6.1)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))
|
'@nuxt/devtools-kit': 1.7.0(magicast@0.5.2)(vite@5.4.21(@types/node@25.0.7)(sass@1.98.0)(terser@5.46.0))
|
||||||
'@nuxt/kit': 3.21.2(magicast@0.5.2)
|
'@nuxt/kit': 3.21.2(magicast@0.5.2)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- magicast
|
- magicast
|
||||||
- vite
|
- vite
|
||||||
- vue
|
- vue
|
||||||
|
|
||||||
nuxt@3.21.2(@parcel/watcher@2.5.6)(@types/node@25.0.7)(@vue/compiler-sfc@3.5.30)(cac@6.7.14)(db0@0.3.4)(encoding@0.1.13)(eslint@9.39.2(jiti@2.6.1))(idb-keyval@6.2.2)(ioredis@5.10.1)(magicast@0.5.2)(optionator@0.9.4)(rollup-plugin-visualizer@7.0.1(rollup@4.60.0))(rollup@4.60.0)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.7)(jiti@2.6.1)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(yaml@2.8.2):
|
nuxt@3.21.2(@parcel/watcher@2.5.6)(@types/node@25.0.7)(@vue/compiler-sfc@3.5.30)(cac@6.7.14)(db0@0.3.4)(encoding@0.1.13)(eslint@9.39.2(jiti@2.6.1))(idb-keyval@6.2.2)(ioredis@5.10.1)(magicast@0.5.2)(optionator@0.9.4)(rollup-plugin-visualizer@7.0.1(rollup@4.60.0))(rollup@4.60.0)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(typescript@5.9.3)(vite@5.4.21(@types/node@25.0.7)(sass@1.98.0)(terser@5.46.0))(yaml@2.8.2):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@dxup/nuxt': 0.4.0(magicast@0.5.2)(typescript@5.9.3)
|
'@dxup/nuxt': 0.4.0(magicast@0.5.2)(typescript@5.9.3)
|
||||||
'@nuxt/cli': 3.34.0(@nuxt/schema@3.21.2)(cac@6.7.14)(magicast@0.5.2)
|
'@nuxt/cli': 3.34.0(@nuxt/schema@3.21.2)(cac@6.7.14)(magicast@0.5.2)
|
||||||
'@nuxt/devtools': 3.2.4(vite@7.3.1(@types/node@25.0.7)(jiti@2.6.1)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.30(typescript@5.9.3))
|
'@nuxt/devtools': 3.2.4(vite@5.4.21(@types/node@25.0.7)(sass@1.98.0)(terser@5.46.0))(vue@3.5.30(typescript@5.9.3))
|
||||||
'@nuxt/kit': 3.21.2(magicast@0.5.2)
|
'@nuxt/kit': 3.21.2(magicast@0.5.2)
|
||||||
'@nuxt/nitro-server': 3.21.2(db0@0.3.4)(encoding@0.1.13)(idb-keyval@6.2.2)(ioredis@5.10.1)(magicast@0.5.2)(nuxt@3.21.2(@parcel/watcher@2.5.6)(@types/node@25.0.7)(@vue/compiler-sfc@3.5.30)(cac@6.7.14)(db0@0.3.4)(encoding@0.1.13)(eslint@9.39.2(jiti@2.6.1))(idb-keyval@6.2.2)(ioredis@5.10.1)(magicast@0.5.2)(optionator@0.9.4)(rollup-plugin-visualizer@7.0.1(rollup@4.60.0))(rollup@4.60.0)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.7)(jiti@2.6.1)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(yaml@2.8.2))(typescript@5.9.3)
|
'@nuxt/nitro-server': 3.21.2(db0@0.3.4)(encoding@0.1.13)(idb-keyval@6.2.2)(ioredis@5.10.1)(magicast@0.5.2)(nuxt@3.21.2(@parcel/watcher@2.5.6)(@types/node@25.0.7)(@vue/compiler-sfc@3.5.30)(cac@6.7.14)(db0@0.3.4)(encoding@0.1.13)(eslint@9.39.2(jiti@2.6.1))(idb-keyval@6.2.2)(ioredis@5.10.1)(magicast@0.5.2)(optionator@0.9.4)(rollup-plugin-visualizer@7.0.1(rollup@4.60.0))(rollup@4.60.0)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(typescript@5.9.3)(vite@5.4.21(@types/node@25.0.7)(sass@1.98.0)(terser@5.46.0))(yaml@2.8.2))(typescript@5.9.3)
|
||||||
'@nuxt/schema': 3.21.2
|
'@nuxt/schema': 3.21.2
|
||||||
'@nuxt/telemetry': 2.7.0(@nuxt/kit@3.21.2(magicast@0.5.2))
|
'@nuxt/telemetry': 2.7.0(@nuxt/kit@3.21.2(magicast@0.5.2))
|
||||||
'@nuxt/vite-builder': 3.21.2(@types/node@25.0.7)(eslint@9.39.2(jiti@2.6.1))(magicast@0.5.2)(nuxt@3.21.2(@parcel/watcher@2.5.6)(@types/node@25.0.7)(@vue/compiler-sfc@3.5.30)(cac@6.7.14)(db0@0.3.4)(encoding@0.1.13)(eslint@9.39.2(jiti@2.6.1))(idb-keyval@6.2.2)(ioredis@5.10.1)(magicast@0.5.2)(optionator@0.9.4)(rollup-plugin-visualizer@7.0.1(rollup@4.60.0))(rollup@4.60.0)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.7)(jiti@2.6.1)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(yaml@2.8.2))(optionator@0.9.4)(rollup-plugin-visualizer@7.0.1(rollup@4.60.0))(rollup@4.60.0)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(typescript@5.9.3)(vue@3.5.30(typescript@5.9.3))(yaml@2.8.2)
|
'@nuxt/vite-builder': 3.21.2(@types/node@25.0.7)(eslint@9.39.2(jiti@2.6.1))(magicast@0.5.2)(nuxt@3.21.2(@parcel/watcher@2.5.6)(@types/node@25.0.7)(@vue/compiler-sfc@3.5.30)(cac@6.7.14)(db0@0.3.4)(encoding@0.1.13)(eslint@9.39.2(jiti@2.6.1))(idb-keyval@6.2.2)(ioredis@5.10.1)(magicast@0.5.2)(optionator@0.9.4)(rollup-plugin-visualizer@7.0.1(rollup@4.60.0))(rollup@4.60.0)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(typescript@5.9.3)(vite@5.4.21(@types/node@25.0.7)(sass@1.98.0)(terser@5.46.0))(yaml@2.8.2))(optionator@0.9.4)(rollup-plugin-visualizer@7.0.1(rollup@4.60.0))(rollup@4.60.0)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(typescript@5.9.3)(vue@3.5.30(typescript@5.9.3))(yaml@2.8.2)
|
||||||
'@unhead/vue': 2.1.12(vue@3.5.30(typescript@5.9.3))
|
'@unhead/vue': 2.1.12(vue@3.5.30(typescript@5.9.3))
|
||||||
'@vue/shared': 3.5.30
|
'@vue/shared': 3.5.30
|
||||||
c12: 3.3.3(magicast@0.5.2)
|
c12: 3.3.3(magicast@0.5.2)
|
||||||
|
|
@ -20647,6 +20662,10 @@ snapshots:
|
||||||
|
|
||||||
pidtree@0.6.0: {}
|
pidtree@0.6.0: {}
|
||||||
|
|
||||||
|
pidusage@4.0.1:
|
||||||
|
dependencies:
|
||||||
|
safe-buffer: 5.2.1
|
||||||
|
|
||||||
pify@2.3.0: {}
|
pify@2.3.0: {}
|
||||||
|
|
||||||
pinia@3.0.4(typescript@5.9.3)(vue@3.5.30(typescript@5.9.3)):
|
pinia@3.0.4(typescript@5.9.3)(vue@3.5.30(typescript@5.9.3)):
|
||||||
|
|
@ -22710,15 +22729,15 @@ snapshots:
|
||||||
'@types/unist': 3.0.3
|
'@types/unist': 3.0.3
|
||||||
vfile-message: 4.0.3
|
vfile-message: 4.0.3
|
||||||
|
|
||||||
vite-dev-rpc@1.1.0(vite@7.3.1(@types/node@25.0.7)(jiti@2.6.1)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)):
|
vite-dev-rpc@1.1.0(vite@5.4.21(@types/node@25.0.7)(sass@1.98.0)(terser@5.46.0)):
|
||||||
dependencies:
|
dependencies:
|
||||||
birpc: 2.9.0
|
birpc: 2.9.0
|
||||||
vite: 7.3.1(@types/node@25.0.7)(jiti@2.6.1)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)
|
vite: 5.4.21(@types/node@25.0.7)(sass@1.98.0)(terser@5.46.0)
|
||||||
vite-hot-client: 2.1.0(vite@7.3.1(@types/node@25.0.7)(jiti@2.6.1)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))
|
vite-hot-client: 2.1.0(vite@5.4.21(@types/node@25.0.7)(sass@1.98.0)(terser@5.46.0))
|
||||||
|
|
||||||
vite-hot-client@2.1.0(vite@7.3.1(@types/node@25.0.7)(jiti@2.6.1)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)):
|
vite-hot-client@2.1.0(vite@5.4.21(@types/node@25.0.7)(sass@1.98.0)(terser@5.46.0)):
|
||||||
dependencies:
|
dependencies:
|
||||||
vite: 7.3.1(@types/node@25.0.7)(jiti@2.6.1)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)
|
vite: 5.4.21(@types/node@25.0.7)(sass@1.98.0)(terser@5.46.0)
|
||||||
|
|
||||||
vite-node@3.2.4(@types/node@22.19.15)(sass@1.98.0)(terser@5.46.0):
|
vite-node@3.2.4(@types/node@22.19.15)(sass@1.98.0)(terser@5.46.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
@ -22792,7 +22811,7 @@ snapshots:
|
||||||
optionator: 0.9.4
|
optionator: 0.9.4
|
||||||
typescript: 5.9.3
|
typescript: 5.9.3
|
||||||
|
|
||||||
vite-plugin-inspect@11.3.3(@nuxt/kit@4.4.2(magicast@0.5.2))(vite@7.3.1(@types/node@25.0.7)(jiti@2.6.1)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)):
|
vite-plugin-inspect@11.3.3(@nuxt/kit@4.4.2(magicast@0.5.2))(vite@5.4.21(@types/node@25.0.7)(sass@1.98.0)(terser@5.46.0)):
|
||||||
dependencies:
|
dependencies:
|
||||||
ansis: 4.2.0
|
ansis: 4.2.0
|
||||||
debug: 4.4.3
|
debug: 4.4.3
|
||||||
|
|
@ -22802,29 +22821,29 @@ snapshots:
|
||||||
perfect-debounce: 2.1.0
|
perfect-debounce: 2.1.0
|
||||||
sirv: 3.0.2
|
sirv: 3.0.2
|
||||||
unplugin-utils: 0.3.1
|
unplugin-utils: 0.3.1
|
||||||
vite: 7.3.1(@types/node@25.0.7)(jiti@2.6.1)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)
|
vite: 5.4.21(@types/node@25.0.7)(sass@1.98.0)(terser@5.46.0)
|
||||||
vite-dev-rpc: 1.1.0(vite@7.3.1(@types/node@25.0.7)(jiti@2.6.1)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))
|
vite-dev-rpc: 1.1.0(vite@5.4.21(@types/node@25.0.7)(sass@1.98.0)(terser@5.46.0))
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@nuxt/kit': 4.4.2(magicast@0.5.2)
|
'@nuxt/kit': 4.4.2(magicast@0.5.2)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
vite-plugin-vue-tracer@1.3.0(vite@7.3.1(@types/node@25.0.7)(jiti@2.6.1)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.30(typescript@5.9.3)):
|
vite-plugin-vue-tracer@1.3.0(vite@5.4.21(@types/node@25.0.7)(sass@1.98.0)(terser@5.46.0))(vue@3.5.30(typescript@5.9.3)):
|
||||||
dependencies:
|
dependencies:
|
||||||
estree-walker: 3.0.3
|
estree-walker: 3.0.3
|
||||||
exsolve: 1.0.8
|
exsolve: 1.0.8
|
||||||
magic-string: 0.30.21
|
magic-string: 0.30.21
|
||||||
pathe: 2.0.3
|
pathe: 2.0.3
|
||||||
source-map-js: 1.2.1
|
source-map-js: 1.2.1
|
||||||
vite: 7.3.1(@types/node@25.0.7)(jiti@2.6.1)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)
|
vite: 5.4.21(@types/node@25.0.7)(sass@1.98.0)(terser@5.46.0)
|
||||||
vue: 3.5.30(typescript@5.9.3)
|
vue: 3.5.30(typescript@5.9.3)
|
||||||
|
|
||||||
vite-plugin-vuetify@2.1.3(vite@7.3.1(@types/node@25.0.7)(jiti@2.6.1)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.30(typescript@5.9.3))(vuetify@3.12.3):
|
vite-plugin-vuetify@2.1.3(vite@5.4.21(@types/node@25.0.7)(sass@1.98.0)(terser@5.46.0))(vue@3.5.30(typescript@5.9.3))(vuetify@3.12.3):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@vuetify/loader-shared': 2.1.2(vue@3.5.30(typescript@5.9.3))(vuetify@3.12.3)
|
'@vuetify/loader-shared': 2.1.2(vue@3.5.30(typescript@5.9.3))(vuetify@3.12.3)
|
||||||
debug: 4.4.3
|
debug: 4.4.3
|
||||||
upath: 2.0.1
|
upath: 2.0.1
|
||||||
vite: 7.3.1(@types/node@25.0.7)(jiti@2.6.1)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)
|
vite: 5.4.21(@types/node@25.0.7)(sass@1.98.0)(terser@5.46.0)
|
||||||
vue: 3.5.30(typescript@5.9.3)
|
vue: 3.5.30(typescript@5.9.3)
|
||||||
vuetify: 3.12.3(typescript@5.9.3)(vite-plugin-vuetify@2.1.3)(vue@3.5.30(typescript@5.9.3))
|
vuetify: 3.12.3(typescript@5.9.3)(vite-plugin-vuetify@2.1.3)(vue@3.5.30(typescript@5.9.3))
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
|
|
@ -23023,7 +23042,7 @@ snapshots:
|
||||||
vue: 3.5.30(typescript@5.9.3)
|
vue: 3.5.30(typescript@5.9.3)
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
typescript: 5.9.3
|
typescript: 5.9.3
|
||||||
vite-plugin-vuetify: 2.1.3(vite@7.3.1(@types/node@25.0.7)(jiti@2.6.1)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.30(typescript@5.9.3))(vuetify@3.12.3)
|
vite-plugin-vuetify: 2.1.3(vite@5.4.21(@types/node@25.0.7)(sass@1.98.0)(terser@5.46.0))(vue@3.5.30(typescript@5.9.3))(vuetify@3.12.3)
|
||||||
|
|
||||||
w3c-keyname@2.2.8: {}
|
w3c-keyname@2.2.8: {}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,12 @@ export async function killTmuxPaneForCurrentPlatform(paneId: string): Promise<vo
|
||||||
invalidateTmuxRuntimeStatusCache();
|
invalidateTmuxRuntimeStatusCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function listTmuxPanePidsForCurrentPlatform(
|
||||||
|
paneIds: readonly string[]
|
||||||
|
): Promise<Map<string, number>> {
|
||||||
|
return runtimeCommandExecutor.listPanePids(paneIds);
|
||||||
|
}
|
||||||
|
|
||||||
export function killTmuxPaneForCurrentPlatformSync(paneId: string): void {
|
export function killTmuxPaneForCurrentPlatformSync(paneId: string): void {
|
||||||
runtimeCommandExecutor.killPaneSync(paneId);
|
runtimeCommandExecutor.killPaneSync(paneId);
|
||||||
invalidateTmuxRuntimeStatusCache();
|
invalidateTmuxRuntimeStatusCache();
|
||||||
|
|
|
||||||
|
|
@ -9,4 +9,5 @@ export {
|
||||||
isTmuxRuntimeReadyForCurrentPlatform,
|
isTmuxRuntimeReadyForCurrentPlatform,
|
||||||
killTmuxPaneForCurrentPlatform,
|
killTmuxPaneForCurrentPlatform,
|
||||||
killTmuxPaneForCurrentPlatformSync,
|
killTmuxPaneForCurrentPlatformSync,
|
||||||
|
listTmuxPanePidsForCurrentPlatform,
|
||||||
} from './composition/runtimeSupport';
|
} from './composition/runtimeSupport';
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,36 @@ export class TmuxPlatformCommandExecutor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async listPanePids(paneIds: readonly string[]): Promise<Map<string, number>> {
|
||||||
|
const normalizedPaneIds = [...new Set(paneIds.map((paneId) => paneId.trim()).filter(Boolean))];
|
||||||
|
if (normalizedPaneIds.length === 0) {
|
||||||
|
return new Map();
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await this.execTmux(
|
||||||
|
['list-panes', '-a', '-F', '#{pane_id}\t#{pane_pid}'],
|
||||||
|
3_000
|
||||||
|
);
|
||||||
|
if (result.exitCode !== 0) {
|
||||||
|
throw new Error(result.stderr || 'Failed to list tmux panes');
|
||||||
|
}
|
||||||
|
|
||||||
|
const wanted = new Set(normalizedPaneIds);
|
||||||
|
const panePidById = new Map<string, number>();
|
||||||
|
for (const line of result.stdout.split('\n')) {
|
||||||
|
const trimmed = line.trim();
|
||||||
|
if (!trimmed) continue;
|
||||||
|
const [paneId = '', rawPid = ''] = trimmed.split('\t');
|
||||||
|
const normalizedPaneId = paneId.trim();
|
||||||
|
if (!wanted.has(normalizedPaneId)) continue;
|
||||||
|
const pid = Number.parseInt(rawPid.trim(), 10);
|
||||||
|
if (Number.isFinite(pid) && pid > 0) {
|
||||||
|
panePidById.set(normalizedPaneId, pid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return panePidById;
|
||||||
|
}
|
||||||
|
|
||||||
killPaneSync(paneId: string): void {
|
killPaneSync(paneId: string): void {
|
||||||
if (process.platform === 'win32') {
|
if (process.platform === 'win32') {
|
||||||
const preferredDistro = this.#wslService.getPersistedPreferredDistroSync();
|
const preferredDistro = this.#wslService.getPersistedPreferredDistroSync();
|
||||||
|
|
|
||||||
|
|
@ -68,4 +68,26 @@ describe('TmuxPlatformCommandExecutor', () => {
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('lists pane pids for the requested pane ids only', async () => {
|
||||||
|
const executor = new TmuxPlatformCommandExecutor(
|
||||||
|
{
|
||||||
|
getPersistedPreferredDistroSync: () => null,
|
||||||
|
} as never,
|
||||||
|
{} as never
|
||||||
|
);
|
||||||
|
vi.spyOn(executor, 'execTmux').mockResolvedValue({
|
||||||
|
exitCode: 0,
|
||||||
|
stdout: '%1\t111\n%2\t222\n%3\tnot-a-pid\n',
|
||||||
|
stderr: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
await expect(executor.listPanePids(['%2', '%3', '%2'])).resolves.toEqual(
|
||||||
|
new Map([['%2', 222]])
|
||||||
|
);
|
||||||
|
expect(executor.execTmux).toHaveBeenCalledWith(
|
||||||
|
['list-panes', '-a', '-F', '#{pane_id}\t#{pane_pid}'],
|
||||||
|
3_000
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,7 @@
|
||||||
import { killTmuxPaneForCurrentPlatformSync } from '@features/tmux-installer/main';
|
import {
|
||||||
|
killTmuxPaneForCurrentPlatformSync,
|
||||||
|
listTmuxPanePidsForCurrentPlatform,
|
||||||
|
} from '@features/tmux-installer/main';
|
||||||
import { ConfigManager } from '@main/services/infrastructure/ConfigManager';
|
import { ConfigManager } from '@main/services/infrastructure/ConfigManager';
|
||||||
import { NotificationManager } from '@main/services/infrastructure/NotificationManager';
|
import { NotificationManager } from '@main/services/infrastructure/NotificationManager';
|
||||||
import { getAppIconPath } from '@main/utils/appIcon';
|
import { getAppIconPath } from '@main/utils/appIcon';
|
||||||
|
|
@ -65,6 +68,7 @@ import { randomUUID } from 'crypto';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as os from 'os';
|
import * as os from 'os';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
|
import pidusage from 'pidusage';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
type GeminiRuntimeAuthState,
|
type GeminiRuntimeAuthState,
|
||||||
|
|
@ -168,13 +172,13 @@ import type {
|
||||||
MemberSpawnStatusEntry,
|
MemberSpawnStatusEntry,
|
||||||
PersistedTeamLaunchPhase,
|
PersistedTeamLaunchPhase,
|
||||||
PersistedTeamLaunchSummary,
|
PersistedTeamLaunchSummary,
|
||||||
|
TeamAgentRuntimeBackendType,
|
||||||
|
TeamAgentRuntimeEntry,
|
||||||
|
TeamAgentRuntimeSnapshot,
|
||||||
TeamChangeEvent,
|
TeamChangeEvent,
|
||||||
TeamConfig,
|
TeamConfig,
|
||||||
TeamCreateRequest,
|
TeamCreateRequest,
|
||||||
TeamCreateResponse,
|
TeamCreateResponse,
|
||||||
TeamAgentRuntimeBackendType,
|
|
||||||
TeamAgentRuntimeEntry,
|
|
||||||
TeamAgentRuntimeSnapshot,
|
|
||||||
TeamLaunchAggregateState,
|
TeamLaunchAggregateState,
|
||||||
TeamLaunchRequest,
|
TeamLaunchRequest,
|
||||||
TeamLaunchResponse,
|
TeamLaunchResponse,
|
||||||
|
|
@ -794,9 +798,38 @@ function createInitialMemberSpawnStatusEntry(): MemberSpawnStatusEntry {
|
||||||
}
|
}
|
||||||
|
|
||||||
interface LiveTeamAgentRuntimeMetadata {
|
interface LiveTeamAgentRuntimeMetadata {
|
||||||
|
alive: boolean;
|
||||||
|
backendType?: TeamAgentRuntimeBackendType;
|
||||||
|
agentId?: string;
|
||||||
pid?: number;
|
pid?: number;
|
||||||
model?: string;
|
model?: string;
|
||||||
rssBytes?: number;
|
tmuxPaneId?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeTeamAgentRuntimeBackendType(
|
||||||
|
value: string | undefined,
|
||||||
|
isLead: boolean
|
||||||
|
): TeamAgentRuntimeBackendType | undefined {
|
||||||
|
if (isLead) return 'lead';
|
||||||
|
const normalized = value?.trim().toLowerCase();
|
||||||
|
if (normalized === 'tmux' || normalized === 'iterm2' || normalized === 'in-process') {
|
||||||
|
return normalized;
|
||||||
|
}
|
||||||
|
return normalized ? 'process' : undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
function matchesMemberNameOrBase(candidateName: string, memberName: string): boolean {
|
||||||
|
if (candidateName === memberName) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const parsed = parseNumericSuffixName(candidateName);
|
||||||
|
return parsed !== null && parsed.suffix >= 2 && parsed.base === memberName;
|
||||||
|
}
|
||||||
|
|
||||||
|
function matchesTeamMemberIdentity(leftName: string, rightName: string): boolean {
|
||||||
|
return (
|
||||||
|
matchesMemberNameOrBase(leftName, rightName) || matchesMemberNameOrBase(rightName, leftName)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function stripWrappedCliFlagValue(raw: string | undefined): string | undefined {
|
function stripWrappedCliFlagValue(raw: string | undefined): string | undefined {
|
||||||
|
|
@ -2180,17 +2213,17 @@ interface McpJsonRpcResponse<TResult> {
|
||||||
}
|
}
|
||||||
|
|
||||||
interface McpToolsListResult {
|
interface McpToolsListResult {
|
||||||
tools?: Array<{
|
tools?: {
|
||||||
name?: string;
|
name?: string;
|
||||||
_meta?: Record<string, unknown>;
|
_meta?: Record<string, unknown>;
|
||||||
}>;
|
}[];
|
||||||
}
|
}
|
||||||
|
|
||||||
interface McpToolCallResult {
|
interface McpToolCallResult {
|
||||||
content?: Array<{
|
content?: {
|
||||||
type?: string;
|
type?: string;
|
||||||
text?: string;
|
text?: string;
|
||||||
}>;
|
}[];
|
||||||
isError?: boolean;
|
isError?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2382,6 +2415,10 @@ export class TeamProvisioningService {
|
||||||
string,
|
string,
|
||||||
{ expiresAtMs: number; snapshot: TeamAgentRuntimeSnapshot }
|
{ expiresAtMs: number; snapshot: TeamAgentRuntimeSnapshot }
|
||||||
>();
|
>();
|
||||||
|
private readonly liveTeamAgentRuntimeMetadataCache = new Map<
|
||||||
|
string,
|
||||||
|
{ expiresAtMs: number; metadata: Map<string, LiveTeamAgentRuntimeMetadata> }
|
||||||
|
>();
|
||||||
private readonly launchStateStore = new TeamLaunchStateStore();
|
private readonly launchStateStore = new TeamLaunchStateStore();
|
||||||
private readonly memberLogsFinder: TeamMemberLogsFinder;
|
private readonly memberLogsFinder: TeamMemberLogsFinder;
|
||||||
private teamChangeEmitter: ((event: TeamChangeEvent) => void) | null = null;
|
private teamChangeEmitter: ((event: TeamChangeEvent) => void) | null = null;
|
||||||
|
|
@ -3759,17 +3796,18 @@ export class TeamProvisioningService {
|
||||||
const runId = this.getTrackedRunId(teamName);
|
const runId = this.getTrackedRunId(teamName);
|
||||||
if (!runId) {
|
if (!runId) {
|
||||||
return this.reconcilePersistedLaunchState(teamName).then(({ snapshot, statuses }) => {
|
return this.reconcilePersistedLaunchState(teamName).then(({ snapshot, statuses }) => {
|
||||||
this.attachLiveRuntimeMetadataToStatuses(teamName, statuses);
|
return this.attachLiveRuntimeMetadataToStatuses(teamName, statuses).then(
|
||||||
return {
|
(nextStatuses) => ({
|
||||||
statuses,
|
statuses: nextStatuses,
|
||||||
runId: null,
|
runId: null,
|
||||||
teamLaunchState: snapshot?.teamLaunchState,
|
teamLaunchState: snapshot?.teamLaunchState,
|
||||||
launchPhase: snapshot?.launchPhase,
|
launchPhase: snapshot?.launchPhase,
|
||||||
expectedMembers: snapshot?.expectedMembers,
|
expectedMembers: snapshot?.expectedMembers,
|
||||||
updatedAt: snapshot?.updatedAt,
|
updatedAt: snapshot?.updatedAt,
|
||||||
summary: snapshot?.summary,
|
summary: snapshot?.summary,
|
||||||
source: snapshot ? 'persisted' : 'persisted',
|
source: snapshot ? 'persisted' : 'persisted',
|
||||||
};
|
})
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
const run = this.runs.get(runId);
|
const run = this.runs.get(runId);
|
||||||
|
|
@ -3790,8 +3828,10 @@ export class TeamProvisioningService {
|
||||||
statuses: this.buildRuntimeSpawnStatusRecord(run),
|
statuses: this.buildRuntimeSpawnStatusRecord(run),
|
||||||
});
|
});
|
||||||
const snapshot = persisted ?? liveSnapshot;
|
const snapshot = persisted ?? liveSnapshot;
|
||||||
const statuses = snapshotToMemberSpawnStatuses(snapshot);
|
const statuses = await this.attachLiveRuntimeMetadataToStatuses(
|
||||||
this.attachLiveRuntimeMetadataToStatuses(teamName, statuses);
|
teamName,
|
||||||
|
snapshotToMemberSpawnStatuses(snapshot)
|
||||||
|
);
|
||||||
return {
|
return {
|
||||||
statuses,
|
statuses,
|
||||||
runId,
|
runId,
|
||||||
|
|
@ -3821,8 +3861,19 @@ export class TeamProvisioningService {
|
||||||
configuredMembers = [];
|
configuredMembers = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
const unixProcessRows = this.readUnixProcessTableRows();
|
const liveRuntimeByMember = await this.getLiveTeamAgentRuntimeMetadata(teamName);
|
||||||
const liveRuntimeByMember = this.getLiveTeamAgentRuntimeMetadata(teamName, unixProcessRows);
|
const runtimePids = new Set<number>();
|
||||||
|
const leadPid = run?.child?.pid;
|
||||||
|
if (typeof leadPid === 'number' && Number.isFinite(leadPid) && leadPid > 0) {
|
||||||
|
runtimePids.add(leadPid);
|
||||||
|
}
|
||||||
|
for (const metadata of liveRuntimeByMember.values()) {
|
||||||
|
const memberPid = metadata.pid;
|
||||||
|
if (typeof memberPid === 'number' && Number.isFinite(memberPid) && memberPid > 0) {
|
||||||
|
runtimePids.add(memberPid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const rssBytesByPid = await this.readProcessRssBytesByPid([...runtimePids]);
|
||||||
const persistedRuntimeMembers = this.readPersistedRuntimeMembers(teamName);
|
const persistedRuntimeMembers = this.readPersistedRuntimeMembers(teamName);
|
||||||
const snapshotMembers: Record<string, TeamAgentRuntimeEntry> = {};
|
const snapshotMembers: Record<string, TeamAgentRuntimeEntry> = {};
|
||||||
|
|
||||||
|
|
@ -3831,10 +3882,7 @@ export class TeamProvisioningService {
|
||||||
): PersistedRuntimeMemberLike | undefined => {
|
): PersistedRuntimeMemberLike | undefined => {
|
||||||
return persistedRuntimeMembers.find((member) => {
|
return persistedRuntimeMembers.find((member) => {
|
||||||
const candidateName = typeof member.name === 'string' ? member.name.trim() : '';
|
const candidateName = typeof member.name === 'string' ? member.name.trim() : '';
|
||||||
if (!candidateName) return false;
|
return candidateName.length > 0 && matchesMemberNameOrBase(candidateName, memberName);
|
||||||
if (candidateName === memberName) return true;
|
|
||||||
const parsed = parseNumericSuffixName(candidateName);
|
|
||||||
return parsed !== null && parsed.suffix >= 2 && parsed.base === memberName;
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -3844,26 +3892,13 @@ export class TeamProvisioningService {
|
||||||
if (candidateName === memberName) {
|
if (candidateName === memberName) {
|
||||||
return metadata;
|
return metadata;
|
||||||
}
|
}
|
||||||
const parsed = parseNumericSuffixName(candidateName);
|
if (matchesMemberNameOrBase(candidateName, memberName)) {
|
||||||
if (parsed !== null && parsed.suffix >= 2 && parsed.base === memberName) {
|
|
||||||
fallback = metadata;
|
fallback = metadata;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return fallback;
|
return fallback;
|
||||||
};
|
};
|
||||||
|
|
||||||
const normalizeBackendType = (
|
|
||||||
value: string | undefined,
|
|
||||||
isLead: boolean
|
|
||||||
): TeamAgentRuntimeBackendType | undefined => {
|
|
||||||
if (isLead) return 'lead';
|
|
||||||
const normalized = value?.trim().toLowerCase();
|
|
||||||
if (normalized === 'tmux' || normalized === 'iterm2' || normalized === 'in-process') {
|
|
||||||
return normalized;
|
|
||||||
}
|
|
||||||
return normalized ? 'process' : undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
for (const member of configuredMembers) {
|
for (const member of configuredMembers) {
|
||||||
const memberName = typeof member?.name === 'string' ? member.name.trim() : '';
|
const memberName = typeof member?.name === 'string' ? member.name.trim() : '';
|
||||||
if (!memberName) continue;
|
if (!memberName) continue;
|
||||||
|
|
@ -3871,7 +3906,7 @@ export class TeamProvisioningService {
|
||||||
const isLead = isLeadMember({ name: memberName, agentType: member.agentType });
|
const isLead = isLeadMember({ name: memberName, agentType: member.agentType });
|
||||||
if (isLead) {
|
if (isLead) {
|
||||||
const pid = run?.child?.pid;
|
const pid = run?.child?.pid;
|
||||||
const rssBytes = pid ? this.lookupProcessRssBytes(pid, unixProcessRows) : undefined;
|
const rssBytes = pid ? rssBytesByPid.get(pid) : undefined;
|
||||||
const runtimeModel =
|
const runtimeModel =
|
||||||
run?.request.model?.trim() ||
|
run?.request.model?.trim() ||
|
||||||
(run?.spawnContext
|
(run?.spawnContext
|
||||||
|
|
@ -3894,18 +3929,23 @@ export class TeamProvisioningService {
|
||||||
|
|
||||||
const persistedRuntimeMember = getPersistedRuntimeMember(memberName);
|
const persistedRuntimeMember = getPersistedRuntimeMember(memberName);
|
||||||
const liveRuntimeMember = getLiveRuntimeMember(memberName);
|
const liveRuntimeMember = getLiveRuntimeMember(memberName);
|
||||||
const backendType = normalizeBackendType(persistedRuntimeMember?.backendType, false);
|
const backendType = normalizeTeamAgentRuntimeBackendType(
|
||||||
|
persistedRuntimeMember?.backendType,
|
||||||
|
false
|
||||||
|
);
|
||||||
const restartable = backendType !== 'in-process';
|
const restartable = backendType !== 'in-process';
|
||||||
const runtimeModel = liveRuntimeMember?.model ?? member.model?.trim() ?? undefined;
|
const runtimeModel = liveRuntimeMember?.model ?? member.model?.trim() ?? undefined;
|
||||||
|
|
||||||
snapshotMembers[memberName] = {
|
snapshotMembers[memberName] = {
|
||||||
memberName,
|
memberName,
|
||||||
alive: Boolean(liveRuntimeMember?.pid),
|
alive: liveRuntimeMember?.alive ?? false,
|
||||||
restartable,
|
restartable,
|
||||||
...(backendType ? { backendType } : {}),
|
...(backendType ? { backendType } : {}),
|
||||||
...(liveRuntimeMember?.pid ? { pid: liveRuntimeMember.pid } : {}),
|
...(liveRuntimeMember?.pid ? { pid: liveRuntimeMember.pid } : {}),
|
||||||
...(runtimeModel ? { runtimeModel } : {}),
|
...(runtimeModel ? { runtimeModel } : {}),
|
||||||
...(liveRuntimeMember?.rssBytes != null ? { rssBytes: liveRuntimeMember.rssBytes } : {}),
|
...(liveRuntimeMember?.pid && rssBytesByPid.has(liveRuntimeMember.pid)
|
||||||
|
? { rssBytes: rssBytesByPid.get(liveRuntimeMember.pid) }
|
||||||
|
: {}),
|
||||||
updatedAt,
|
updatedAt,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -3951,10 +3991,7 @@ export class TeamProvisioningService {
|
||||||
|
|
||||||
const persistedRuntimeMembers = this.readPersistedRuntimeMembers(teamName).filter((member) => {
|
const persistedRuntimeMembers = this.readPersistedRuntimeMembers(teamName).filter((member) => {
|
||||||
const candidateName = typeof member.name === 'string' ? member.name.trim() : '';
|
const candidateName = typeof member.name === 'string' ? member.name.trim() : '';
|
||||||
if (!candidateName) return false;
|
return candidateName.length > 0 && matchesMemberNameOrBase(candidateName, memberName);
|
||||||
if (candidateName === memberName) return true;
|
|
||||||
const parsed = parseNumericSuffixName(candidateName);
|
|
||||||
return parsed !== null && parsed.suffix >= 2 && parsed.base === memberName;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const backendTypes = new Set(
|
const backendTypes = new Set(
|
||||||
|
|
@ -3968,18 +4005,26 @@ export class TeamProvisioningService {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const unixProcessRows = this.readUnixProcessTableRows();
|
const liveRuntimeByMember = await this.getLiveTeamAgentRuntimeMetadata(teamName);
|
||||||
const liveRuntimeByMember = this.getLiveTeamAgentRuntimeMetadata(teamName, unixProcessRows);
|
|
||||||
const livePids = new Set<number>();
|
const livePids = new Set<number>();
|
||||||
|
let hasAliveRuntimeWithoutPid = false;
|
||||||
for (const [candidateName, metadata] of liveRuntimeByMember.entries()) {
|
for (const [candidateName, metadata] of liveRuntimeByMember.entries()) {
|
||||||
if (candidateName === memberName) {
|
if (!matchesMemberNameOrBase(candidateName, memberName)) {
|
||||||
if (metadata.pid) livePids.add(metadata.pid);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const parsed = parseNumericSuffixName(candidateName);
|
if (metadata.pid) {
|
||||||
if (parsed !== null && parsed.suffix >= 2 && parsed.base === memberName && metadata.pid) {
|
|
||||||
livePids.add(metadata.pid);
|
livePids.add(metadata.pid);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
if (metadata.alive && metadata.backendType !== 'in-process') {
|
||||||
|
hasAliveRuntimeWithoutPid = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasAliveRuntimeWithoutPid) {
|
||||||
|
throw new Error(
|
||||||
|
`Member "${memberName}" is running, but its backend does not expose a restartable pid yet`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const persistedRuntimeMember of persistedRuntimeMembers) {
|
for (const persistedRuntimeMember of persistedRuntimeMembers) {
|
||||||
|
|
@ -4025,6 +4070,7 @@ export class TeamProvisioningService {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.agentRuntimeSnapshotCache.delete(teamName);
|
this.agentRuntimeSnapshotCache.delete(teamName);
|
||||||
|
this.liveTeamAgentRuntimeMetadataCache.delete(teamName);
|
||||||
this.setMemberSpawnStatus(run, memberName, 'offline');
|
this.setMemberSpawnStatus(run, memberName, 'offline');
|
||||||
this.setMemberSpawnStatus(run, memberName, 'spawning');
|
this.setMemberSpawnStatus(run, memberName, 'spawning');
|
||||||
this.appendMemberBootstrapDiagnostic(run, memberName, 'manual restart requested from UI');
|
this.appendMemberBootstrapDiagnostic(run, memberName, 'manual restart requested from UI');
|
||||||
|
|
@ -7471,7 +7517,7 @@ export class TeamProvisioningService {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const liveAgentNames = this.getLiveTeamAgentNames(run.teamName);
|
const liveAgentNames = await this.getLiveTeamAgentNames(run.teamName);
|
||||||
|
|
||||||
// Flag any expected member not found in config.json (excluding the lead)
|
// Flag any expected member not found in config.json (excluding the lead)
|
||||||
for (const expected of run.expectedMembers) {
|
for (const expected of run.expectedMembers) {
|
||||||
|
|
@ -7581,42 +7627,245 @@ export class TeamProvisioningService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private hasLiveTeamAgentProcess(teamName: string, memberName: string): boolean {
|
private async attachLiveRuntimeMetadataToStatuses(
|
||||||
return this.getLiveTeamAgentRuntimeMetadata(teamName).has(memberName);
|
|
||||||
}
|
|
||||||
|
|
||||||
private attachLiveRuntimeMetadataToStatuses(
|
|
||||||
teamName: string,
|
teamName: string,
|
||||||
statuses: Record<string, MemberSpawnStatusEntry>
|
statuses: Record<string, MemberSpawnStatusEntry>
|
||||||
): void {
|
): Promise<Record<string, MemberSpawnStatusEntry>> {
|
||||||
for (const [memberName, metadata] of this.getLiveTeamAgentRuntimeMetadata(teamName).entries()) {
|
const runtimeByMember = await this.getLiveTeamAgentRuntimeMetadata(teamName);
|
||||||
const current = statuses[memberName];
|
const nextStatuses = { ...statuses };
|
||||||
|
for (const [memberName, metadata] of runtimeByMember.entries()) {
|
||||||
|
const current = nextStatuses[memberName];
|
||||||
if (!current || !metadata.model) {
|
if (!current || !metadata.model) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
statuses[memberName] = {
|
nextStatuses[memberName] = {
|
||||||
...current,
|
...current,
|
||||||
runtimeModel: metadata.model,
|
runtimeModel: metadata.model,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
return nextStatuses;
|
||||||
}
|
}
|
||||||
|
|
||||||
private getLiveTeamAgentNames(teamName: string): Set<string> {
|
private async getLiveTeamAgentNames(teamName: string): Promise<Set<string>> {
|
||||||
return new Set(this.getLiveTeamAgentRuntimeMetadata(teamName).keys());
|
const runtimeByMember = await this.getLiveTeamAgentRuntimeMetadata(teamName);
|
||||||
|
return new Set(
|
||||||
|
[...runtimeByMember.entries()]
|
||||||
|
.filter(([, metadata]) => metadata.alive)
|
||||||
|
.map(([memberName]) => memberName)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private readUnixProcessTableRows(): Array<{
|
private findConfiguredMemberModel(
|
||||||
|
configuredMembers: TeamConfig['members'] | undefined,
|
||||||
|
memberName: string
|
||||||
|
): string | undefined {
|
||||||
|
for (const member of configuredMembers ?? []) {
|
||||||
|
const candidateName = typeof member?.name === 'string' ? member.name.trim() : '';
|
||||||
|
if (!candidateName || !matchesTeamMemberIdentity(candidateName, memberName)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const model = member.model?.trim();
|
||||||
|
if (model) {
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
private findMetaMemberModel(
|
||||||
|
metaMembers: Awaited<ReturnType<TeamMembersMetaStore['getMembers']>>,
|
||||||
|
memberName: string
|
||||||
|
): string | undefined {
|
||||||
|
for (const member of metaMembers) {
|
||||||
|
const candidateName = member.name?.trim() ?? '';
|
||||||
|
if (!candidateName || !matchesTeamMemberIdentity(candidateName, memberName)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const model = member.model?.trim();
|
||||||
|
if (model) {
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
private findEffectiveRunMemberModel(
|
||||||
|
run: ProvisioningRun | null,
|
||||||
|
memberName: string
|
||||||
|
): string | undefined {
|
||||||
|
if (!run) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
for (const member of run.effectiveMembers ?? []) {
|
||||||
|
const candidateName = member.name?.trim() ?? '';
|
||||||
|
if (!candidateName || !matchesTeamMemberIdentity(candidateName, memberName)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const model = member.model?.trim();
|
||||||
|
if (model) {
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
private findTrackedMemberSpawnStatus(
|
||||||
|
run: ProvisioningRun | null,
|
||||||
|
memberName: string
|
||||||
|
): MemberSpawnStatusEntry | undefined {
|
||||||
|
if (!run) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
const statusMap = run.memberSpawnStatuses instanceof Map ? run.memberSpawnStatuses : undefined;
|
||||||
|
if (!statusMap) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
const direct = statusMap.get(memberName);
|
||||||
|
if (direct) {
|
||||||
|
return direct;
|
||||||
|
}
|
||||||
|
for (const [candidateName, entry] of statusMap.entries()) {
|
||||||
|
if (matchesTeamMemberIdentity(candidateName, memberName)) {
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getLiveTeamAgentRuntimeMetadata(
|
||||||
|
teamName: string
|
||||||
|
): Promise<Map<string, LiveTeamAgentRuntimeMetadata>> {
|
||||||
|
const cached = this.liveTeamAgentRuntimeMetadataCache.get(teamName);
|
||||||
|
if (cached && cached.expiresAtMs > Date.now()) {
|
||||||
|
return cached.metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
const runId = this.getTrackedRunId(teamName);
|
||||||
|
const run = runId ? (this.runs.get(runId) ?? null) : null;
|
||||||
|
|
||||||
|
let configuredMembers: TeamConfig['members'] = [];
|
||||||
|
try {
|
||||||
|
configuredMembers = (await this.configReader.getConfig(teamName))?.members ?? [];
|
||||||
|
} catch {
|
||||||
|
configuredMembers = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
let metaMembers: Awaited<ReturnType<TeamMembersMetaStore['getMembers']>> = [];
|
||||||
|
try {
|
||||||
|
metaMembers = await this.membersMetaStore.getMembers(teamName);
|
||||||
|
} catch {
|
||||||
|
metaMembers = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const persistedRuntimeMembers = this.readPersistedRuntimeMembers(teamName);
|
||||||
|
const metadataByMember = new Map<string, LiveTeamAgentRuntimeMetadata>();
|
||||||
|
const upsertMetadata = (
|
||||||
|
memberName: string,
|
||||||
|
patch: Partial<LiveTeamAgentRuntimeMetadata>
|
||||||
|
): void => {
|
||||||
|
const current = metadataByMember.get(memberName) ?? { alive: false };
|
||||||
|
metadataByMember.set(memberName, {
|
||||||
|
...current,
|
||||||
|
...patch,
|
||||||
|
alive: patch.alive ?? current.alive,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const member of persistedRuntimeMembers) {
|
||||||
|
const memberName = typeof member.name === 'string' ? member.name.trim() : '';
|
||||||
|
if (!memberName || isLeadMember({ name: memberName })) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const runtimeModel =
|
||||||
|
this.findConfiguredMemberModel(configuredMembers, memberName) ??
|
||||||
|
this.findEffectiveRunMemberModel(run, memberName) ??
|
||||||
|
this.findMetaMemberModel(metaMembers, memberName);
|
||||||
|
upsertMetadata(memberName, {
|
||||||
|
backendType: normalizeTeamAgentRuntimeBackendType(member.backendType, false),
|
||||||
|
agentId:
|
||||||
|
typeof member.agentId === 'string' ? member.agentId.trim() || undefined : undefined,
|
||||||
|
tmuxPaneId:
|
||||||
|
typeof member.tmuxPaneId === 'string' ? member.tmuxPaneId.trim() || undefined : undefined,
|
||||||
|
...(runtimeModel ? { model: runtimeModel } : {}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const member of configuredMembers) {
|
||||||
|
const memberName = typeof member?.name === 'string' ? member.name.trim() : '';
|
||||||
|
if (!memberName || isLeadMember({ name: memberName, agentType: member.agentType })) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const runtimeModel =
|
||||||
|
member.model?.trim() ||
|
||||||
|
this.findEffectiveRunMemberModel(run, memberName) ||
|
||||||
|
this.findMetaMemberModel(metaMembers, memberName);
|
||||||
|
upsertMetadata(memberName, {
|
||||||
|
...(runtimeModel ? { model: runtimeModel } : {}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const member of run?.effectiveMembers ?? []) {
|
||||||
|
const memberName = member.name?.trim() ?? '';
|
||||||
|
if (!memberName || isLeadMember(member) || memberName.toLowerCase() === 'user') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
upsertMetadata(memberName, {
|
||||||
|
...(member.model?.trim() ? { model: member.model.trim() } : {}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const paneIds = [...metadataByMember.values()]
|
||||||
|
.map((metadata) => metadata.tmuxPaneId?.trim() ?? '')
|
||||||
|
.filter((paneId) => paneId.length > 0);
|
||||||
|
let panePidById = new Map<string, number>();
|
||||||
|
if (paneIds.length > 0) {
|
||||||
|
try {
|
||||||
|
panePidById = await listTmuxPanePidsForCurrentPlatform(paneIds);
|
||||||
|
} catch (error) {
|
||||||
|
logger.debug(
|
||||||
|
`[${teamName}] Failed to read tmux pane pids for runtime snapshot: ${
|
||||||
|
error instanceof Error ? error.message : String(error)
|
||||||
|
}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const [memberName, metadata] of metadataByMember.entries()) {
|
||||||
|
const paneId = metadata.tmuxPaneId?.trim() ?? '';
|
||||||
|
const backendType = metadata.backendType;
|
||||||
|
const panePid = paneId ? panePidById.get(paneId) : undefined;
|
||||||
|
const status = this.findTrackedMemberSpawnStatus(run, memberName);
|
||||||
|
const alive =
|
||||||
|
typeof panePid === 'number' && panePid > 0
|
||||||
|
? true
|
||||||
|
: backendType === 'tmux'
|
||||||
|
? false
|
||||||
|
: Boolean(status?.runtimeAlive || status?.bootstrapConfirmed);
|
||||||
|
metadataByMember.set(memberName, {
|
||||||
|
...metadata,
|
||||||
|
alive,
|
||||||
|
...(typeof panePid === 'number' && panePid > 0 ? { pid: panePid } : {}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.liveTeamAgentRuntimeMetadataCache.set(teamName, {
|
||||||
|
expiresAtMs: Date.now() + TeamProvisioningService.AGENT_RUNTIME_SNAPSHOT_CACHE_TTL_MS,
|
||||||
|
metadata: metadataByMember,
|
||||||
|
});
|
||||||
|
return metadataByMember;
|
||||||
|
}
|
||||||
|
|
||||||
|
private readUnixProcessTableRows(): {
|
||||||
pid: number;
|
pid: number;
|
||||||
rssBytes?: number;
|
|
||||||
command: string;
|
command: string;
|
||||||
}> {
|
}[] {
|
||||||
if (process.platform === 'win32') {
|
if (process.platform === 'win32') {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
let output = '';
|
let output = '';
|
||||||
try {
|
try {
|
||||||
output = execFileSync('ps', ['-ax', '-o', 'pid=,rss=,command='], {
|
output = execFileSync('ps', ['-ax', '-o', 'pid=,command='], {
|
||||||
encoding: 'utf8',
|
encoding: 'utf8',
|
||||||
stdio: ['ignore', 'pipe', 'ignore'],
|
stdio: ['ignore', 'pipe', 'ignore'],
|
||||||
});
|
});
|
||||||
|
|
@ -7624,79 +7873,64 @@ export class TeamProvisioningService {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
const rows: Array<{ pid: number; rssBytes?: number; command: string }> = [];
|
const rows: { pid: number; command: string }[] = [];
|
||||||
for (const line of output.split('\n')) {
|
for (const line of output.split('\n')) {
|
||||||
const trimmed = line.trim();
|
const trimmed = line.trim();
|
||||||
if (!trimmed) continue;
|
if (!trimmed) continue;
|
||||||
const match = /^(\d+)\s+(\d+)\s+(.*)$/.exec(trimmed);
|
const match = /^(\d+)\s+(.*)$/.exec(trimmed);
|
||||||
if (!match) continue;
|
if (!match) continue;
|
||||||
const pid = Number.parseInt(match[1], 10);
|
const pid = Number.parseInt(match[1], 10);
|
||||||
const rssKb = Number.parseInt(match[2], 10);
|
const command = match[2]?.trim() ?? '';
|
||||||
const command = match[3]?.trim() ?? '';
|
|
||||||
if (!Number.isFinite(pid) || pid <= 0 || command.length === 0) {
|
if (!Number.isFinite(pid) || pid <= 0 || command.length === 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
rows.push({
|
rows.push({
|
||||||
pid,
|
pid,
|
||||||
...(Number.isFinite(rssKb) && rssKb >= 0 ? { rssBytes: rssKb * 1024 } : {}),
|
|
||||||
command,
|
command,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return rows;
|
return rows;
|
||||||
}
|
}
|
||||||
|
|
||||||
private lookupProcessRssBytes(
|
private async readProcessRssBytesByPid(pids: readonly number[]): Promise<Map<number, number>> {
|
||||||
pid: number,
|
const uniquePids = [...new Set(pids.filter((pid) => Number.isFinite(pid) && pid > 0))];
|
||||||
unixProcessRows?: Array<{ pid: number; rssBytes?: number; command: string }>
|
if (uniquePids.length === 0) {
|
||||||
): number | undefined {
|
return new Map();
|
||||||
if (!Number.isFinite(pid) || pid <= 0) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
const cached = unixProcessRows?.find((row) => row.pid === pid);
|
|
||||||
if (cached) {
|
|
||||||
return cached.rssBytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (process.platform === 'win32') {
|
|
||||||
return undefined;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const rssBytesByPid = new Map<number, number>();
|
||||||
|
const options = { maxage: 0 };
|
||||||
try {
|
try {
|
||||||
const output = execFileSync('ps', ['-o', 'rss=', '-p', String(pid)], {
|
const statsByPid = await pidusage(uniquePids, options);
|
||||||
encoding: 'utf8',
|
for (const [rawPid, stat] of Object.entries(statsByPid)) {
|
||||||
stdio: ['ignore', 'pipe', 'ignore'],
|
const pid = Number.parseInt(rawPid, 10);
|
||||||
});
|
const rssBytes = stat?.memory;
|
||||||
const rssKb = Number.parseInt(output.trim(), 10);
|
if (Number.isFinite(pid) && pid > 0 && Number.isFinite(rssBytes) && rssBytes >= 0) {
|
||||||
return Number.isFinite(rssKb) && rssKb >= 0 ? rssKb * 1024 : undefined;
|
rssBytesByPid.set(pid, rssBytes);
|
||||||
} catch {
|
}
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private getLiveTeamAgentRuntimeMetadata(
|
|
||||||
teamName: string,
|
|
||||||
unixProcessRows?: Array<{ pid: number; rssBytes?: number; command: string }>
|
|
||||||
): Map<string, LiveTeamAgentRuntimeMetadata> {
|
|
||||||
const teamMarker = `--team-name ${teamName}`;
|
|
||||||
const metadataByAgent = new Map<string, LiveTeamAgentRuntimeMetadata>();
|
|
||||||
const rows = unixProcessRows ?? this.readUnixProcessTableRows();
|
|
||||||
for (const row of rows) {
|
|
||||||
const trimmed = row.command.trim();
|
|
||||||
if (!trimmed.includes(teamMarker)) continue;
|
|
||||||
const match = /--agent-id\s+([^\s@]+)@/.exec(trimmed);
|
|
||||||
if (!match) continue;
|
|
||||||
const agentName = match[1]?.trim();
|
|
||||||
if (agentName) {
|
|
||||||
const model = extractCliFlagValue(trimmed, '--model');
|
|
||||||
metadataByAgent.set(agentName, {
|
|
||||||
pid: row.pid,
|
|
||||||
...(model ? { model } : {}),
|
|
||||||
...(row.rssBytes != null ? { rssBytes: row.rssBytes } : {}),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
return rssBytesByPid;
|
||||||
|
} catch (error) {
|
||||||
|
logger.debug(
|
||||||
|
`pidusage batch runtime snapshot failed; falling back to per-pid reads: ${
|
||||||
|
error instanceof Error ? error.message : String(error)
|
||||||
|
}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return metadataByAgent;
|
|
||||||
|
await Promise.all(
|
||||||
|
uniquePids.map(async (pid) => {
|
||||||
|
try {
|
||||||
|
const stat = await pidusage(pid, options);
|
||||||
|
if (Number.isFinite(stat.memory) && stat.memory >= 0) {
|
||||||
|
rssBytesByPid.set(pid, stat.memory);
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// Process likely exited between discovery and sampling.
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
return rssBytesByPid;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async clearPersistedLaunchState(teamName: string): Promise<void> {
|
private async clearPersistedLaunchState(teamName: string): Promise<void> {
|
||||||
|
|
@ -7862,7 +8096,7 @@ export class TeamProvisioningService {
|
||||||
// best-effort
|
// best-effort
|
||||||
}
|
}
|
||||||
|
|
||||||
const liveAgentNames = this.getLiveTeamAgentNames(teamName);
|
const liveAgentNames = await this.getLiveTeamAgentNames(teamName);
|
||||||
const nextMembers = { ...persisted.members };
|
const nextMembers = { ...persisted.members };
|
||||||
const now = nowIso();
|
const now = nowIso();
|
||||||
for (const expected of persisted.expectedMembers) {
|
for (const expected of persisted.expectedMembers) {
|
||||||
|
|
@ -8493,6 +8727,7 @@ export class TeamProvisioningService {
|
||||||
*/
|
*/
|
||||||
stopTeam(teamName: string): void {
|
stopTeam(teamName: string): void {
|
||||||
this.agentRuntimeSnapshotCache.delete(teamName);
|
this.agentRuntimeSnapshotCache.delete(teamName);
|
||||||
|
this.liveTeamAgentRuntimeMetadataCache.delete(teamName);
|
||||||
this.stopPersistentTeamMembers(teamName);
|
this.stopPersistentTeamMembers(teamName);
|
||||||
|
|
||||||
const runId = this.getTrackedRunId(teamName);
|
const runId = this.getTrackedRunId(teamName);
|
||||||
|
|
@ -11091,6 +11326,7 @@ export class TeamProvisioningService {
|
||||||
}
|
}
|
||||||
if (!hasNewerTrackedRun) {
|
if (!hasNewerTrackedRun) {
|
||||||
this.agentRuntimeSnapshotCache.delete(run.teamName);
|
this.agentRuntimeSnapshotCache.delete(run.teamName);
|
||||||
|
this.liveTeamAgentRuntimeMetadataCache.delete(run.teamName);
|
||||||
this.leadInboxRelayInFlight.delete(run.teamName);
|
this.leadInboxRelayInFlight.delete(run.teamName);
|
||||||
this.relayedLeadInboxMessageIds.delete(run.teamName);
|
this.relayedLeadInboxMessageIds.delete(run.teamName);
|
||||||
this.pendingCrossTeamFirstReplies.delete(run.teamName);
|
this.pendingCrossTeamFirstReplies.delete(run.teamName);
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,19 @@ vi.mock('@main/services/team/ClaudeBinaryResolver', () => ({
|
||||||
ClaudeBinaryResolver: { resolve: vi.fn() },
|
ClaudeBinaryResolver: { resolve: vi.fn() },
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
vi.mock('@features/tmux-installer/main', () => ({
|
||||||
|
killTmuxPaneForCurrentPlatformSync: vi.fn(),
|
||||||
|
listTmuxPanePidsForCurrentPlatform: vi.fn(async () => new Map()),
|
||||||
|
isTmuxRuntimeReadyForCurrentPlatform: vi.fn(async () => true),
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock('pidusage', () => {
|
||||||
|
const pidusageMock = vi.fn();
|
||||||
|
return {
|
||||||
|
default: pidusageMock,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
vi.mock('@main/services/team/TeamTaskReader', () => ({
|
vi.mock('@main/services/team/TeamTaskReader', () => ({
|
||||||
TeamTaskReader: class {
|
TeamTaskReader: class {
|
||||||
async getTasks() {
|
async getTasks() {
|
||||||
|
|
@ -61,6 +74,8 @@ import { getTeamLaunchStatePath } from '@main/services/team/TeamLaunchStateStore
|
||||||
import { ClaudeBinaryResolver } from '@main/services/team/ClaudeBinaryResolver';
|
import { ClaudeBinaryResolver } from '@main/services/team/ClaudeBinaryResolver';
|
||||||
import { spawnCli } from '@main/utils/childProcess';
|
import { spawnCli } from '@main/utils/childProcess';
|
||||||
import { AGENT_TEAMS_NAMESPACED_TEAMMATE_OPERATIONAL_TOOL_NAMES } from 'agent-teams-controller';
|
import { AGENT_TEAMS_NAMESPACED_TEAMMATE_OPERATIONAL_TOOL_NAMES } from 'agent-teams-controller';
|
||||||
|
import { listTmuxPanePidsForCurrentPlatform } from '@features/tmux-installer/main';
|
||||||
|
import pidusage from 'pidusage';
|
||||||
|
|
||||||
function allowConsoleLogs() {
|
function allowConsoleLogs() {
|
||||||
vi.spyOn(console, 'error').mockImplementation(() => {});
|
vi.spyOn(console, 'error').mockImplementation(() => {});
|
||||||
|
|
@ -91,6 +106,18 @@ function createRunningChild() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createPidusageStat(pid: number, memory: number) {
|
||||||
|
return {
|
||||||
|
cpu: 0,
|
||||||
|
memory,
|
||||||
|
ppid: 1,
|
||||||
|
pid,
|
||||||
|
ctime: 0,
|
||||||
|
elapsed: 0,
|
||||||
|
timestamp: Date.now(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function writeLaunchConfig(
|
function writeLaunchConfig(
|
||||||
teamName: string,
|
teamName: string,
|
||||||
projectPath: string,
|
projectPath: string,
|
||||||
|
|
@ -197,6 +224,100 @@ describe('TeamProvisioningService', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('getTeamAgentRuntimeSnapshot', () => {
|
||||||
|
it('uses batched pidusage rss values for lead and teammates', async () => {
|
||||||
|
const svc = new TeamProvisioningService();
|
||||||
|
(svc as any).configReader = {
|
||||||
|
getConfig: vi.fn(async () => ({
|
||||||
|
members: [
|
||||||
|
{ name: 'team-lead', agentType: 'team-lead' },
|
||||||
|
{ name: 'alice', model: 'gpt-5.4-mini' },
|
||||||
|
],
|
||||||
|
})),
|
||||||
|
};
|
||||||
|
(svc as any).readPersistedRuntimeMembers = vi.fn(() => [
|
||||||
|
{
|
||||||
|
name: 'alice',
|
||||||
|
agentId: 'alice@runtime-team',
|
||||||
|
tmuxPaneId: '%1',
|
||||||
|
backendType: 'tmux',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
(svc as any).aliveRunByTeam.set('runtime-team', 'run-1');
|
||||||
|
(svc as any).runs.set('run-1', {
|
||||||
|
runId: 'run-1',
|
||||||
|
child: { pid: 111 },
|
||||||
|
request: { model: 'gpt-5.4' },
|
||||||
|
processKilled: false,
|
||||||
|
cancelRequested: false,
|
||||||
|
spawnContext: null,
|
||||||
|
});
|
||||||
|
vi.mocked(listTmuxPanePidsForCurrentPlatform).mockResolvedValueOnce(new Map([['%1', 222]]));
|
||||||
|
|
||||||
|
vi.mocked(pidusage).mockResolvedValueOnce({
|
||||||
|
'111': createPidusageStat(111, 123_000_000),
|
||||||
|
'222': createPidusageStat(222, 456_000_000),
|
||||||
|
} as any);
|
||||||
|
|
||||||
|
const snapshot = await svc.getTeamAgentRuntimeSnapshot('runtime-team');
|
||||||
|
|
||||||
|
expect(pidusage).toHaveBeenCalledWith([111, 222], { maxage: 0 });
|
||||||
|
expect(snapshot.members['team-lead']).toMatchObject({
|
||||||
|
pid: 111,
|
||||||
|
rssBytes: 123_000_000,
|
||||||
|
runtimeModel: 'gpt-5.4',
|
||||||
|
});
|
||||||
|
expect(snapshot.members.alice).toMatchObject({
|
||||||
|
pid: 222,
|
||||||
|
rssBytes: 456_000_000,
|
||||||
|
runtimeModel: 'gpt-5.4-mini',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('falls back to per-pid pidusage reads when batched sampling fails', async () => {
|
||||||
|
const svc = new TeamProvisioningService();
|
||||||
|
(svc as any).configReader = {
|
||||||
|
getConfig: vi.fn(async () => ({
|
||||||
|
members: [
|
||||||
|
{ name: 'team-lead', agentType: 'team-lead' },
|
||||||
|
{ name: 'alice', model: 'gpt-5.4-mini' },
|
||||||
|
],
|
||||||
|
})),
|
||||||
|
};
|
||||||
|
(svc as any).readPersistedRuntimeMembers = vi.fn(() => [
|
||||||
|
{
|
||||||
|
name: 'alice',
|
||||||
|
agentId: 'alice@runtime-team',
|
||||||
|
tmuxPaneId: '%1',
|
||||||
|
backendType: 'tmux',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
(svc as any).aliveRunByTeam.set('runtime-team', 'run-1');
|
||||||
|
(svc as any).runs.set('run-1', {
|
||||||
|
runId: 'run-1',
|
||||||
|
child: { pid: 111 },
|
||||||
|
request: { model: 'gpt-5.4' },
|
||||||
|
processKilled: false,
|
||||||
|
cancelRequested: false,
|
||||||
|
spawnContext: null,
|
||||||
|
});
|
||||||
|
vi.mocked(listTmuxPanePidsForCurrentPlatform).mockResolvedValueOnce(new Map([['%1', 222]]));
|
||||||
|
|
||||||
|
vi.mocked(pidusage)
|
||||||
|
.mockRejectedValueOnce(new Error('ps: process exited'))
|
||||||
|
.mockResolvedValueOnce(createPidusageStat(111, 123_000_000) as any)
|
||||||
|
.mockResolvedValueOnce(createPidusageStat(222, 456_000_000) as any);
|
||||||
|
|
||||||
|
const snapshot = await svc.getTeamAgentRuntimeSnapshot('runtime-team');
|
||||||
|
|
||||||
|
expect(pidusage).toHaveBeenNthCalledWith(1, [111, 222], { maxage: 0 });
|
||||||
|
expect(pidusage).toHaveBeenNthCalledWith(2, 111, { maxage: 0 });
|
||||||
|
expect(pidusage).toHaveBeenNthCalledWith(3, 222, { maxage: 0 });
|
||||||
|
expect(snapshot.members['team-lead']?.rssBytes).toBe(123_000_000);
|
||||||
|
expect(snapshot.members.alice?.rssBytes).toBe(456_000_000);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('removes generated MCP config when createTeam spawn fails synchronously', async () => {
|
it('removes generated MCP config when createTeam spawn fails synchronously', async () => {
|
||||||
allowConsoleLogs();
|
allowConsoleLogs();
|
||||||
vi.mocked(ClaudeBinaryResolver.resolve).mockResolvedValue('/mock/claude');
|
vi.mocked(ClaudeBinaryResolver.resolve).mockResolvedValue('/mock/claude');
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue