chore: import upstream snapshot with attribution
Create PR to main with cherry-pick from release / cherry-pick (push) Failing after 0s
CICD NeMo / pre-flight (push) Failing after 0s
CICD NeMo / configure (push) Has been skipped
Build, validate, and release Neural Modules / pre-flight (push) Failing after 1s
CICD NeMo / code-linting (push) Has been skipped
Build, validate, and release Neural Modules / release (push) Has been skipped
Build, validate, and release Neural Modules / release-summary (push) Has been cancelled
CICD NeMo / cicd-test-container-build (push) Has been cancelled
CICD NeMo / cicd-import-tests (push) Has been cancelled
CICD NeMo / L0_Setup_Test_Data_And_Models (push) Has been cancelled
CICD NeMo / cicd-main-unit-tests (push) Has been cancelled
CICD NeMo / cicd-main-speech (push) Has been cancelled
CICD NeMo / Nemo_CICD_Test (push) Has been cancelled
CICD NeMo / Coverage (e2e) (push) Has been cancelled
CICD NeMo / Coverage (unit-test) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
CICD NeMo / cicd-wait-in-queue (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 13:28:58 +08:00
commit ba4be087d5
2316 changed files with 2668701 additions and 0 deletions
+85
View File
@@ -0,0 +1,85 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>NeMo Voice Agent</title>
<style>
.server-selection {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 10px;
}
.server-selection label {
font-weight: bold;
color: #333;
}
.server-selection select {
padding: 6px 12px;
border: 1px solid #ccc;
border-radius: 4px;
background-color: white;
font-size: 14px;
cursor: pointer;
}
.server-selection select:focus {
outline: none;
border-color: #2196F3;
box-shadow: 0 0 0 2px rgba(33, 150, 243, 0.2);
}
.server-selection select:disabled {
background-color: #f5f5f5;
cursor: not-allowed;
opacity: 0.6;
}
</style>
</head>
<body>
<div class="container">
<div class="status-bar">
<div class="status">
Transport: <span id="connection-status">Disconnected</span>
</div>
<div class="server-selection">
<label for="server-select">Server:</label>
<select id="server-select">
<option value="websocket">WebSocket Server (Port 8765)</option>
<option value="fastapi">FastAPI Server (Port 8000)</option>
</select>
</div>
<div class="controls">
<button id="connect-btn">Connect</button>
<button id="disconnect-btn" disabled>Disconnect</button>
<button id="mute-btn" disabled>Mute</button>
<button id="reset-btn" disabled>Reset</button>
</div>
</div>
<div class="volume-indicator">
<div class="volume-label">Microphone Volume:</div>
<div class="volume-bar-container">
<div class="volume-bar" id="volume-bar"></div>
</div>
<div class="volume-text" id="volume-text">0%</div>
</div>
<audio id="bot-audio" autoplay></audio>
<div class="debug-panel">
<h3>Debug Info</h3>
<div id="debug-log"></div>
</div>
</div>
<script type="module" src="/src/app.ts"></script>
<link rel="stylesheet" href="/src/style.css">
</body>
</html>
File diff suppressed because it is too large Load Diff
+30
View File
@@ -0,0 +1,30 @@
{
"name": "client",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"preview": "vite preview"
},
"keywords": [],
"author": "",
"license": "ISC",
"description": "",
"devDependencies": {
"@types/node": "^22.15.30",
"@types/protobufjs": "^6.0.0",
"@types/react": "^19.2.2",
"@types/react-dom": "^19.2.2",
"@vitejs/plugin-react-swc": "^3.10.1",
"typescript": "^5.8.3",
"vite": "^6.3.5"
},
"dependencies": {
"@pipecat-ai/client-js": "^0.4.0",
"@pipecat-ai/websocket-transport": "^0.4.1",
"protobufjs": "^7.4.0",
"react": "^19.2.0",
"react-dom": "^19.2.0"
}
}
+572
View File
@@ -0,0 +1,572 @@
/**
* Copyright (c) 20242025, Daily
*
* SPDX-License-Identifier: BSD 2-Clause License
*/
/**
* RTVI Client Implementation
*
* This client connects to an RTVI-compatible bot server using WebSocket.
*
* Requirements:
* - A running RTVI bot server (defaults to http://localhost:7860)
*/
import {
RTVIClient,
RTVIClientOptions,
RTVIEvent,
} from '@pipecat-ai/client-js';
import {
WebSocketTransport
} from "@pipecat-ai/websocket-transport";
class WebsocketClientApp {
private rtviClient: RTVIClient | null = null;
private connectBtn: HTMLButtonElement | null = null;
private disconnectBtn: HTMLButtonElement | null = null;
private muteBtn: HTMLButtonElement | null = null;
private resetBtn: HTMLButtonElement | null = null;
private serverSelect: HTMLSelectElement | null = null;
private statusSpan: HTMLElement | null = null;
private debugLog: HTMLElement | null = null;
private volumeBar: HTMLElement | null = null;
private volumeText: HTMLElement | null = null;
private botAudio: HTMLAudioElement;
private isConnecting: boolean = false;
private isDisconnecting: boolean = false;
private isMuted: boolean = false;
private audioContext: AudioContext | null = null;
private analyser: AnalyserNode | null = null;
private microphone: MediaStreamAudioSourceNode | null = null;
private volumeUpdateInterval: number | null = null;
private currentBotMessageElement: HTMLDivElement | null = null;
private currentBotMessage: string = '';
// Server configurations
private readonly serverConfigs = {
websocket: {
name: 'WebSocket Server',
baseUrl: `http://${window.location.hostname}:7860`,
port: 8765
},
fastapi: {
name: 'FastAPI Server',
baseUrl: `http://${window.location.hostname}:8000`,
port: 8000
}
};
constructor() {
console.log("WebsocketClientApp");
this.botAudio = document.createElement('audio');
this.botAudio.autoplay = true;
//this.botAudio.playsInline = true;
document.body.appendChild(this.botAudio);
this.setupDOMElements();
this.setupEventListeners();
}
/**
* Set up references to DOM elements and create necessary media elements
*/
private setupDOMElements(): void {
this.connectBtn = document.getElementById('connect-btn') as HTMLButtonElement;
this.disconnectBtn = document.getElementById('disconnect-btn') as HTMLButtonElement;
this.muteBtn = document.getElementById('mute-btn') as HTMLButtonElement;
this.resetBtn = document.getElementById('reset-btn') as HTMLButtonElement;
this.serverSelect = document.getElementById('server-select') as HTMLSelectElement;
this.statusSpan = document.getElementById('connection-status');
this.debugLog = document.getElementById('debug-log');
this.volumeBar = document.getElementById('volume-bar');
this.volumeText = document.getElementById('volume-text');
}
/**
* Set up event listeners for connect/disconnect buttons
*/
private setupEventListeners(): void {
this.connectBtn?.addEventListener('click', () => this.connect());
this.disconnectBtn?.addEventListener('click', () => this.disconnect());
this.muteBtn?.addEventListener('click', () => this.toggleMute());
this.resetBtn?.addEventListener('click', () => this.reset());
this.serverSelect?.addEventListener('change', () => this.updateServerUrl());
}
/**
* Add a timestamped message to the debug log
*/
private log(message: string): void {
if (!this.debugLog) return;
const entry = document.createElement('div');
entry.textContent = `${new Date().toISOString()} - ${message}`;
if (message.startsWith('User: ')) {
entry.style.color = '#2196F3';
} else if (message.startsWith('Bot: ')) {
entry.style.color = '#4CAF50';
}
this.debugLog.appendChild(entry);
this.debugLog.scrollTop = this.debugLog.scrollHeight;
console.log(message);
}
/**
* Create a bot message element and add it to the debug log
*/
private createBotMessageElement(initialText: string): HTMLDivElement | null {
if (!this.debugLog) return null;
const entry = document.createElement('div');
entry.style.color = '#4CAF50';
entry.textContent = `${new Date().toISOString()} - ${initialText}`;
this.debugLog.appendChild(entry);
this.debugLog.scrollTop = this.debugLog.scrollHeight;
return entry;
}
/**
* Update the connection status display
*/
private updateStatus(status: string): void {
if (this.statusSpan) {
this.statusSpan.textContent = status;
}
this.log(`Status: ${status}`);
}
/**
* Check for available media tracks and set them up if present
* This is called when the bot is ready or when the transport state changes to ready
*/
setupMediaTracks() {
if (!this.rtviClient) return;
const tracks = this.rtviClient.tracks();
if (tracks.bot?.audio) {
this.setupAudioTrack(tracks.bot.audio);
}
}
/**
* Set up listeners for track events (start/stop)
* This handles new tracks being added during the session
*/
setupTrackListeners() {
if (!this.rtviClient) {
this.log('Cannot setup track listeners: client is null');
return;
}
try {
// Listen for new tracks starting
this.rtviClient.on(RTVIEvent.TrackStarted, (track, participant) => {
// Only handle non-local (bot) tracks
if (!participant?.local && track.kind === 'audio') {
this.setupAudioTrack(track);
}
});
// Listen for tracks stopping
this.rtviClient.on(RTVIEvent.TrackStopped, (track, participant) => {
this.log(`Track stopped: ${track.kind} from ${participant?.name || 'unknown'}`);
});
} catch (error) {
this.log(`Error setting up track listeners: ${error}`);
}
}
/**
* Set up an audio track for playback
* Handles both initial setup and track updates
*/
private setupAudioTrack(track: MediaStreamTrack): void {
this.log('Setting up audio track');
if (this.botAudio.srcObject && "getAudioTracks" in this.botAudio.srcObject) {
const oldTrack = this.botAudio.srcObject.getAudioTracks()[0];
if (oldTrack?.id === track.id) return;
}
this.botAudio.srcObject = new MediaStream([track]);
}
/**
* Initialize and connect to the bot
* This sets up the RTVI client, initializes devices, and establishes the connection
*/
public async connect(): Promise<void> {
if (this.isConnecting) {
this.log('Connection already in progress, ignoring...');
return;
}
try {
this.isConnecting = true;
const startTime = Date.now();
//const transport = new DailyTransport();
const transport = new WebSocketTransport();
const RTVIConfig: RTVIClientOptions = {
transport,
params: {
// The baseURL and endpoint of your bot server that the client will connect to
baseUrl: this.getSelectedServerConfig().baseUrl,
endpoints: { connect: '/connect' },
},
enableMic: true,
enableCam: false,
callbacks: {
onConnected: () => {
this.updateStatus('Connected');
if (this.connectBtn) this.connectBtn.disabled = true;
if (this.disconnectBtn) this.disconnectBtn.disabled = false;
if (this.muteBtn) {
this.muteBtn.disabled = false;
this.muteBtn.textContent = 'Mute';
}
if (this.resetBtn) this.resetBtn.disabled = false;
if (this.serverSelect) this.serverSelect.disabled = true;
// Start volume monitoring when connected
if (!this.isMuted) {
this.startVolumeMonitoring();
}
},
onDisconnected: () => {
// Only handle disconnect if we're not in the middle of error cleanup
if (!this.isConnecting) {
this.updateStatus('Disconnected');
if (this.connectBtn) this.connectBtn.disabled = false;
if (this.disconnectBtn) this.disconnectBtn.disabled = true;
if (this.muteBtn) {
this.muteBtn.disabled = true;
this.muteBtn.textContent = 'Mute';
}
if (this.resetBtn) this.resetBtn.disabled = true;
if (this.serverSelect) this.serverSelect.disabled = false;
// Stop volume monitoring when disconnected
this.stopVolumeMonitoring();
this.log('Client disconnected');
}
},
onBotReady: (data) => {
this.log(`Bot ready: ${JSON.stringify(data)}`);
this.setupMediaTracks();
},
onUserTranscript: (data) => {
if (data.final) {
this.log(`User: ${data.text}`);
}
},
onBotTranscript: (data) => {
// If no current element exists, create one (fallback in case BOT_LLM_STARTED didn't fire)
if (!this.currentBotMessageElement) {
this.currentBotMessage = '';
this.currentBotMessageElement = this.createBotMessageElement('Bot: ');
}
// Accumulate the text
this.currentBotMessage += data.text;
// Update the current element
if (this.currentBotMessageElement) {
const timestamp = new Date().toISOString();
this.currentBotMessageElement.textContent = `${timestamp} - Bot: ${this.currentBotMessage}`;
this.debugLog?.scrollTo({ top: this.debugLog.scrollHeight, behavior: 'smooth' });
}
},
onBotLlmStarted: () => {
// Only create a new bot message element if the current one has content
if (this.currentBotMessage !== '') {
this.currentBotMessage = '';
this.currentBotMessageElement = this.createBotMessageElement('Bot: ');
} else if (!this.currentBotMessageElement) {
// Create element if it doesn't exist at all
this.currentBotMessage = '';
this.currentBotMessageElement = this.createBotMessageElement('Bot: ');
}
},
onMessageError: (error) => console.error('Message error:', error),
onError: (error) => console.error('Error:', error),
},
}
// Create the client with error handling
try {
this.rtviClient = new RTVIClient(RTVIConfig);
this.setupTrackListeners();
} catch (clientError) {
this.log(`Error creating RTVI client: ${clientError}`);
throw clientError;
}
this.log('Initializing devices...');
await this.rtviClient.initDevices();
this.log('Devices initialized successfully');
this.log('Connecting to bot...');
await this.rtviClient.connect();
const timeTaken = Date.now() - startTime;
this.log(`Connection complete, timeTaken: ${timeTaken}`);
} catch (error) {
this.log(`Error connecting: ${(error as Error).message}`);
this.updateStatus('Error');
// Clean up if there's an error
await this.cleanupOnError();
} finally {
this.isConnecting = false;
}
}
/**
* Clean up resources when there's an error during connection
*/
private async cleanupOnError(): Promise<void> {
// Set disconnecting flag to prevent onDisconnected callback interference
this.isDisconnecting = true;
// Store reference to client before it might become null
const client = this.rtviClient;
if (client) {
try {
// Check if the client is in a state where disconnect can be called
if (typeof client.disconnect === 'function') {
await client.disconnect();
}
} catch (disconnectError) {
this.log(`Error during cleanup disconnect: ${disconnectError}`);
} finally {
// Always reset the client to null to allow reconnection
this.rtviClient = null;
}
} else {
this.log('Client was already null during cleanup');
}
// Reset button states
if (this.connectBtn) this.connectBtn.disabled = false;
if (this.disconnectBtn) this.disconnectBtn.disabled = true;
if (this.muteBtn) {
this.muteBtn.disabled = true;
this.muteBtn.textContent = 'Mute';
}
if (this.resetBtn) this.resetBtn.disabled = true;
if (this.serverSelect) this.serverSelect.disabled = false;
// Stop volume monitoring
this.stopVolumeMonitoring();
// Clean up bot message state
this.currentBotMessage = '';
this.currentBotMessageElement = null;
// Reset mute state
this.isMuted = false;
// Reset disconnecting flag
this.isDisconnecting = false;
}
/**
* Disconnect from the bot and clean up media resources
*/
public async disconnect(): Promise<void> {
if (this.isDisconnecting) {
this.log('Disconnection already in progress, ignoring...');
return;
}
this.isDisconnecting = true;
// Store reference to client before it might become null
const client = this.rtviClient;
if (client) {
try {
// Check if the client is in a state where disconnect can be called
if (typeof client.disconnect === 'function') {
await client.disconnect();
}
} catch (error) {
this.log(`Error disconnecting: ${(error as Error).message}`);
} finally {
// Always clean up resources and reset the client
this.rtviClient = null;
if (this.botAudio.srcObject && "getAudioTracks" in this.botAudio.srcObject) {
this.botAudio.srcObject.getAudioTracks().forEach((track) => track.stop());
this.botAudio.srcObject = null;
}
}
} else {
this.log('Client was already null during disconnect');
}
// Stop volume monitoring
this.stopVolumeMonitoring();
// Clean up bot message state
this.currentBotMessage = '';
this.currentBotMessageElement = null;
// Reset mute state
this.isMuted = false;
this.isDisconnecting = false;
}
/**
* Toggle microphone mute/unmute
*/
private toggleMute(): void {
if (!this.rtviClient) {
this.log('Cannot toggle mute: client is null');
return;
}
this.isMuted = !this.isMuted;
this.rtviClient.enableMic(!this.isMuted);
// Update button text
if (this.muteBtn) {
this.muteBtn.textContent = this.isMuted ? 'Unmute' : 'Mute';
}
// Update volume monitoring
if (this.isMuted) {
this.stopVolumeMonitoring();
} else {
this.startVolumeMonitoring();
}
this.log(this.isMuted ? 'Microphone muted' : 'Microphone unmuted');
}
/**
* Start monitoring microphone volume
*/
private async startVolumeMonitoring(): Promise<void> {
try {
if (!this.audioContext) {
this.audioContext = new AudioContext();
}
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
this.analyser = this.audioContext.createAnalyser();
this.analyser.fftSize = 256;
this.analyser.smoothingTimeConstant = 0.8;
this.microphone = this.audioContext.createMediaStreamSource(stream);
this.microphone.connect(this.analyser);
// Start continuous volume updates
this.volumeUpdateInterval = window.setInterval(() => {
this.updateVolumeDisplay();
}, 100); // Update every 100ms
this.log('Volume monitoring started');
} catch (error) {
this.log(`Error starting volume monitoring: ${error}`);
}
}
/**
* Stop monitoring microphone volume
*/
private stopVolumeMonitoring(): void {
if (this.volumeUpdateInterval) {
clearInterval(this.volumeUpdateInterval);
this.volumeUpdateInterval = null;
}
if (this.microphone) {
this.microphone.disconnect();
this.microphone = null;
}
// Reset volume display
this.updateVolumeDisplay(0);
this.log('Volume monitoring stopped');
}
/**
* Update the volume display
*/
private updateVolumeDisplay(volume?: number): void {
if (!this.volumeBar || !this.volumeText) return;
if (volume === undefined && this.analyser) {
const dataArray = new Uint8Array(this.analyser.frequencyBinCount);
this.analyser.getByteFrequencyData(dataArray);
// Calculate average volume
const average = dataArray.reduce((sum, value) => sum + value, 0) / dataArray.length;
volume = (average / 255) * 100;
}
const displayVolume = volume || 0;
const clampedVolume = Math.min(100, Math.max(0, displayVolume));
this.volumeBar.style.width = `${clampedVolume}%`;
this.volumeText.textContent = `${Math.round(clampedVolume)}%`;
// Update color based on volume level
if (clampedVolume < 30) {
this.volumeBar.style.background = '#4caf50'; // Green
} else if (clampedVolume < 70) {
this.volumeBar.style.background = '#ff9800'; // Orange
} else {
this.volumeBar.style.background = '#f44336'; // Red
}
}
/**
* Reset the conversation context by calling the server action
*/
private async reset(): Promise<void> {
if (!this.rtviClient) {
this.log('Cannot reset: not connected to server');
return;
}
try {
this.log('Resetting conversation context...');
// Call the reset action on the server
const result = await this.rtviClient.action({ service: 'context', action: 'reset', arguments: [] });
if (result) {
this.log('Conversation context reset successfully');
} else {
this.log('Failed to reset conversation context');
}
} catch (error) {
this.log(`Error resetting context: ${error}`);
}
}
private getSelectedServerConfig(): { name: string; baseUrl: string; port: number } {
const selectedValue = this.serverSelect?.value || 'websocket';
return this.serverConfigs[selectedValue as keyof typeof this.serverConfigs];
}
private updateServerUrl(): void {
const selectedConfig = this.getSelectedServerConfig();
this.log(`Server changed to: ${selectedConfig.name} (${selectedConfig.baseUrl})`);
// If connected, show a message that they need to reconnect
if (this.rtviClient) {
this.log('Please disconnect and reconnect to use the new server');
}
}
}
declare global {
interface Window {
WebsocketClientApp: typeof WebsocketClientApp;
}
}
window.addEventListener('DOMContentLoaded', () => {
window.WebsocketClientApp = WebsocketClientApp;
new WebsocketClientApp();
});
+180
View File
@@ -0,0 +1,180 @@
body {
margin: 0;
padding: 20px;
font-family: Arial, sans-serif;
background-color: #f0f0f0;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
.status-bar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px;
background-color: #fff;
border-radius: 8px;
margin-bottom: 20px;
}
.controls button {
padding: 8px 16px;
margin-left: 10px;
border: none;
border-radius: 4px;
cursor: pointer;
}
#connect-btn {
background-color: #4caf50;
color: white;
}
#disconnect-btn {
background-color: #f44336;
color: white;
}
#mute-btn {
background-color: #ff9800;
color: white;
}
#mute-btn:disabled {
background-color: #ccc;
color: #666;
}
button:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.volume-indicator {
display: flex;
align-items: center;
gap: 10px;
padding: 10px;
background-color: #fff;
border-radius: 8px;
margin-bottom: 20px;
}
.volume-label {
font-weight: bold;
min-width: 120px;
}
.volume-bar-container {
flex: 1;
height: 20px;
background-color: #e0e0e0;
border-radius: 10px;
overflow: hidden;
position: relative;
}
.volume-bar {
height: 100%;
background: linear-gradient(90deg, #4caf50, #ff9800, #f44336);
width: 0%;
transition: width 0.1s ease;
border-radius: 10px;
}
.volume-text {
min-width: 40px;
text-align: right;
font-weight: bold;
font-size: 14px;
}
.main-content {
background-color: #fff;
border-radius: 8px;
padding: 20px;
margin-bottom: 20px;
}
.bot-container {
display: flex;
flex-direction: column;
align-items: center;
}
#bot-video-container {
width: 640px;
height: 360px;
background-color: #e0e0e0;
border-radius: 8px;
margin: 20px auto;
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
}
#bot-video-container video {
width: 100%;
height: 100%;
object-fit: cover;
}
.debug-panel {
background-color: #fff;
border-radius: 8px;
padding: 20px;
}
.debug-panel h3 {
margin: 0 0 10px 0;
font-size: 16px;
font-weight: bold;
}
#debug-log {
height: 500px;
overflow-y: auto;
background-color: #f8f8f8;
padding: 10px;
border-radius: 4px;
font-family: monospace;
font-size: 12px;
line-height: 1.4;
}
.server-selection {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 10px;
}
.server-selection label {
font-weight: bold;
color: #333;
}
.server-selection select {
padding: 6px 12px;
border: 1px solid #ccc;
border-radius: 4px;
background-color: white;
font-size: 14px;
cursor: pointer;
}
.server-selection select:focus {
outline: none;
border-color: #2196F3;
box-shadow: 0 0 0 2px rgba(33, 150, 243, 0.2);
}
.server-selection select:disabled {
background-color: #f5f5f5;
cursor: not-allowed;
opacity: 0.6;
}
+111
View File
@@ -0,0 +1,111 @@
{
"compilerOptions": {
/* Visit https://aka.ms/tsconfig to read more about this file */
/* Projects */
// "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
// "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
/* Language and Environment */
"target": "ES2020", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
"lib": ["ES2020", "DOM", "DOM.Iterable"], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
"jsx": "react-jsx", /* Specify what JSX code is generated. */
// "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
// "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
// "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
/* Modules */
"module": "ESNext", /* Specify what module code is generated. */
// "rootDir": "./", /* Specify the root folder within your source files. */
"moduleResolution": "bundler", /* Specify how TypeScript looks up a file from a given module specifier. */
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
// "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
// "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
// "rewriteRelativeImportExtensions": true, /* Rewrite '.ts', '.tsx', '.mts', and '.cts' file extensions in relative import paths to their JavaScript equivalent in output files. */
// "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */
// "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */
// "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */
// "noUncheckedSideEffectImports": true, /* Check side effect imports. */
"resolveJsonModule": true, /* Enable importing .json files. */
// "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */
// "noResolve": true, /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
/* JavaScript Support */
// "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
// "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
/* Emit */
// "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
// "sourceMap": true, /* Create source map files for emitted JavaScript files. */
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
// "noEmit": true, /* Disable emitting files from a compilation. */
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
// "outDir": "./", /* Specify an output folder for all emitted files. */
// "removeComments": true, /* Disable emitting comments. */
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
// "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
// "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
// "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
// "newLine": "crlf", /* Set the newline character for emitting files. */
// "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
// "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */
// "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
// "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */
// "declarationDir": "./", /* Specify the output directory for generated declaration files. */
/* Interop Constraints */
"isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
// "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
// "isolatedDeclarations": true, /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */
"allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
/* Type Checking */
"strict": true, /* Enable all strict type-checking options. */
// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
// "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
// "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
// "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
// "strictBuiltinIteratorReturn": true, /* Built-in iterators are instantiated with a 'TReturn' type of 'undefined' instead of 'any'. */
// "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
// "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
// "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
// "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
// "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
// "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
// "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
/* Completeness */
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
"skipLibCheck": true /* Skip type checking all .d.ts files. */
}
}
@@ -0,0 +1,17 @@
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react-swc';
export default defineConfig({
plugins: [react()],
server: {
host: '0.0.0.0', // Bind to all interfaces
port: 5173, // Back to default Vite port
proxy: {
// Proxy /api requests to the backend server
'/connect': {
target: 'http://0.0.0.0:7860', // Replace with your backend URL if needed
changeOrigin: true,
},
},
},
});