diff --git a/.github/workflows/release-pkg.yaml b/.github/workflows/release-pkg.yaml index d2c0c711b..1a9c16411 100644 --- a/.github/workflows/release-pkg.yaml +++ b/.github/workflows/release-pkg.yaml @@ -5,9 +5,6 @@ on: tags: - 'v*' -env: - STORE_PATH: '' - permissions: contents: write issues: write diff --git a/.github/workflows/release-vsix.yaml b/.github/workflows/release-vsix.yaml new file mode 100644 index 000000000..b0e81e4ab --- /dev/null +++ b/.github/workflows/release-vsix.yaml @@ -0,0 +1,39 @@ +name: Release + +on: + push: + tags: + - '@proj-airi/airi-plugin-vscode@v*' + - 'v*' + +permissions: + contents: read + +jobs: + release-vsix: + name: Release - VSCE & OVSX + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + + - uses: pnpm/action-setup@v3 + with: + run_install: false + + - name: Install Node.js 24.x + uses: actions/setup-node@v4 + with: + node-version: 24.x + # registry-url required. Learn more at + # https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages + registry-url: 'https://registry.npmjs.org' + cache: pnpm + + - run: pnpm install --frozen-lockfile + - run: pnpm run build:packages + - run: pnpm run -F @proj-airi/airi-plugin-vscode build + - run: pnpm run publish + working-directory: ./plugins/airi-plugin-vscode + env: + VSCE_TOKEN: ${{ secrets.VSCE_TOKEN }} + OVSX_TOKEN: ${{ secrets.OVSX_TOKEN }} diff --git a/.gitignore b/.gitignore index ac000320e..f7fa904c8 100644 --- a/.gitignore +++ b/.gitignore @@ -77,6 +77,10 @@ components.d.ts # Serving fonts locally **/public/assets/fonts/ +# Code generation +plugins/airi-plugin-vscode/src/generated/ +plugins/airi-plugin-vscode/LICENSE + # Make it easy for devenv users to override their local environment. # See: https://github.com/moeru-ai/airi/pull/110#discussion_r2024378953 .direnv diff --git a/plugins/airi-plugin-vscode/.vscodeignore b/plugins/airi-plugin-vscode/.vscodeignore new file mode 100644 index 000000000..1c40f9fca --- /dev/null +++ b/plugins/airi-plugin-vscode/.vscodeignore @@ -0,0 +1,8 @@ +.github/** +.vscode/** +.vscode-test/** +scripts/** +src/** +test/** +tsconfig.json +tsdown.config.ts diff --git a/plugins/airi-plugin-vscode/README.md b/plugins/airi-plugin-vscode/README.md new file mode 100644 index 000000000..e7cb45b39 --- /dev/null +++ b/plugins/airi-plugin-vscode/README.md @@ -0,0 +1,3 @@ +# AIRI VSCode Plugin + +> Official VSCode extension for AIRI, streaming your current working at stuff back to AIRI. diff --git a/plugins/airi-plugin-vscode/package.json b/plugins/airi-plugin-vscode/package.json index 842baf894..8a5184239 100644 --- a/plugins/airi-plugin-vscode/package.json +++ b/plugins/airi-plugin-vscode/package.json @@ -1,14 +1,21 @@ { - "publisher": "airi", + "publisher": "proj-airi", "name": "@proj-airi/airi-plugin-vscode", "displayName": "AIRI", "version": "0.8.0-alpha.6", "private": true, "description": "VSCode extension that shares your coding context with AIRI", + "repository": { + "type": "git", + "url": "https://github.com/moeru-ai/airi.git", + "directory": "plugins/airi-plugin-vscode" + }, "categories": [ "Other" ], - "main": "./dist/extension.js", + "preview": true, + "main": "./dist/extension.cjs", + "icon": "res/logo.jpg", "engines": { "vscode": "^1.106.1" }, @@ -18,32 +25,32 @@ "contributes": { "commands": [ { - "command": "airi.enable", + "command": "airi-vscode.enable", "title": "AIRI: Enable" }, { - "command": "airi.disable", + "command": "airi-vscode.disable", "title": "AIRI: Disable" }, { - "command": "airi.status", + "command": "airi-vscode.status", "title": "AIRI: Show Status" } ], "configuration": { "title": "AIRI", "properties": { - "airi.enabled": { + "airi-vscode.enabled": { "type": "boolean", "default": true, - "description": "Enable AIRI companion" + "description": "Enable or disable the AIRI extension" }, - "airi.contextLines": { + "airi-vscode.contextLines": { "type": "number", "default": 5, "description": "Number of context lines to send (before and after current line)" }, - "airi.sendInterval": { + "airi-vscode.sendInterval": { "type": "number", "default": 3000, "description": "Interval in milliseconds to send updates (0 for real-time)" @@ -52,9 +59,11 @@ } }, "scripts": { - "vscode:prepublish": "pnpm run build", - "build": "tsdown", + "prepare": "pnpm run update", + "update": "tsx ./scripts/vscode-ext-gen.ts", "dev": "tsdown --watch", + "build": "tsdown", + "publish": "tsx ./scripts/publish.ts", "typecheck": "tsc --noEmit" }, "dependencies": { @@ -62,6 +71,8 @@ "@proj-airi/server-sdk": "workspace:*" }, "devDependencies": { - "@types/vscode": "^1.106.1" + "@types/vscode": "^1.106.1", + "tinyexec": "^1.0.2", + "vscode-ext-gen": "^1.4.0" } -} +} \ No newline at end of file diff --git a/plugins/airi-plugin-vscode/res/logo.jpg b/plugins/airi-plugin-vscode/res/logo.jpg new file mode 100644 index 000000000..775b1e6e7 Binary files /dev/null and b/plugins/airi-plugin-vscode/res/logo.jpg differ diff --git a/plugins/airi-plugin-vscode/scripts/dev.ts b/plugins/airi-plugin-vscode/scripts/dev.ts new file mode 100644 index 000000000..17793c954 --- /dev/null +++ b/plugins/airi-plugin-vscode/scripts/dev.ts @@ -0,0 +1,9 @@ +// https://github.com/unocss/unocss/blob/dba521e377887ed2b3b38dc86f36d4f292230ac8/packages-integrations/vscode/scripts/dev.ts + +import { packageJSONForVSCode } from './shared' + +async function run() { + await packageJSONForVSCode('airi-vscode') +} + +run() diff --git a/plugins/airi-plugin-vscode/scripts/publish.ts b/plugins/airi-plugin-vscode/scripts/publish.ts new file mode 100644 index 000000000..bbe2cc55a --- /dev/null +++ b/plugins/airi-plugin-vscode/scripts/publish.ts @@ -0,0 +1,58 @@ +// https://github.com/unocss/unocss/blob/dba521e377887ed2b3b38dc86f36d4f292230ac8/packages-integrations/vscode/scripts/publish.ts + +import process from 'node:process' + +import { copyFile, readFile, rm, writeFile } from 'node:fs/promises' +import { dirname, join } from 'node:path' +import { fileURLToPath } from 'node:url' + +import { exec } from 'tinyexec' + +import { packageJSONForVSCode } from './shared' + +const dir = typeof __dirname === 'string' ? __dirname : dirname(fileURLToPath(import.meta.url)) +const root = dirname(dir) + +async function publish() { + const { restore, isPreview } = await packageJSONForVSCode('airi-vscode') + const pkgPath = join(root, 'package.json') + const rawJSON = await readFile(pkgPath, 'utf-8') + + const pkg = JSON.parse(rawJSON) + + if (isPreview) + pkg.preview = true + else + delete pkg.preview + + await writeFile(pkgPath, JSON.stringify(pkg, null, 2), 'utf-8') + + await rm(join(root, 'LICENSE'), { force: true }).catch(() => {}) + await copyFile(join(root, '..', '..', 'LICENSE'), join(root, 'LICENSE')) + + try { + { + // eslint-disable-next-line no-console + console.log('\nPublish to VSCE...\n') + const execPublish = exec('pnpx', ['@vscode/vsce', 'publish', '--no-dependencies', '-p', process.env.VSCE_TOKEN!, ...[(isPreview ? '--pre-release' : '')]], { nodeOptions: { cwd: root } }) + for await (const line of execPublish) { + // eslint-disable-next-line no-console + console.log(line) + } + } + { + // eslint-disable-next-line no-console + console.log('\nPublish to OVSE...\n') + const execPublish = exec('pnpx', ['ovsx', 'publish', '--no-dependencies', '-p', process.env.OVSX_TOKEN!, ...[(isPreview ? '--pre-release' : '')]], { nodeOptions: { cwd: root } }) + for await (const line of execPublish) { + // eslint-disable-next-line no-console + console.log(line) + } + } + } + finally { + await restore() + } +} + +publish() diff --git a/plugins/airi-plugin-vscode/scripts/shared.ts b/plugins/airi-plugin-vscode/scripts/shared.ts new file mode 100644 index 000000000..23c16098a --- /dev/null +++ b/plugins/airi-plugin-vscode/scripts/shared.ts @@ -0,0 +1,93 @@ +// https://github.com/unocss/unocss/blob/dba521e377887ed2b3b38dc86f36d4f292230ac8/packages-integrations/vscode/scripts/dev.ts + +import { readFile, writeFile } from 'node:fs/promises' + +export async function packageJSONForVSCode(name: string) { + const json = JSON.parse(await readFile(new URL('../package.json', import.meta.url), 'utf-8')) + const originalName = json.name + const originalVersion = json.version + + if (json.name !== name) { + json.name = name + + await writeFile(new URL('../package.json', import.meta.url), JSON.stringify(json, null, 2), 'utf-8') + } + + const numericVersion = encodeNumericVersion(originalVersion) + if (json.version !== numericVersion.version) { + json.version = numericVersion.version + + await writeFile(new URL('../package.json', import.meta.url), JSON.stringify(json, null, 2), 'utf-8') + } + + return { + originalName, + originalVersion, + name, + version: numericVersion.version, + isPreview: numericVersion.preview, + restore: async () => { + json.name = originalName + json.version = originalVersion + + await writeFile(new URL('../package.json', import.meta.url), JSON.stringify(json, null, 2), 'utf-8') + }, + } +} + +// NOTICE: VSCE rejects prerelease identifiers, so we encode stage+sequence into a numeric-only patch bucket: +// encodedPatch = patch*10000 + stageBucket + sequence. +// stageBucket: alpha=1000, beta=2000, rc=3000, stable=9000. +// Examples: +// 0.8.0-alpha.6 -> 0.8.(0*10000+1000+6)=0.8.1006 (preview=true) +// 0.8.0-beta.1 -> 0.8.2001 (preview=true) +// 0.8.0 -> 0.8.(0*10000+9000)=0.8.9000 (preview=false) +// This keeps ordering: alpha < beta < rc < stable. Unknown prerelease tags default to alpha. +export function encodeNumericVersion(version: string) { + const match = version.match(/^(?\d+)\.(?\d+)\.(?\d+)(-(?
[0-9A-Z.-]+))?$/i)
+  if (!match || !match.groups)
+    throw new Error(`Invalid semver: ${version}`)
+
+  const major = Number.parseInt(match.groups.major, 10)
+  const minor = Number.parseInt(match.groups.minor, 10)
+  const patch = Number.parseInt(match.groups.patch, 10)
+  const prerelease = match.groups.pre
+
+  const multiplier = 10_000
+  const stageBuckets = {
+    alpha: 1_000,
+    beta: 2_000,
+    rc: 3_000,
+    stable: 9_000,
+  } as const
+
+  const { stage, sequence } = parsePrerelease(prerelease)
+  const maxSequence = (multiplier - 1) - stageBuckets[stage]
+  if (sequence > maxSequence) {
+    throw new Error(`Prerelease sequence overflow for ${stage}: ${sequence} exceeds limit ${maxSequence}`)
+  }
+  if (sequence < 0) {
+    throw new Error(`Prerelease sequence must be non-negative: ${sequence}`)
+  }
+
+  const encodedPatch = (patch * multiplier) + (stageBuckets[stage] ?? stageBuckets.alpha) + sequence
+  const encoded = `${major}.${minor}.${encodedPatch}`
+
+  return {
+    version: encoded,
+    preview: stage !== 'stable',
+  }
+}
+
+function parsePrerelease(prerelease?: string) {
+  if (!prerelease) {
+    return { stage: 'stable' as const, sequence: 0 }
+  }
+
+  const [stageRaw, sequenceRaw] = prerelease.split('.')
+  const stage = stageRaw === 'beta' || stageRaw === 'rc' || stageRaw === 'alpha' ? stageRaw : 'alpha'
+  const sequenceParsed = Number.parseInt(sequenceRaw ?? '', 10)
+  const sequence = Number.isFinite(sequenceParsed) ? sequenceParsed : 0
+
+  return { stage, sequence }
+}
diff --git a/plugins/airi-plugin-vscode/scripts/vscode-ext-gen.ts b/plugins/airi-plugin-vscode/scripts/vscode-ext-gen.ts
new file mode 100644
index 000000000..065d10f6d
--- /dev/null
+++ b/plugins/airi-plugin-vscode/scripts/vscode-ext-gen.ts
@@ -0,0 +1,19 @@
+import { dirname } from 'node:path'
+
+import { exec } from 'tinyexec'
+
+import { packageJSONForVSCode } from './shared'
+
+async function run() {
+  const { restore, name } = await packageJSONForVSCode('airi-vscode')
+
+  const execGen = exec('pnpm', ['-F', name, 'exec', 'vscode-ext-gen', '--scope=unocss', '--output', 'src/generated/meta.ts'], { nodeOptions: { cwd: dirname(new URL('../', import.meta.url).pathname) } })
+  for await (const line of execGen) {
+    // eslint-disable-next-line no-console
+    console.log(line)
+  }
+
+  await restore()
+}
+
+run()
diff --git a/plugins/airi-plugin-vscode/src/airi-client.ts b/plugins/airi-plugin-vscode/src/airi-client.ts
index 9cac37ccb..8c0276e98 100644
--- a/plugins/airi-plugin-vscode/src/airi-client.ts
+++ b/plugins/airi-plugin-vscode/src/airi-client.ts
@@ -1,20 +1,20 @@
-import type { AiriEvent } from './types'
+import type { Events } from './types'
 
 import { useLogger } from '@guiiai/logg'
