;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports: [AgentComponent]
+ })
+ .compileComponents();
+
+ fixture = TestBed.createComponent(AgentComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/agent/agent.component.ts b/src/app/agent/agent.component.ts
new file mode 100644
index 0000000..8a65335
--- /dev/null
+++ b/src/app/agent/agent.component.ts
@@ -0,0 +1,12 @@
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'app-agent',
+ standalone: true,
+ imports: [],
+ templateUrl: './agent.component.html',
+ styleUrl: './agent.component.css'
+})
+export class AgentComponent {
+
+}
diff --git a/src/app/app.component.css b/src/app/app.component.css
new file mode 100644
index 0000000..7602598
--- /dev/null
+++ b/src/app/app.component.css
@@ -0,0 +1,32 @@
+:root {
+ font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
+ font-size: 16px;
+ line-height: 24px;
+ font-weight: 400;
+ font-synthesis: none;
+ text-rendering: optimizeLegibility;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ -webkit-text-size-adjust: 100%;
+}
+
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+body {
+ margin-top: 0;
+}
+
+main {
+ text-align: center;
+ color: #ffffff;
+ background: #000000;
+ width: 100vw;
+ height: 100vh;
+ top: 0;
+ left: 0;
+ overflow: hidden;
+}
diff --git a/src/app/app.component.html b/src/app/app.component.html
new file mode 100644
index 0000000..b3cb235
--- /dev/null
+++ b/src/app/app.component.html
@@ -0,0 +1,3 @@
+
+
+
diff --git a/src/app/app.component.ts b/src/app/app.component.ts
new file mode 100644
index 0000000..2eadd2a
--- /dev/null
+++ b/src/app/app.component.ts
@@ -0,0 +1,14 @@
+import { Component } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { RouterOutlet } from '@angular/router';
+
+@Component({
+ selector: 'app-root',
+ standalone: true,
+ imports: [CommonModule, RouterOutlet],
+ templateUrl: './app.component.html',
+ styleUrl: './app.component.css'
+})
+export class AppComponent {
+
+}
diff --git a/src/app/app.config.ts b/src/app/app.config.ts
new file mode 100644
index 0000000..966a865
--- /dev/null
+++ b/src/app/app.config.ts
@@ -0,0 +1,8 @@
+import { ApplicationConfig } from "@angular/core";
+import { provideRouter } from "@angular/router";
+
+import { routes } from "./app.routes";
+
+export const appConfig: ApplicationConfig = {
+ providers: [provideRouter(routes)],
+};
diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts
new file mode 100644
index 0000000..b202701
--- /dev/null
+++ b/src/app/app.routes.ts
@@ -0,0 +1,10 @@
+import { Routes } from "@angular/router";
+import { HomeComponent } from "./home/home.component";
+import { ConfigComponent } from "./config/config.component";
+import { AgentComponent } from "./agent/agent.component";
+
+export const routes: Routes = [
+ { path: "", pathMatch: "full", component: HomeComponent },
+ { path: "config", component: ConfigComponent },
+ { path: "agent", component: AgentComponent }
+];
diff --git a/src/app/config.service.spec.ts b/src/app/config.service.spec.ts
new file mode 100644
index 0000000..1c9863a
--- /dev/null
+++ b/src/app/config.service.spec.ts
@@ -0,0 +1,16 @@
+import { TestBed } from '@angular/core/testing';
+
+import { ConfigService } from '../../../../../.config/emacs/backups/!home!naomi!code!deepgram!deepgram-voice-assistant!src!app!config.service.ts~';
+
+describe('ConfigService', () => {
+ let service: ConfigService;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({});
+ service = TestBed.inject(ConfigService);
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+});
diff --git a/src/app/config.service.ts b/src/app/config.service.ts
new file mode 100644
index 0000000..6057948
--- /dev/null
+++ b/src/app/config.service.ts
@@ -0,0 +1,19 @@
+import { Injectable } from '@angular/core';
+import { Config } from "./interfaces/Config";
+
+@Injectable({
+ providedIn: 'root'
+})
+export class ConfigService {
+ public getConfig(): Config | null {
+ const config = localStorage.getItem("config");
+ if (!config) {
+ return null;
+ }
+ return JSON.parse(config) as Config;
+ }
+
+ public setConfig(config: Config) {
+ localStorage.setItem("config", JSON.stringify(config));
+ }
+}
diff --git a/src/app/config/config.component.css b/src/app/config/config.component.css
new file mode 100644
index 0000000..8145836
--- /dev/null
+++ b/src/app/config/config.component.css
@@ -0,0 +1,22 @@
+form {
+ display: grid;
+ grid-template-columns: 200px 400px;
+ margin: auto;
+ width: 600px;
+}
+
+input, select {
+ margin-bottom: 1rem;
+}
+
+.green {
+ background: green;
+}
+
+.red {
+ background: red;
+}
+
+button {
+ border: 2px solid white;
+}
diff --git a/src/app/config/config.component.html b/src/app/config/config.component.html
new file mode 100644
index 0000000..5850607
--- /dev/null
+++ b/src/app/config/config.component.html
@@ -0,0 +1,61 @@
+Configuration
+These settings determine how your Deepgram Voice Agent behaves.
+
+
+
diff --git a/src/app/config/config.component.spec.ts b/src/app/config/config.component.spec.ts
new file mode 100644
index 0000000..2f8e2b0
--- /dev/null
+++ b/src/app/config/config.component.spec.ts
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { ConfigComponent } from './config.component';
+
+describe('ConfigComponent', () => {
+ let component: ConfigComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports: [ConfigComponent]
+ })
+ .compileComponents();
+
+ fixture = TestBed.createComponent(ConfigComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/config/config.component.ts b/src/app/config/config.component.ts
new file mode 100644
index 0000000..6c71e3c
--- /dev/null
+++ b/src/app/config/config.component.ts
@@ -0,0 +1,66 @@
+import { Component } from '@angular/core';
+import { AbstractControl, FormControl, ReactiveFormsModule, Validators } from '@angular/forms';
+import { ConfigService } from '../config.service';
+import { Config } from '../interfaces/Config';
+import type { SpeakModel, ThinkModel, ListenModel } from "../interfaces/Settings";
+
+@Component({
+ selector: 'app-config',
+ standalone: true,
+ imports: [ReactiveFormsModule],
+ templateUrl: './config.component.html',
+ styleUrl: './config.component.css'
+})
+export class ConfigComponent {
+ public apiKey = new FormControl("", [
+ Validators.required
+ ]);
+ public speakModel = new FormControl("aura-athena-en", [
+ Validators.required,
+ () => (control: AbstractControl) => ["aura-asteria-en", "aura-luna-en", "aura-athena-en", "aura-stella-en",
+ "aura-hera-en", "aura-orion-en", "aura-arcas-en", "aura-perseus-en",
+ "aura-angus-en", "aura-orpheus-en", "aura-helios-en", "aura-zeus-en"].includes(control.value)
+ ]);
+ public listenModel = new FormControl("nova-2", [
+ Validators.required,
+ () => (control: AbstractControl) => [ "nova-2", "nova-2-meeting", "nova-2-phonecall", "nova-2-finance",
+ "nova-2-conversationalai", "nova-2-finance", "nova-2-voicemail",
+ "nova-2-video", "nova-2-medical", "nova-2-drivethru", "nova-2-automotive",
+ "nova-2-atc", "nova", "nova-phonecall", "nova-medical", "enhanced",
+ "enhanced-phonecall", "enhanced-meeting", "enhanced-finance", "base",
+ "base-phonecall", "base-meeting", "base-finance", "base-conversationalai",
+ "base-voicemail", "base-video", "whisper-tiny", "whisper-small",
+ "whisper-medium", "whisper-large", "whisper-base"
+].includes(control.value)
+ ]);
+ public thinkModel = new FormControl("claude-3-haiku-20240307", [
+ Validators.required,
+ () => (control: AbstractControl) => ["claude-3-haiku-20240307", "gpt-4o-mini"].includes(control.value)
+ ]);
+
+ public save() {
+ const config: Config = {
+ apiKey: this.apiKey.value ?? "",
+ speakModel: this.speakModel.value as SpeakModel,
+ listenModel: this.listenModel.value as ListenModel,
+ thinkModel: this.thinkModel.value as ThinkModel
+ }
+ this.configService.setConfig(config);
+ window.location.pathname = "/";
+ }
+
+ public cancel() {
+ window.location.pathname = "/";
+ }
+
+ constructor(private configService: ConfigService) {
+ const config = this.configService.getConfig();
+ if (!config) {
+ return;
+ }
+ this.apiKey.setValue(config.apiKey);
+ this.speakModel.setValue(config.speakModel);
+ this.listenModel.setValue(config.listenModel);
+ this.thinkModel.setValue(config.thinkModel);
+ }
+}
diff --git a/src/app/home/home.component.css b/src/app/home/home.component.css
new file mode 100644
index 0000000..27cb876
--- /dev/null
+++ b/src/app/home/home.component.css
@@ -0,0 +1,22 @@
+.btn {
+ border: 2px solid black;
+ width: 200px;
+ text-decoration: none;
+}
+
+.green {
+ background: green;
+ color: white;
+}
+
+.yellow {
+ background: yellow;
+ color: black;
+}
+
+.grid {
+ display: grid;
+ width: 500px;
+ grid-template-columns: 250px 250px;
+ margin: auto;
+}
diff --git a/src/app/home/home.component.html b/src/app/home/home.component.html
new file mode 100644
index 0000000..e9ac515
--- /dev/null
+++ b/src/app/home/home.component.html
@@ -0,0 +1,6 @@
+Deepgram Voice Assistant
+Welcome to your new favourite voice-powered assistant.
+
diff --git a/src/app/home/home.component.spec.ts b/src/app/home/home.component.spec.ts
new file mode 100644
index 0000000..60c47c4
--- /dev/null
+++ b/src/app/home/home.component.spec.ts
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { HomeComponent } from './home.component';
+
+describe('HomeComponent', () => {
+ let component: HomeComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports: [HomeComponent]
+ })
+ .compileComponents();
+
+ fixture = TestBed.createComponent(HomeComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/home/home.component.ts b/src/app/home/home.component.ts
new file mode 100644
index 0000000..deaec52
--- /dev/null
+++ b/src/app/home/home.component.ts
@@ -0,0 +1,12 @@
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'app-home',
+ standalone: true,
+ imports: [],
+ templateUrl: './home.component.html',
+ styleUrl: './home.component.css'
+})
+export class HomeComponent {
+
+}
diff --git a/src/app/interfaces/Config.ts b/src/app/interfaces/Config.ts
new file mode 100644
index 0000000..dc23742
--- /dev/null
+++ b/src/app/interfaces/Config.ts
@@ -0,0 +1,8 @@
+import { ListenModel, SpeakModel, ThinkModel } from "./Settings";
+
+export interface Config {
+ apiKey: string;
+ speakModel: SpeakModel;
+ thinkModel: ThinkModel;
+ listenModel: ListenModel;
+}
diff --git a/src/app/interfaces/Settings.ts b/src/app/interfaces/Settings.ts
new file mode 100644
index 0000000..8b9e9dd
--- /dev/null
+++ b/src/app/interfaces/Settings.ts
@@ -0,0 +1,5 @@
+export type ListenModel = "nova-2" | "nova-2-meeting" | "nova-2-phonecall" | "nova-2-finance" | "nova-2-conversationalai" | "nova-2-voicemail" | "nova-2-video" | "nova-2-medical" | "nova-2-drivethru" | "nova-2-automotive" | "nova-2-atc" | "nova" | "nova-phonecall" | "nova-medical" | "enhanced" | "enhanced-phonecall" | "enhanced-meeting" | "enhanced-finance" | "base" | "base-phonecall" | "base-meeting" | "base-finance" | "base-conversationalai" | "base-voicemail" | "base-video" | "whisper-tiny" | "whisper-small" | "whisper-medium" | "whisper-large" | "whisper-base";
+
+export type ThinkModel = "gpt-4o-mini" | "claude-3-haiku-20240307";
+
+export type SpeakModel = "aura-asteria-en" | "aura-luna-en" | "aura-athena-en" | "aura-stella-en" | "aura-hera-en" | "aura-orion-en" | "aura-arcas-en" | "aura-perseus-en" | "aura-angus-en" | "aura-oprheus-en" | "aura-helios-en" | "aura-zeus-en";
diff --git a/src/index.html b/src/index.html
new file mode 100644
index 0000000..0bc320a
--- /dev/null
+++ b/src/index.html
@@ -0,0 +1,12 @@
+
+
+
+
+ Tauri + Angular
+
+
+
+
+
+
+
diff --git a/src/main.ts b/src/main.ts
new file mode 100644
index 0000000..6829613
--- /dev/null
+++ b/src/main.ts
@@ -0,0 +1,7 @@
+import { bootstrapApplication } from "@angular/platform-browser";
+import { appConfig } from "./app/app.config";
+import { AppComponent } from "./app/app.component";
+
+bootstrapApplication(AppComponent, appConfig).catch((err) =>
+ console.error(err),
+);
diff --git a/tsconfig.app.json b/tsconfig.app.json
new file mode 100644
index 0000000..84f1f99
--- /dev/null
+++ b/tsconfig.app.json
@@ -0,0 +1,10 @@
+/* To learn more about this file see: https://angular.io/config/tsconfig. */
+{
+ "extends": "./tsconfig.json",
+ "compilerOptions": {
+ "outDir": "./out-tsc/app",
+ "types": []
+ },
+ "files": ["src/main.ts"],
+ "include": ["src/**/*.d.ts"]
+}
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000..a799413
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,16 @@
+/* To learn more about this file see: https://angular.io/config/tsconfig. */
+{
+ "extends": "@nhcarrigan/typescript-config",
+ "compilerOptions": {
+ "outDir": "./dist/out-tsc",
+ "target": "ES2022",
+ "module": "ES2022",
+ "lib": ["ES2022", "dom"]
+ },
+ "angularCompilerOptions": {
+ "enableI18nLegacyMessageIdFormat": false,
+ "strictInjectionParameters": true,
+ "strictInputAccessModifiers": true,
+ "strictTemplates": true
+ }
+}