diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 8be86aa..abe5a72 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -2,6 +2,11 @@ name: CI
on:
pull_request:
+ types:
+ - opened
+ - synchronize
+ - reopened
+ - closed
push:
branches:
- main
@@ -19,6 +24,7 @@ env:
jobs:
validate-cockpit:
+ if: ${{ !(github.event_name == 'pull_request' && github.event.action == 'closed') }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
@@ -39,6 +45,7 @@ jobs:
run: pnpm nx run-many --projects=cockpit -t lint typecheck test
validate-backend:
+ if: ${{ !(github.event_name == 'pull_request' && github.event.action == 'closed') }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
@@ -63,6 +70,7 @@ jobs:
run: pnpm nx run-many --projects=backend -t lint typecheck test
validate-i12e:
+ if: ${{ !(github.event_name == 'pull_request' && github.event.action == 'closed') }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
@@ -86,6 +94,7 @@ jobs:
run: docker compose --env-file i12e/orchestrator/deploy/.env.prod.example --file i12e/orchestrator/deploy/docker-compose.prod.yml config --quiet
validate-release-ref:
+ if: ${{ !(github.event_name == 'pull_request' && github.event.action == 'closed') }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
@@ -99,6 +108,7 @@ jobs:
git merge-base --is-ancestor "$GITHUB_SHA" origin/main
build-image-cockpit:
+ if: ${{ !(github.event_name == 'pull_request' && github.event.action == 'closed') }}
runs-on: ubuntu-latest
needs:
- validate-release-ref
@@ -108,28 +118,31 @@ jobs:
with:
fetch-depth: 0
+ - name: Log in to GHCR
+ uses: docker/login-action@v4
+ with:
+ registry: ${{ env.REGISTRY }}
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
- name: Build cockpit image
shell: bash
run: |
set -euo pipefail
image_base="${REGISTRY}/${IMAGE_NAMESPACE,,}"
- sha_tag="sha-${GITHUB_SHA::12}"
- image="${image_base}/app-cockpit:${sha_tag}"
+ image_tag="sha-${GITHUB_SHA::12}"
+ if [ "${GITHUB_EVENT_NAME}" = "pull_request" ]; then
+ image_tag="pr-${{ github.event.pull_request.number }}-${GITHUB_SHA::12}"
+ fi
+ image="${image_base}/app-cockpit:${image_tag}"
docker build --file apps/cockpit/Dockerfile --tag "$image" .
- mkdir -p dist/images
- docker save "$image" --output dist/images/app-cockpit.tar
-
- - name: Upload cockpit image
- uses: actions/upload-artifact@v7
- with:
- name: image-app-cockpit
- path: dist/images/app-cockpit.tar
- retention-days: 1
+ docker push "$image"
build-image-backend:
+ if: ${{ !(github.event_name == 'pull_request' && github.event.action == 'closed') }}
runs-on: ubuntu-latest
needs:
- validate-release-ref
@@ -139,28 +152,31 @@ jobs:
with:
fetch-depth: 0
+ - name: Log in to GHCR
+ uses: docker/login-action@v4
+ with:
+ registry: ${{ env.REGISTRY }}
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
- name: Build backend image
shell: bash
run: |
set -euo pipefail
image_base="${REGISTRY}/${IMAGE_NAMESPACE,,}"
- sha_tag="sha-${GITHUB_SHA::12}"
- image="${image_base}/service-backend:${sha_tag}"
+ image_tag="sha-${GITHUB_SHA::12}"
+ if [ "${GITHUB_EVENT_NAME}" = "pull_request" ]; then
+ image_tag="pr-${{ github.event.pull_request.number }}-${GITHUB_SHA::12}"
+ fi
+ image="${image_base}/service-backend:${image_tag}"
docker build --file services/backend/Dockerfile --tag "$image" .
- mkdir -p dist/images
- docker save "$image" --output dist/images/service-backend.tar
-
- - name: Upload backend image
- uses: actions/upload-artifact@v7
- with:
- name: image-service-backend
- path: dist/images/service-backend.tar
- retention-days: 1
+ docker push "$image"
build-images-i12e:
+ if: ${{ !(github.event_name == 'pull_request' && github.event.action == 'closed') }}
runs-on: ubuntu-latest
needs:
- validate-release-ref
@@ -170,30 +186,34 @@ jobs:
with:
fetch-depth: 0
+ - name: Log in to GHCR
+ uses: docker/login-action@v4
+ with:
+ registry: ${{ env.REGISTRY }}
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
- name: Build i12e images
shell: bash
run: |
set -euo pipefail
image_base="${REGISTRY}/${IMAGE_NAMESPACE,,}"
- sha_tag="sha-${GITHUB_SHA::12}"
- postgres_image="${image_base}/i12e-postgres:${sha_tag}"
- gateway_image="${image_base}/i12e-gateway:${sha_tag}"
+ image_tag="sha-${GITHUB_SHA::12}"
+ if [ "${GITHUB_EVENT_NAME}" = "pull_request" ]; then
+ image_tag="pr-${{ github.event.pull_request.number }}-${GITHUB_SHA::12}"
+ fi
+ postgres_image="${image_base}/i12e-postgres:${image_tag}"
+ gateway_image="${image_base}/i12e-gateway:${image_tag}"
docker build --file i12e/postgres/Dockerfile --tag "$postgres_image" i12e/postgres
docker build --file i12e/gateway/Dockerfile --tag "$gateway_image" .
- mkdir -p dist/images
- docker save "$postgres_image" "$gateway_image" --output dist/images/i12e.tar
-
- - name: Upload i12e images
- uses: actions/upload-artifact@v7
- with:
- name: images-i12e
- path: dist/images/i12e.tar
- retention-days: 1
+ docker push "$postgres_image"
+ docker push "$gateway_image"
test-images-integration:
+ if: ${{ !(github.event_name == 'pull_request' && github.event.action == 'closed') }}
runs-on: ubuntu-latest
needs:
- build-image-cockpit
@@ -204,25 +224,22 @@ jobs:
with:
fetch-depth: 0
- - name: Download images
- uses: actions/download-artifact@v4
- with:
- pattern: image-*
- path: dist/images
- merge-multiple: true
-
- - name: Download i12e images
- uses: actions/download-artifact@v4
+ - name: Log in to GHCR
+ uses: docker/login-action@v4
with:
- name: images-i12e
- path: dist/images
+ registry: ${{ env.REGISTRY }}
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
- name: Smoke test core image set
shell: bash
run: |
set -euo pipefail
- sha_tag="sha-${GITHUB_SHA::12}"
+ image_tag="sha-${GITHUB_SHA::12}"
+ if [ "${GITHUB_EVENT_NAME}" = "pull_request" ]; then
+ image_tag="pr-${{ github.event.pull_request.number }}-${GITHUB_SHA::12}"
+ fi
ci_env_file="$(mktemp)"
compose_ci() {
@@ -236,12 +253,14 @@ jobs:
trap cleanup EXIT
- docker load --input dist/images/app-cockpit.tar
- docker load --input dist/images/service-backend.tar
- docker load --input dist/images/i12e.tar
+ image_base="${REGISTRY}/${IMAGE_NAMESPACE,,}"
+ docker pull "${image_base}/app-cockpit:${image_tag}"
+ docker pull "${image_base}/service-backend:${image_tag}"
+ docker pull "${image_base}/i12e-postgres:${image_tag}"
+ docker pull "${image_base}/i12e-gateway:${image_tag}"
{
- echo "CENTRAL_VERSION=$sha_tag"
+ echo "CENTRAL_VERSION=$image_tag"
echo "COMPOSE_PROJECT_NAME=central-ci-${GITHUB_RUN_ID}"
echo "SERVICE_RESTART_POLICY=no"
echo "GATEWAY_BIND=127.0.0.1"
@@ -270,21 +289,8 @@ jobs:
needs:
- test-images-integration
steps:
- - name: Download app and service images
- uses: actions/download-artifact@v4
- with:
- pattern: image-*
- path: dist/images
- merge-multiple: true
-
- - name: Download i12e images
- uses: actions/download-artifact@v4
- with:
- name: images-i12e
- path: dist/images
-
- name: Log in to GHCR
- uses: docker/login-action@v3
+ uses: docker/login-action@v4
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
@@ -307,15 +313,11 @@ jobs:
fi
fi
- docker load --input dist/images/app-cockpit.tar
- docker load --input dist/images/service-backend.tar
- docker load --input dist/images/i12e.tar
-
publish_image() {
local name="$1"
local image="${image_base}/${name}"
- docker push "${image}:${sha_tag}"
+ docker pull "${image}:${sha_tag}"
if [ -n "$version_tag" ]; then
docker tag "${image}:${sha_tag}" "${image}:${version_tag}"
@@ -333,6 +335,59 @@ jobs:
publish_image i12e-postgres
publish_image i12e-gateway
+ cleanup-pr-images:
+ runs-on: ubuntu-latest
+ if: github.event_name == 'pull_request' && github.event.action == 'closed'
+ steps:
+ - name: Delete closed PR images
+ uses: actions/github-script@v8
+ with:
+ script: |
+ const owner = context.repo.owner;
+ const ownerType = context.payload.repository.owner.type;
+ const packageNames = [
+ 'central/app-cockpit',
+ 'central/service-backend',
+ 'central/i12e-postgres',
+ 'central/i12e-gateway',
+ ];
+ const prTagPrefix = `pr-${context.payload.pull_request.number}-`;
+
+ for (const packageName of packageNames) {
+ const listRoute =
+ ownerType === 'Organization'
+ ? 'GET /orgs/{org}/packages/{package_type}/{package_name}/versions'
+ : 'GET /user/packages/{package_type}/{package_name}/versions';
+ const deleteRoute =
+ ownerType === 'Organization'
+ ? 'DELETE /orgs/{org}/packages/{package_type}/{package_name}/versions/{package_version_id}'
+ : 'DELETE /user/packages/{package_type}/{package_name}/versions/{package_version_id}';
+ const packageOwner = ownerType === 'Organization' ? { org: owner } : {};
+
+ for await (const versions of github.paginate.iterator(listRoute, {
+ ...packageOwner,
+ package_type: 'container',
+ package_name: packageName,
+ per_page: 100,
+ })) {
+ for (const version of versions.data) {
+ const tags = version.metadata?.container?.tags ?? [];
+ const hasClosedPrTag = tags.some((tag) => tag.startsWith(prTagPrefix));
+
+ if (!hasClosedPrTag) {
+ continue;
+ }
+
+ await github.request(deleteRoute, {
+ ...packageOwner,
+ package_type: 'container',
+ package_name: packageName,
+ package_version_id: version.id,
+ });
+ }
+ }
+ }
+
package-deploy-bundle:
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/')
@@ -357,3 +412,4 @@ jobs:
with:
name: central-deploy-${{ github.ref_name }}
path: dist/central-deploy-${{ github.ref_name }}.tar.gz
+ retention-days: 1
diff --git a/apps/cockpit/Dockerfile b/apps/cockpit/Dockerfile
index 3dabe27..b9b0603 100644
--- a/apps/cockpit/Dockerfile
+++ b/apps/cockpit/Dockerfile
@@ -17,7 +17,6 @@ WORKDIR /workspace
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
COPY apps/cockpit/package.json apps/cockpit/package.json
-COPY apps/cockpit/scripts/ apps/cockpit/scripts/
COPY libs/ts-log/package.json libs/ts-log/package.json
RUN pnpm install --frozen-lockfile
@@ -28,11 +27,27 @@ WORKDIR /workspace/apps/cockpit
EXPOSE 3000
CMD ["pnpm", "exec", "vite", "dev", "--host", "0.0.0.0", "--port", "3000", "--strictPort"]
-FROM base AS prod
+FROM base AS build
COPY . .
-RUN pnpm --dir apps/cockpit run build
+RUN pnpm --dir apps/cockpit run build \
+ && pnpm --filter @central/cockpit deploy --prod --legacy /workspace/cockpit-deploy
+
+FROM node:24-alpine AS prod
+ARG BACKEND_BASE_URL=http://localhost:5010
+ARG ASSISTANT_SERVICE_BASE_URL=http://localhost:5020
+ARG VITE_BACKEND_API_BASE_URL=http://localhost:5010
+ARG VITE_ASSISTANT_API_BASE_URL=http://localhost:5020
+ENV BACKEND_BASE_URL=$BACKEND_BASE_URL
+ENV VITE_BACKEND_API_BASE_URL=$VITE_BACKEND_API_BASE_URL
+ENV ASSISTANT_SERVICE_BASE_URL=$ASSISTANT_SERVICE_BASE_URL
+ENV VITE_ASSISTANT_API_BASE_URL=$VITE_ASSISTANT_API_BASE_URL
WORKDIR /workspace/apps/cockpit
+
+COPY --from=build /workspace/cockpit-deploy/node_modules ./node_modules
+COPY --from=build /workspace/cockpit-deploy/package.json ./package.json
+COPY --from=build /workspace/apps/cockpit/dist ./dist
+
EXPOSE 3000
-CMD ["pnpm", "exec", "vite", "preview", "--host", "0.0.0.0", "--port", "3000", "--strictPort"]
+CMD ["node", "node_modules/srvx/bin/srvx.mjs", "serve", "--dir", ".", "--entry", "dist/server/server.js", "--static", "dist/client", "--prod"]
diff --git a/apps/cockpit/README.md b/apps/cockpit/README.md
index 622702b..bad27fa 100644
--- a/apps/cockpit/README.md
+++ b/apps/cockpit/README.md
@@ -67,8 +67,7 @@ The `/finance/cash` route manages manual income and expense transactions:
The voice widget keeps `service-assistant` as the backend boundary, but its primary turn path is now streamed:
- Browser speech segments are cut locally with browser VAD.
-- Browser VAD model/worklet assets are self-hosted from cockpit under `public/vendor/` instead of loading from a CDN.
-- The ONNX runtime module and WASM binary are self-hosted as Vite-managed app assets, so dev/build keep working without CDN requests.
+- Browser voice activity detection is temporarily disabled.
- The browser streams turns directly to `service-assistant` via `POST /api/v1/assistant/turn/stream`.
- `service-assistant` then performs `STT -> streamed LLM -> chunked TTS`.
- Cockpit starts audio playback as soon as the first synthesized chunk arrives.
@@ -85,15 +84,7 @@ Voice widget diagnostics are written as structured `@central/ts-log` records wit
For local debugging in Node-backed assistant turns, cockpit dumps artifacts into `apps/cockpit/tmp/` as input audio, per-chunk output audio files, and a JSON metadata file.
-Self-hosted voice assets are synchronized from the installed `@ricky0123/vad-web` and `onnxruntime-web` packages by:
-
-```bash
-pnpm --dir apps/cockpit run sync:voice-vad-assets
-```
-
-The workspace `postinstall` runs that sync automatically after `pnpm install` or dependency updates from the repository root.
-
-`build`, `start:dev`, `start:preview`, `test`, and `typecheck` also run the sync automatically before execution, so the matching runtime assets are always refreshed without manual copying.
+VAD asset synchronization is disabled while browser VAD is offline.
## Container
diff --git a/apps/cockpit/package.json b/apps/cockpit/package.json
index bc639d4..4f4fd4c 100644
--- a/apps/cockpit/package.json
+++ b/apps/cockpit/package.json
@@ -6,36 +6,30 @@
"#/*": "./src/*"
},
"scripts": {
- "sync:voice-vad-assets": "node scripts/sync-vad-assets.mjs",
- "prebuild": "pnpm run sync:voice-vad-assets",
"build": "vite build",
- "prestart:dev": "pnpm run sync:voice-vad-assets",
"start:dev": "vite dev --port 5000",
- "prestart:preview": "pnpm run sync:voice-vad-assets",
"start:preview": "vite preview",
- "pretest": "pnpm run sync:voice-vad-assets",
"test": "vitest run",
- "pretypecheck": "pnpm run sync:voice-vad-assets",
"typecheck": "tsc --noEmit -p tsconfig.json"
},
"dependencies": {
"@central/ts-log": "workspace:*",
"@meteocons/svg": "^0.1.0",
- "@ricky0123/vad-react": "0.0.33",
"@tailwindcss/vite": "4.2.1",
- "@tanstack/react-devtools": "0.9.6",
"@tanstack/react-router": "1.163.2",
- "@tanstack/react-router-devtools": "1.163.2",
"@tanstack/react-router-ssr-query": "1.163.2",
"@tanstack/react-start": "1.163.2",
"@tanstack/router-plugin": "1.163.2",
"react": "19.2.4",
"react-dom": "19.2.4",
"react-icons": "5.5.0",
+ "srvx": "0.11.8",
"tailwindcss": "4.3.0"
},
"devDependencies": {
"@tanstack/devtools-vite": "0.5.1",
+ "@tanstack/react-devtools": "0.9.6",
+ "@tanstack/react-router-devtools": "1.163.2",
"@testing-library/dom": "10.4.1",
"@testing-library/react": "16.3.2",
"@testing-library/user-event": "14.6.1",
diff --git a/apps/cockpit/scripts/sync-vad-assets.mjs b/apps/cockpit/scripts/sync-vad-assets.mjs
deleted file mode 100644
index c966aa5..0000000
--- a/apps/cockpit/scripts/sync-vad-assets.mjs
+++ /dev/null
@@ -1,179 +0,0 @@
-import { cp, mkdir, readFile, readdir, rm, stat, writeFile } from 'node:fs/promises'
-import path from 'node:path'
-import { fileURLToPath } from 'node:url'
-import { createRequire } from 'node:module'
-
-const __filename = fileURLToPath(import.meta.url)
-const __dirname = path.dirname(__filename)
-const cockpitRoot = path.resolve(__dirname, '..')
-const publicVendorRoot = path.join(cockpitRoot, 'public', 'vendor')
-const generatedVoiceAssetRoot = path.join(cockpitRoot, 'src', 'widgets', 'voice', 'generated')
-const manifestPath = path.join(publicVendorRoot, 'voice-vad-assets.manifest.json')
-const legacyOnnxPublicAssetRoot = path.join(publicVendorRoot, 'onnxruntime-web')
-
-const require = createRequire(import.meta.url)
-const vadReactPackageJsonPath = require.resolve('@ricky0123/vad-react/package.json')
-const vadReactRequire = createRequire(vadReactPackageJsonPath)
-
-function packageRootFromPackageJson(packageJsonPath) {
- return path.dirname(packageJsonPath)
-}
-
-async function readPackageVersion(packageJsonPath) {
- const packageJson = JSON.parse(await readFile(packageJsonPath, 'utf8'))
- if (typeof packageJson.version !== 'string' || packageJson.version.length === 0) {
- throw new Error(`Package at ${packageJsonPath} does not declare a valid version.`)
- }
-
- return packageJson.version
-}
-
-async function resolvePackageJsonPath(packageName, resolver) {
- const entryPath = resolver.resolve(packageName)
- let currentDirectory = path.dirname(entryPath)
-
- while (true) {
- const packageJsonPath = path.join(currentDirectory, 'package.json')
-
- try {
- const packageJson = JSON.parse(await readFile(packageJsonPath, 'utf8'))
- if (packageJson.name === packageName) {
- return packageJsonPath
- }
- } catch {
- // keep walking up to the package root
- }
-
- const parentDirectory = path.dirname(currentDirectory)
- if (parentDirectory === currentDirectory) {
- break
- }
-
- currentDirectory = parentDirectory
- }
-
- throw new Error(`Failed to locate package.json for ${packageName}.`)
-}
-
-async function ensureFilesExist(directory, requiredFiles) {
- for (const requiredFile of requiredFiles) {
- const requiredPath = path.join(directory, requiredFile)
- try {
- await stat(requiredPath)
- } catch (error) {
- throw new Error(
- `Expected runtime asset "${requiredFile}" in ${directory}, but it was not found.`,
- { cause: error },
- )
- }
- }
-}
-
-async function copyFiles(sourceDirectory, destinationDirectory, files) {
- await rm(destinationDirectory, { force: true, recursive: true })
- await mkdir(destinationDirectory, { recursive: true })
-
- for (const file of files) {
- const sourcePath = path.join(sourceDirectory, file)
- const destinationPath = path.join(destinationDirectory, file)
-
- await mkdir(path.dirname(destinationPath), { recursive: true })
- await cp(sourcePath, destinationPath)
- }
-}
-
-async function countFiles(directory) {
- const entries = await stat(directory)
- if (!entries.isDirectory()) {
- return 0
- }
-
- let fileCount = 0
- const stack = [directory]
-
- while (stack.length > 0) {
- const currentDirectory = stack.pop()
- const children = await readdir(currentDirectory, { withFileTypes: true })
-
- for (const child of children) {
- const childPath = path.join(currentDirectory, child.name)
- if (child.isDirectory()) {
- stack.push(childPath)
- continue
- }
-
- if (child.isFile()) {
- fileCount += 1
- }
- }
- }
-
- return fileCount
-}
-
-async function syncPackageAssets({ destinationName, packageName, requiredFiles, resolver = require }) {
- const packageJsonPath = await resolvePackageJsonPath(packageName, resolver)
- const packageRoot = packageRootFromPackageJson(packageJsonPath)
- const version = await readPackageVersion(packageJsonPath)
- const sourceDirectory = path.join(packageRoot, 'dist')
- const destinationDirectory = path.join(cockpitRoot, destinationName)
-
- await ensureFilesExist(sourceDirectory, requiredFiles)
- await copyFiles(sourceDirectory, destinationDirectory, requiredFiles)
- await ensureFilesExist(destinationDirectory, requiredFiles)
-
- return {
- destinationDirectory,
- destinationName,
- fileCount: await countFiles(destinationDirectory),
- packageName,
- sourceDirectory,
- version,
- }
-}
-
-async function run() {
- await rm(legacyOnnxPublicAssetRoot, { force: true, recursive: true })
-
- const copiedPackages = await Promise.all([
- syncPackageAssets({
- destinationName: path.join('public', 'vendor', 'vad'),
- packageName: '@ricky0123/vad-web',
- requiredFiles: ['silero_vad_legacy.onnx', 'silero_vad_v5.onnx', 'vad.worklet.bundle.min.js'],
- resolver: vadReactRequire,
- }),
- syncPackageAssets({
- destinationName: path.join('src', 'widgets', 'voice', 'generated', 'onnxruntime-web'),
- packageName: 'onnxruntime-web',
- requiredFiles: ['ort-wasm-simd-threaded.jsep.mjs', 'ort-wasm-simd-threaded.jsep.wasm'],
- resolver: vadReactRequire,
- }),
- ])
-
- const manifest = {
- copiedAt: new Date().toISOString(),
- packages: copiedPackages.map((copiedPackage) => ({
- destinationDirectory: path.relative(cockpitRoot, copiedPackage.destinationDirectory),
- destinationName: copiedPackage.destinationName,
- fileCount: copiedPackage.fileCount,
- packageName: copiedPackage.packageName,
- sourceDirectory: path.relative(cockpitRoot, copiedPackage.sourceDirectory),
- version: copiedPackage.version,
- })),
- }
-
- await mkdir(publicVendorRoot, { recursive: true })
- await mkdir(generatedVoiceAssetRoot, { recursive: true })
- await writeFile(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`, 'utf8')
-
- for (const copiedPackage of copiedPackages) {
- console.log(
- `Synced ${copiedPackage.packageName}@${copiedPackage.version} -> ${path.relative(cockpitRoot, copiedPackage.destinationDirectory)} (${copiedPackage.fileCount} files)`,
- )
- }
-}
-
-run().catch((error) => {
- console.error(error instanceof Error ? error.message : error)
- process.exitCode = 1
-})
diff --git a/apps/cockpit/src/domain/assistant/Jarvis/Jarvis.tsx b/apps/cockpit/src/domain/assistant/Jarvis/Jarvis.tsx
index f6c102f..a98013d 100644
--- a/apps/cockpit/src/domain/assistant/Jarvis/Jarvis.tsx
+++ b/apps/cockpit/src/domain/assistant/Jarvis/Jarvis.tsx
@@ -1,6 +1,5 @@
import 'src/domain/assistant/Jarvis/jarvis.css';
import { useCallback, useEffect, useMemo, useState } from 'react';
-import { useMicVAD } from '@ricky0123/vad-react';
import {
MdGraphicEq as OutputIcon,
MdMic as MicIcon,
@@ -9,8 +8,6 @@ import {
} from 'react-icons/md';
import { cx } from '@/utils/styles.ts';
import { formatJarvisPercent, type JarvisMode, resolveJarvisSystemState } from '@/domain/assistant/Jarvis/model.ts';
-import { configureVoiceOrt, VAD_BASE_ASSET_PATH } from '@/domain/voice/model/vadAssetPaths.ts';
-import { getFloat32SignalLevel } from '@/domain/voice/model/audioLevel.ts';
import { useVoiceConversation } from '@/domain/voice/model/useVoiceConversation.ts';
import { JarvisOrb } from '@/domain/assistant/Jarvis/JarvisOrb.tsx';
@@ -38,11 +35,6 @@ const INITIAL_MICROPHONE_STATE: MicrophoneState = {
userSpeaking: false,
};
-type ActiveMicrophoneProps = {
- onSpeechSegment: (audio: Float32Array) => Promise
- Sprich nach dem Aktivieren frei in das Mikrofon. Das Widget trennt Sprache lokal im Browser, sendet nur
- erkannte Sprachsegmente an den Assistant-Service und startet die Sprachausgabe bereits waehrend der Antwort.
+ Voice Activity Detection ist voruebergehend deaktiviert. Es werden keine Mikrofonsegmente erfasst oder an
+ den Assistant-Service gesendet.