-import { Client } from '@proj-airi/server-sdk'
+import { Client as ServerClient } from '@proj-airi/server-sdk'
 
 /**
  * Airi Channel Server Client
  */
-export class AiriClient {
-  private client: Client | null = null
+export class Client {
+  private client: ServerClient | null = null
 
   /**
    * Connect to Channel Server
    */
   async connect(): Promise {
     try {
-      this.client = new Client({ name: 'proj-airi:plugin-vscode' })
+      this.client = new ServerClient({ name: 'proj-airi:plugin-vscode' })
 
       useLogger().log('Airi companion connected to Channel Server')
       return true
@@ -39,7 +39,7 @@ export class AiriClient {
   /**
    * Send event to Airi
    */
-  sendEvent(event: AiriEvent): void {
+  sendEvent(event: Events): void {
     if (!this.client) {
       useLogger().warn('Cannot send event: not connected to Airi Channel Server')
       return
diff --git a/plugins/airi-plugin-vscode/src/extension.ts b/plugins/airi-plugin-vscode/src/extension.ts
index 9c30cdb04..c6ccd8423 100644
--- a/plugins/airi-plugin-vscode/src/extension.ts
+++ b/plugins/airi-plugin-vscode/src/extension.ts
@@ -2,10 +2,10 @@ import type * as vscode from 'vscode'
 
 import { initLogger, LoggerFormat, LoggerLevel, useLogger } from '@guiiai/logg'
 
-import { AiriClient } from './airi-client'
+import { Client } from './airi-client'
 import { ContextCollector } from './context-collector'
 
-let airiClient: AiriClient
+let client: Client
 let contextCollector: ContextCollector
 let updateTimer: NodeJS.Timeout | null = null
 let isEnabled = true
@@ -19,48 +19,48 @@ export async function activate(context: vscode.ExtensionContext) {
 
   const { window, workspace, commands } = await import('vscode')
 
-  useLogger().log('Airi Companion is activating...')
+  useLogger().log('AIRI is activating...')
 
   // Get the configuration
-  const config = workspace.getConfiguration('airi.companion')
+  const config = workspace.getConfiguration('airi-vscode')
   isEnabled = config.get('enabled', true)
   const contextLines = config.get('contextLines', 5)
   const sendInterval = config.get('sendInterval', 3000)
 
   // Initialize
-  airiClient = new AiriClient()
+  client = new Client()
   contextCollector = new ContextCollector(contextLines)
 
   // Connect to Airi Channel Server
   if (isEnabled) {
-    const connected = await airiClient.connect()
+    const connected = await client.connect()
     if (connected) {
-      window.showInformationMessage('Airi Companion connected!')
+      window.showInformationMessage('AIRI server channel connected!')
     }
     else {
-      window.showWarningMessage('Airi Companion failed to connect to server')
+      window.showWarningMessage('AIRI server channel connection failed!')
     }
   }
 
   // Register commands
   context.subscriptions.push(
-    commands.registerCommand('airi.companion.enable', async () => {
+    commands.registerCommand('airi-vscode.enable', async () => {
       isEnabled = true
-      await airiClient.connect()
+      await client.connect()
       await registerListeners(sendInterval)
-      window.showInformationMessage('Airi Companion enabled')
+      window.showInformationMessage('AIRI enabled!')
     }),
 
-    commands.registerCommand('airi.companion.disable', () => {
+    commands.registerCommand('airi-vscode.disable', () => {
       isEnabled = false
       unregisterListeners()
-      airiClient.disconnect()
-      window.showInformationMessage('Airi Companion disabled')
+      client.disconnect()
+      window.showInformationMessage('AIRI disabled!')
     }),
 
-    commands.registerCommand('airi.companion.status', () => {
-      const status = isEnabled && airiClient ? 'Connected' : 'Disconnected'
-      window.showInformationMessage(`Airi Companion Status: ${status}`)
+    commands.registerCommand('airi-vscode.status', () => {
+      const status = isEnabled && client ? 'Connected' : 'Disconnected'
+      window.showInformationMessage(`AIRI server channel status: ${status}.`)
     }),
   )
 
@@ -69,7 +69,7 @@ export async function activate(context: vscode.ExtensionContext) {
     await registerListeners(sendInterval)
   }
 
-  useLogger().log('Airi Companion activated successfully')
+  useLogger().log('AIRI activated successfully')
 }
 
 /**
@@ -87,7 +87,7 @@ async function registerListeners(sendInterval: number) {
       if (editor && editor.document === document) {
         const ctx = await contextCollector.collect(editor)
         if (ctx) {
-          airiClient.sendEvent({
+          client.sendEvent({
             type: 'coding:save',
             data: ctx,
           })
@@ -102,7 +102,7 @@ async function registerListeners(sendInterval: number) {
       if (editor) {
         const ctx = await contextCollector.collect(editor)
         if (ctx) {
-          airiClient.sendEvent({
+          client.sendEvent({
             type: 'coding:switch-file',
             data: ctx,
           })
@@ -143,7 +143,7 @@ function startMonitoring(interval: number) {
 
     const ctx = await contextCollector.collect(editor)
     if (ctx) {
-      airiClient.sendEvent({
+      client.sendEvent({
         type: 'coding:context',
         data: ctx,
       })
@@ -166,6 +166,6 @@ function stopMonitoring() {
  */
 export function deactivate() {
   unregisterListeners()
-  airiClient?.disconnect()
-  useLogger().log('Airi Companion deactivated')
+  client?.disconnect()
+  useLogger().log('AIRI deactivated!')
 }
diff --git a/plugins/airi-plugin-vscode/src/types.ts b/plugins/airi-plugin-vscode/src/types.ts
index 06c71fb98..1da2126fe 100644
--- a/plugins/airi-plugin-vscode/src/types.ts
+++ b/plugins/airi-plugin-vscode/src/types.ts
@@ -42,7 +42,7 @@ export interface CodingContext {
 /**
  * Event types sent to Airi
  */
-export interface AiriEvent {
+export interface Events {
   type: 'coding:context' | 'coding:save' | 'coding:switch-file'
   data: CodingContext
 }
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index c780af25e..cc725b2b7 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -1065,7 +1065,7 @@ importers:
         version: 11.1.12(vue@3.5.25(typescript@5.9.3))
       vue-sonner:
         specifier: ^2.0.9
-        version: 2.0.9(@nuxt/kit@4.0.3(magicast@0.3.5))(@nuxt/schema@4.0.3)(nuxt@4.0.3(@netlify/blobs@9.1.2)(@parcel/watcher@2.5.0)(@types/node@24.10.1)(@vue/compiler-sfc@3.5.25)(bufferutil@4.0.9)(db0@0.3.2(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(@types/pg@8.15.6)(gel@2.0.0)(pg@8.16.3)(postgres@3.4.7)))(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(@types/pg@8.15.6)(gel@2.0.0)(pg@8.16.3)(postgres@3.4.7))(eslint@9.39.1(jiti@2.6.1))(ioredis@5.7.0)(less@4.4.2)(lightningcss@1.30.2)(magicast@0.3.5)(optionator@0.9.4)(rolldown@1.0.0-beta.51)(rollup@4.53.2)(terser@5.43.1)(tsx@4.21.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(vite@7.2.2(@types/node@24.10.1)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.2)(terser@5.43.1)(tsx@4.21.0)(yaml@2.8.1))(vue-tsc@3.1.5(typescript@5.9.3))(xml2js@0.6.2)(yaml@2.8.1))
+        version: 2.0.9(@nuxt/kit@4.0.3(magicast@0.3.5))(@nuxt/schema@4.0.3)(nuxt@4.0.3(@netlify/blobs@9.1.2)(@parcel/watcher@2.5.0)(@types/node@24.10.1)(@vue/compiler-sfc@3.5.25)(bufferutil@4.0.9)(db0@0.3.2(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(@types/pg@8.15.6)(gel@2.0.0)(pg@8.16.3)(postgres@3.4.7)))(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(@types/pg@8.15.6)(gel@2.0.0)(pg@8.16.3)(postgres@3.4.7))(encoding@0.1.13)(eslint@9.39.1(jiti@2.6.1))(ioredis@5.7.0)(less@4.4.2)(lightningcss@1.30.2)(magicast@0.3.5)(optionator@0.9.4)(rolldown@1.0.0-beta.51)(rollup@4.53.2)(terser@5.43.1)(tsx@4.21.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(vite@7.2.2(@types/node@24.10.1)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.2)(terser@5.43.1)(tsx@4.21.0)(yaml@2.8.1))(vue-tsc@3.1.5(typescript@5.9.3))(xml2js@0.6.2)(yaml@2.8.1))
     devDependencies:
       '@iconify-json/lucide':
         specifier: ^1.2.73
@@ -1609,7 +1609,7 @@ importers:
         version: 4.6.3(vue@3.5.25(typescript@5.9.3))
       vue-sonner:
         specifier: ^2.0.9
-        version: 2.0.9(@nuxt/kit@4.0.3(magicast@0.3.5))(@nuxt/schema@4.0.3)(nuxt@4.0.3(@netlify/blobs@9.1.2)(@parcel/watcher@2.5.0)(@types/node@24.10.1)(@vue/compiler-sfc@3.5.25)(bufferutil@4.0.9)(db0@0.3.2(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(@types/pg@8.15.6)(gel@2.0.0)(pg@8.16.3)(postgres@3.4.7)))(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(@types/pg@8.15.6)(gel@2.0.0)(pg@8.16.3)(postgres@3.4.7))(eslint@9.39.1(jiti@2.6.1))(ioredis@5.7.0)(less@4.4.2)(lightningcss@1.30.2)(magicast@0.3.5)(optionator@0.9.4)(rolldown@1.0.0-beta.51)(rollup@4.53.2)(terser@5.43.1)(tsx@4.21.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(vite@6.4.1(@types/node@24.10.1)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.2)(terser@5.43.1)(tsx@4.21.0)(yaml@2.8.1))(vue-tsc@3.1.5(typescript@5.9.3))(xml2js@0.6.2)(yaml@2.8.1))
+        version: 2.0.9(@nuxt/kit@4.0.3(magicast@0.3.5))(@nuxt/schema@4.0.3)(nuxt@4.0.3(@netlify/blobs@9.1.2)(@parcel/watcher@2.5.0)(@types/node@24.10.1)(@vue/compiler-sfc@3.5.25)(bufferutil@4.0.9)(db0@0.3.2(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(@types/pg@8.15.6)(gel@2.0.0)(pg@8.16.3)(postgres@3.4.7)))(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(@types/pg@8.15.6)(gel@2.0.0)(pg@8.16.3)(postgres@3.4.7))(encoding@0.1.13)(eslint@9.39.1(jiti@2.6.1))(ioredis@5.7.0)(less@4.4.2)(lightningcss@1.30.2)(magicast@0.3.5)(optionator@0.9.4)(rolldown@1.0.0-beta.51)(rollup@4.53.2)(terser@5.43.1)(tsx@4.21.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(vite@6.4.1(@types/node@24.10.1)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.2)(terser@5.43.1)(tsx@4.21.0)(yaml@2.8.1))(vue-tsc@3.1.5(typescript@5.9.3))(xml2js@0.6.2)(yaml@2.8.1))
       vue-tsc:
         specifier: ^3.1.4
         version: 3.1.5(typescript@5.9.3)
@@ -1851,7 +1851,7 @@ importers:
         version: rolldown-vite@7.2.5(@types/node@24.10.1)(esbuild@0.25.9)(jiti@2.6.1)(less@4.4.2)(terser@5.43.1)(tsx@4.21.0)(yaml@2.8.1)
       vite-plugin-vue-devtools:
         specifier: ^8.0.3
-        version: 8.0.3(@nuxt/kit@4.0.3(magicast@0.3.5))(rolldown-vite@7.2.5(@types/node@24.10.1)(esbuild@0.25.9)(jiti@2.6.1)(less@4.4.2)(terser@5.43.1)(tsx@4.21.0)(yaml@2.8.1))(vue@3.5.25(typescript@5.9.3))
+        version: 8.0.3(rolldown-vite@7.2.5(@types/node@24.10.1)(esbuild@0.25.9)(jiti@2.6.1)(less@4.4.2)(terser@5.43.1)(tsx@4.21.0)(yaml@2.8.1))(vue@3.5.25(typescript@5.9.3))
       vue-router:
         specifier: ^4.6.3
         version: 4.6.3(vue@3.5.25(typescript@5.9.3))
@@ -1885,7 +1885,7 @@ importers:
         version: rolldown-vite@7.2.5(@types/node@24.10.1)(esbuild@0.25.9)(jiti@2.6.1)(less@4.4.2)(terser@5.43.1)(tsx@4.21.0)(yaml@2.8.1)
       vite-plugin-vue-devtools:
         specifier: ^8.0.3
-        version: 8.0.3(@nuxt/kit@4.0.3(magicast@0.3.5))(rolldown-vite@7.2.5(@types/node@24.10.1)(esbuild@0.25.9)(jiti@2.6.1)(less@4.4.2)(terser@5.43.1)(tsx@4.21.0)(yaml@2.8.1))(vue@3.5.25(typescript@5.9.3))
+        version: 8.0.3(rolldown-vite@7.2.5(@types/node@24.10.1)(esbuild@0.25.9)(jiti@2.6.1)(less@4.4.2)(terser@5.43.1)(tsx@4.21.0)(yaml@2.8.1))(vue@3.5.25(typescript@5.9.3))
       vue-router:
         specifier: ^4.6.3
         version: 4.6.3(vue@3.5.25(typescript@5.9.3))
@@ -1970,6 +1970,12 @@ importers:
       '@types/vscode':
         specifier: ^1.106.1
         version: 1.106.1
+      tinyexec:
+        specifier: ^1.0.2
+        version: 1.0.2
+      vscode-ext-gen:
+        specifier: ^1.4.0
+        version: 1.4.0
 
   plugins/airi-plugin-web-extension:
     dependencies:
@@ -15834,6 +15840,10 @@ packages:
       jsdom:
         optional: true
 
+  vscode-ext-gen@1.4.0:
+    resolution: {integrity: sha512-rN3vdlD9XmE8WCim0RO0/8VuSOtMvisKX0s9gA2RhKz0Nrl5pPYFF8Q0C8CmeYH3ZqacxntGRFsNZXR5vgOJ1w==}
+    hasBin: true
+
   vscode-uri@3.1.0:
     resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==}
 
@@ -29148,7 +29158,7 @@ snapshots:
       - yaml
     optional: true
 
-  nuxt@4.0.3(@netlify/blobs@9.1.2)(@parcel/watcher@2.5.0)(@types/node@24.10.1)(@vue/compiler-sfc@3.5.25)(bufferutil@4.0.9)(db0@0.3.2(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(@types/pg@8.15.6)(gel@2.0.0)(pg@8.16.3)(postgres@3.4.7)))(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(@types/pg@8.15.6)(gel@2.0.0)(pg@8.16.3)(postgres@3.4.7))(eslint@9.39.1(jiti@2.6.1))(ioredis@5.7.0)(less@4.4.2)(lightningcss@1.30.2)(magicast@0.3.5)(optionator@0.9.4)(rolldown@1.0.0-beta.51)(rollup@4.53.2)(terser@5.43.1)(tsx@4.21.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(vite@6.4.1(@types/node@24.10.1)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.2)(terser@5.43.1)(tsx@4.21.0)(yaml@2.8.1))(vue-tsc@3.1.5(typescript@5.9.3))(xml2js@0.6.2)(yaml@2.8.1):
+  nuxt@4.0.3(@netlify/blobs@9.1.2)(@parcel/watcher@2.5.0)(@types/node@24.10.1)(@vue/compiler-sfc@3.5.25)(bufferutil@4.0.9)(db0@0.3.2(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(@types/pg@8.15.6)(gel@2.0.0)(pg@8.16.3)(postgres@3.4.7)))(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(@types/pg@8.15.6)(gel@2.0.0)(pg@8.16.3)(postgres@3.4.7))(encoding@0.1.13)(eslint@9.39.1(jiti@2.6.1))(ioredis@5.7.0)(less@4.4.2)(lightningcss@1.30.2)(magicast@0.3.5)(optionator@0.9.4)(rolldown@1.0.0-beta.51)(rollup@4.53.2)(terser@5.43.1)(tsx@4.21.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(vite@6.4.1(@types/node@24.10.1)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.2)(terser@5.43.1)(tsx@4.21.0)(yaml@2.8.1))(vue-tsc@3.1.5(typescript@5.9.3))(xml2js@0.6.2)(yaml@2.8.1):
     dependencies:
       '@nuxt/cli': 3.28.0(magicast@0.3.5)
       '@nuxt/devalue': 2.0.2
@@ -29273,7 +29283,7 @@ snapshots:
       - yaml
     optional: true
 
-  nuxt@4.0.3(@netlify/blobs@9.1.2)(@parcel/watcher@2.5.0)(@types/node@24.10.1)(@vue/compiler-sfc@3.5.25)(bufferutil@4.0.9)(db0@0.3.2(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(@types/pg@8.15.6)(gel@2.0.0)(pg@8.16.3)(postgres@3.4.7)))(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(@types/pg@8.15.6)(gel@2.0.0)(pg@8.16.3)(postgres@3.4.7))(eslint@9.39.1(jiti@2.6.1))(ioredis@5.7.0)(less@4.4.2)(lightningcss@1.30.2)(magicast@0.3.5)(optionator@0.9.4)(rolldown@1.0.0-beta.51)(rollup@4.53.2)(terser@5.43.1)(tsx@4.21.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(vite@7.2.2(@types/node@24.10.1)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.2)(terser@5.43.1)(tsx@4.21.0)(yaml@2.8.1))(vue-tsc@3.1.5(typescript@5.9.3))(xml2js@0.6.2)(yaml@2.8.1):
+  nuxt@4.0.3(@netlify/blobs@9.1.2)(@parcel/watcher@2.5.0)(@types/node@24.10.1)(@vue/compiler-sfc@3.5.25)(bufferutil@4.0.9)(db0@0.3.2(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(@types/pg@8.15.6)(gel@2.0.0)(pg@8.16.3)(postgres@3.4.7)))(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(@types/pg@8.15.6)(gel@2.0.0)(pg@8.16.3)(postgres@3.4.7))(encoding@0.1.13)(eslint@9.39.1(jiti@2.6.1))(ioredis@5.7.0)(less@4.4.2)(lightningcss@1.30.2)(magicast@0.3.5)(optionator@0.9.4)(rolldown@1.0.0-beta.51)(rollup@4.53.2)(terser@5.43.1)(tsx@4.21.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(vite@7.2.2(@types/node@24.10.1)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.2)(terser@5.43.1)(tsx@4.21.0)(yaml@2.8.1))(vue-tsc@3.1.5(typescript@5.9.3))(xml2js@0.6.2)(yaml@2.8.1):
     dependencies:
       '@nuxt/cli': 3.28.0(magicast@0.3.5)
       '@nuxt/devalue': 2.0.2
@@ -33169,7 +33179,6 @@ snapshots:
       '@nuxt/kit': 3.18.1(magicast@0.3.5)
     transitivePeerDependencies:
       - supports-color
-    optional: true
 
   vite-plugin-inspect@11.3.3(@nuxt/kit@3.18.1(magicast@0.3.5))(vite@6.4.1(@types/node@24.10.1)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.2)(terser@5.43.1)(tsx@4.21.0)(yaml@2.8.1)):
     dependencies:
@@ -33248,6 +33257,20 @@ snapshots:
       - supports-color
       - vue
 
+  vite-plugin-vue-devtools@8.0.3(rolldown-vite@7.2.5(@types/node@24.10.1)(esbuild@0.25.9)(jiti@2.6.1)(less@4.4.2)(terser@5.43.1)(tsx@4.21.0)(yaml@2.8.1))(vue@3.5.25(typescript@5.9.3)):
+    dependencies:
+      '@vue/devtools-core': 8.0.3(rolldown-vite@7.2.5(@types/node@24.10.1)(esbuild@0.25.9)(jiti@2.6.1)(less@4.4.2)(terser@5.43.1)(tsx@4.21.0)(yaml@2.8.1))(vue@3.5.25(typescript@5.9.3))
+      '@vue/devtools-kit': 8.0.3
+      '@vue/devtools-shared': 8.0.3
+      sirv: 3.0.2
+      vite: rolldown-vite@7.2.5(@types/node@24.10.1)(esbuild@0.25.9)(jiti@2.6.1)(less@4.4.2)(terser@5.43.1)(tsx@4.21.0)(yaml@2.8.1)
+      vite-plugin-inspect: 11.3.3(@nuxt/kit@3.18.1(magicast@0.3.5))(rolldown-vite@7.2.5(@types/node@24.10.1)(esbuild@0.25.9)(jiti@2.6.1)(less@4.4.2)(terser@5.43.1)(tsx@4.21.0)(yaml@2.8.1))
+      vite-plugin-vue-inspector: 5.3.2(rolldown-vite@7.2.5(@types/node@24.10.1)(esbuild@0.25.9)(jiti@2.6.1)(less@4.4.2)(terser@5.43.1)(tsx@4.21.0)(yaml@2.8.1))
+    transitivePeerDependencies:
+      - '@nuxt/kit'
+      - supports-color
+      - vue
+
   vite-plugin-vue-inspector@5.3.2(rolldown-vite@7.2.5(@types/node@24.10.1)(esbuild@0.25.9)(jiti@2.6.1)(less@4.4.2)(terser@5.43.1)(tsx@4.21.0)(yaml@2.8.1)):
     dependencies:
       '@babel/core': 7.28.3
@@ -33442,6 +33465,10 @@ snapshots:
       - tsx
       - yaml
 
+  vscode-ext-gen@1.4.0:
+    dependencies:
+      cac: 6.7.14
+
   vscode-uri@3.1.0: {}
 
   vue-bundle-renderer@2.1.2:
@@ -33492,17 +33519,17 @@ snapshots:
       '@nuxt/schema': 4.0.3
       nuxt: 4.0.3(@netlify/blobs@9.1.2)(@parcel/watcher@2.5.0)(@types/node@24.10.1)(@vue/compiler-sfc@3.5.25)(bufferutil@4.0.9)(db0@0.3.2(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(@types/pg@8.15.6)(gel@2.0.0)(pg@8.16.3)(postgres@3.4.7)))(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(@types/pg@8.15.6)(gel@2.0.0)(pg@8.16.3)(postgres@3.4.7))(encoding@0.1.13)(eslint@9.39.1(jiti@2.6.1))(ioredis@5.7.0)(less@4.4.2)(lightningcss@1.30.2)(magicast@0.3.5)(optionator@0.9.4)(rolldown-vite@7.2.5(@types/node@24.10.1)(esbuild@0.25.9)(jiti@2.6.1)(less@4.4.2)(terser@5.43.1)(tsx@4.21.0)(yaml@2.8.1))(rolldown@1.0.0-beta.51)(rollup@2.79.2)(terser@5.43.1)(tsx@4.21.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(vue-tsc@3.1.5(typescript@5.9.3))(xml2js@0.6.2)(yaml@2.8.1)
 
-  vue-sonner@2.0.9(@nuxt/kit@4.0.3(magicast@0.3.5))(@nuxt/schema@4.0.3)(nuxt@4.0.3(@netlify/blobs@9.1.2)(@parcel/watcher@2.5.0)(@types/node@24.10.1)(@vue/compiler-sfc@3.5.25)(bufferutil@4.0.9)(db0@0.3.2(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(@types/pg@8.15.6)(gel@2.0.0)(pg@8.16.3)(postgres@3.4.7)))(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(@types/pg@8.15.6)(gel@2.0.0)(pg@8.16.3)(postgres@3.4.7))(eslint@9.39.1(jiti@2.6.1))(ioredis@5.7.0)(less@4.4.2)(lightningcss@1.30.2)(magicast@0.3.5)(optionator@0.9.4)(rolldown@1.0.0-beta.51)(rollup@4.53.2)(terser@5.43.1)(tsx@4.21.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(vite@6.4.1(@types/node@24.10.1)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.2)(terser@5.43.1)(tsx@4.21.0)(yaml@2.8.1))(vue-tsc@3.1.5(typescript@5.9.3))(xml2js@0.6.2)(yaml@2.8.1)):
+  vue-sonner@2.0.9(@nuxt/kit@4.0.3(magicast@0.3.5))(@nuxt/schema@4.0.3)(nuxt@4.0.3(@netlify/blobs@9.1.2)(@parcel/watcher@2.5.0)(@types/node@24.10.1)(@vue/compiler-sfc@3.5.25)(bufferutil@4.0.9)(db0@0.3.2(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(@types/pg@8.15.6)(gel@2.0.0)(pg@8.16.3)(postgres@3.4.7)))(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(@types/pg@8.15.6)(gel@2.0.0)(pg@8.16.3)(postgres@3.4.7))(encoding@0.1.13)(eslint@9.39.1(jiti@2.6.1))(ioredis@5.7.0)(less@4.4.2)(lightningcss@1.30.2)(magicast@0.3.5)(optionator@0.9.4)(rolldown@1.0.0-beta.51)(rollup@4.53.2)(terser@5.43.1)(tsx@4.21.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(vite@6.4.1(@types/node@24.10.1)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.2)(terser@5.43.1)(tsx@4.21.0)(yaml@2.8.1))(vue-tsc@3.1.5(typescript@5.9.3))(xml2js@0.6.2)(yaml@2.8.1)):
     optionalDependencies:
       '@nuxt/kit': 4.0.3(magicast@0.3.5)
       '@nuxt/schema': 4.0.3
-      nuxt: 4.0.3(@netlify/blobs@9.1.2)(@parcel/watcher@2.5.0)(@types/node@24.10.1)(@vue/compiler-sfc@3.5.25)(bufferutil@4.0.9)(db0@0.3.2(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(@types/pg@8.15.6)(gel@2.0.0)(pg@8.16.3)(postgres@3.4.7)))(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(@types/pg@8.15.6)(gel@2.0.0)(pg@8.16.3)(postgres@3.4.7))(eslint@9.39.1(jiti@2.6.1))(ioredis@5.7.0)(less@4.4.2)(lightningcss@1.30.2)(magicast@0.3.5)(optionator@0.9.4)(rolldown@1.0.0-beta.51)(rollup@4.53.2)(terser@5.43.1)(tsx@4.21.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(vite@6.4.1(@types/node@24.10.1)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.2)(terser@5.43.1)(tsx@4.21.0)(yaml@2.8.1))(vue-tsc@3.1.5(typescript@5.9.3))(xml2js@0.6.2)(yaml@2.8.1)
+      nuxt: 4.0.3(@netlify/blobs@9.1.2)(@parcel/watcher@2.5.0)(@types/node@24.10.1)(@vue/compiler-sfc@3.5.25)(bufferutil@4.0.9)(db0@0.3.2(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(@types/pg@8.15.6)(gel@2.0.0)(pg@8.16.3)(postgres@3.4.7)))(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(@types/pg@8.15.6)(gel@2.0.0)(pg@8.16.3)(postgres@3.4.7))(encoding@0.1.13)(eslint@9.39.1(jiti@2.6.1))(ioredis@5.7.0)(less@4.4.2)(lightningcss@1.30.2)(magicast@0.3.5)(optionator@0.9.4)(rolldown@1.0.0-beta.51)(rollup@4.53.2)(terser@5.43.1)(tsx@4.21.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(vite@6.4.1(@types/node@24.10.1)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.2)(terser@5.43.1)(tsx@4.21.0)(yaml@2.8.1))(vue-tsc@3.1.5(typescript@5.9.3))(xml2js@0.6.2)(yaml@2.8.1)
 
-  vue-sonner@2.0.9(@nuxt/kit@4.0.3(magicast@0.3.5))(@nuxt/schema@4.0.3)(nuxt@4.0.3(@netlify/blobs@9.1.2)(@parcel/watcher@2.5.0)(@types/node@24.10.1)(@vue/compiler-sfc@3.5.25)(bufferutil@4.0.9)(db0@0.3.2(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(@types/pg@8.15.6)(gel@2.0.0)(pg@8.16.3)(postgres@3.4.7)))(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(@types/pg@8.15.6)(gel@2.0.0)(pg@8.16.3)(postgres@3.4.7))(eslint@9.39.1(jiti@2.6.1))(ioredis@5.7.0)(less@4.4.2)(lightningcss@1.30.2)(magicast@0.3.5)(optionator@0.9.4)(rolldown@1.0.0-beta.51)(rollup@4.53.2)(terser@5.43.1)(tsx@4.21.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(vite@7.2.2(@types/node@24.10.1)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.2)(terser@5.43.1)(tsx@4.21.0)(yaml@2.8.1))(vue-tsc@3.1.5(typescript@5.9.3))(xml2js@0.6.2)(yaml@2.8.1)):
+  vue-sonner@2.0.9(@nuxt/kit@4.0.3(magicast@0.3.5))(@nuxt/schema@4.0.3)(nuxt@4.0.3(@netlify/blobs@9.1.2)(@parcel/watcher@2.5.0)(@types/node@24.10.1)(@vue/compiler-sfc@3.5.25)(bufferutil@4.0.9)(db0@0.3.2(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(@types/pg@8.15.6)(gel@2.0.0)(pg@8.16.3)(postgres@3.4.7)))(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(@types/pg@8.15.6)(gel@2.0.0)(pg@8.16.3)(postgres@3.4.7))(encoding@0.1.13)(eslint@9.39.1(jiti@2.6.1))(ioredis@5.7.0)(less@4.4.2)(lightningcss@1.30.2)(magicast@0.3.5)(optionator@0.9.4)(rolldown@1.0.0-beta.51)(rollup@4.53.2)(terser@5.43.1)(tsx@4.21.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(vite@7.2.2(@types/node@24.10.1)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.2)(terser@5.43.1)(tsx@4.21.0)(yaml@2.8.1))(vue-tsc@3.1.5(typescript@5.9.3))(xml2js@0.6.2)(yaml@2.8.1)):
     optionalDependencies:
       '@nuxt/kit': 4.0.3(magicast@0.3.5)
       '@nuxt/schema': 4.0.3
-      nuxt: 4.0.3(@netlify/blobs@9.1.2)(@parcel/watcher@2.5.0)(@types/node@24.10.1)(@vue/compiler-sfc@3.5.25)(bufferutil@4.0.9)(db0@0.3.2(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(@types/pg@8.15.6)(gel@2.0.0)(pg@8.16.3)(postgres@3.4.7)))(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(@types/pg@8.15.6)(gel@2.0.0)(pg@8.16.3)(postgres@3.4.7))(eslint@9.39.1(jiti@2.6.1))(ioredis@5.7.0)(less@4.4.2)(lightningcss@1.30.2)(magicast@0.3.5)(optionator@0.9.4)(rolldown@1.0.0-beta.51)(rollup@4.53.2)(terser@5.43.1)(tsx@4.21.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(vite@7.2.2(@types/node@24.10.1)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.2)(terser@5.43.1)(tsx@4.21.0)(yaml@2.8.1))(vue-tsc@3.1.5(typescript@5.9.3))(xml2js@0.6.2)(yaml@2.8.1)
+      nuxt: 4.0.3(@netlify/blobs@9.1.2)(@parcel/watcher@2.5.0)(@types/node@24.10.1)(@vue/compiler-sfc@3.5.25)(bufferutil@4.0.9)(db0@0.3.2(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(@types/pg@8.15.6)(gel@2.0.0)(pg@8.16.3)(postgres@3.4.7)))(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(@types/pg@8.15.6)(gel@2.0.0)(pg@8.16.3)(postgres@3.4.7))(encoding@0.1.13)(eslint@9.39.1(jiti@2.6.1))(ioredis@5.7.0)(less@4.4.2)(lightningcss@1.30.2)(magicast@0.3.5)(optionator@0.9.4)(rolldown@1.0.0-beta.51)(rollup@4.53.2)(terser@5.43.1)(tsx@4.21.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(vite@7.2.2(@types/node@24.10.1)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.2)(terser@5.43.1)(tsx@4.21.0)(yaml@2.8.1))(vue-tsc@3.1.5(typescript@5.9.3))(xml2js@0.6.2)(yaml@2.8.1)
 
   vue-tsc@3.1.5(typescript@5.9.3):
     dependencies: