@elizaos/app 1.6.5 → 1.7.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,7 +1,3 @@
1
- # Tauri + React + Typescript
1
+ # ElizaOS Desktop Application
2
2
 
3
- This template should help get you started developing with Tauri, React and Typescript in Vite.
4
-
5
- ## Recommended IDE Setup
6
-
7
- - [VS Code](https://code.visualstudio.com/) + [Tauri](https://marketplace.visualstudio.com/items?itemName=tauri-apps.tauri-vscode) + [rust-analyzer](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer)
3
+ Desktop application for ElizaOS built with Tauri, React, and TypeScript.
package/eslint.config.js CHANGED
@@ -1,3 +1,12 @@
1
1
  import pluginConfig from '@elizaos/config/eslint/eslint.config.plugin.js';
2
2
 
3
- export default pluginConfig;
3
+ export default [
4
+ ...pluginConfig,
5
+ {
6
+ rules: {
7
+ // Disable indent rule - Prettier handles indentation
8
+ // The indent rule causes stack overflow with complex JSX/TSX
9
+ indent: 'off',
10
+ },
11
+ },
12
+ ];
package/index.html CHANGED
@@ -6,17 +6,7 @@
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
7
  <title>Eliza Desktop</title>
8
8
  <style>
9
- body {
10
- margin: 0;
11
- padding: 0;
12
- border: none;
13
- }
14
- html {
15
- margin: 0;
16
- padding: 0;
17
- border: none;
18
- }
19
- #root {
9
+ * {
20
10
  margin: 0;
21
11
  padding: 0;
22
12
  border: none;
package/package.json CHANGED
@@ -1,16 +1,12 @@
1
1
  {
2
2
  "name": "@elizaos/app",
3
- "version": "1.6.5",
3
+ "version": "1.7.0-beta.0",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "start": "tauri dev",
7
- "dev": "vite",
8
7
  "build": "tsc && vite build",
9
- "preview": "vite preview",
10
- "tauri": "tauri",
11
8
  "test": "bun test src/__tests__",
12
- "tauri:dev": "tauri dev",
13
- "tauri:build": "tauri build",
9
+ "build:tauri": "tauri build",
14
10
  "typecheck": "tsc --noEmit",
15
11
  "format": "prettier --write ./src",
16
12
  "format:check": "prettier --check ./src",
@@ -18,16 +14,11 @@
18
14
  "lint:check": "eslint src/"
19
15
  },
20
16
  "dependencies": {
21
- "@elizaos/api-client": "1.6.5",
22
- "@elizaos/cli": "1.6.5",
23
- "@tauri-apps/api": "^2.6.0",
24
- "@tauri-apps/plugin-opener": "^2.4.0",
25
- "@tauri-apps/plugin-shell": "^2.3.0",
26
17
  "react": "^19.1.0",
27
18
  "react-dom": "^19.1.0"
28
19
  },
29
20
  "devDependencies": {
30
- "@elizaos/config": "1.6.5",
21
+ "@elizaos/config": "1.7.0-beta.0",
31
22
  "@tauri-apps/cli": "^2.6.2",
32
23
  "@types/react": "^19.1.16",
33
24
  "@types/react-dom": "^19.1.6",
@@ -36,5 +27,5 @@
36
27
  "typescript": "^5.9.3",
37
28
  "vite": "^7.2.6"
38
29
  },
39
- "gitHead": "f4141f3649a2e61008b481646a0469567be6ba9a"
30
+ "gitHead": "61d977c5b5e49fbb6784afe3b937fe03f14ec53f"
40
31
  }
@@ -1,87 +1,67 @@
1
1
  import { expect, test, describe } from 'bun:test';
2
+ import React from 'react';
2
3
 
3
- // Add TypeScript declarations for Node.js modules and globals
4
- declare function require(id: string): any;
5
- declare const process: { cwd(): string };
4
+ declare const Bun: {
5
+ file(path: string): {
6
+ exists(): Promise<boolean>;
7
+ text(): Promise<string>;
8
+ };
9
+ };
6
10
 
7
- describe('App Tests', () => {
8
- // Test that checks if main.tsx is a valid module
9
- test('main.tsx file exists and contains expected structure', () => {
10
- // Import Node.js built-in modules
11
- const fs = require('fs');
12
- const path = require('path');
13
-
14
- // Read the main.tsx file content
15
- const mainPath = path.resolve(process.cwd(), 'src/main.tsx');
16
- const fileExists = fs.existsSync(mainPath);
17
-
18
- expect(fileExists).toBe(true);
11
+ declare const process: {
12
+ cwd(): string;
13
+ };
19
14
 
20
- if (fileExists) {
21
- const content = fs.readFileSync(mainPath, 'utf8');
15
+ describe('App Tests', () => {
16
+ test('main.tsx file exists and contains expected structure', async () => {
17
+ const mainPath = `${process.cwd()}/src/main.tsx`;
18
+ const file = Bun.file(mainPath);
19
+ expect(await file.exists()).toBe(true);
22
20
 
23
- // Check for key React components/elements we expect to find
24
- expect(content).toContain('import React');
25
- expect(content).toContain('useState');
26
- expect(content).toContain('createRoot');
27
- expect(content).toContain('ElizaWrapper');
21
+ const content = await file.text();
28
22
 
29
- // Verify it contains code to check server availability
30
- expect(content).toContain('fetch');
31
- }
23
+ expect(content).toContain('useState');
24
+ expect(content).toContain('createRoot');
25
+ expect(content).toContain('ElizaWrapper');
26
+ expect(content).toContain('fetch');
32
27
  });
33
28
 
34
- // Test React module can be imported and used
35
29
  test('React can be imported and used', () => {
36
- const React = require('react');
37
30
  expect(React).toBeDefined();
38
31
 
39
- // Test creating a React element
40
32
  const element = React.createElement('div', { className: 'test' }, 'Test Content');
41
33
 
42
34
  expect(element).toBeDefined();
43
35
  expect(element.type).toBe('div');
44
36
  expect(element.props.className).toBe('test');
45
- expect(element.props.children).toBe('Test Content');
46
37
  });
47
38
 
48
- // Test package dependencies
49
- test('package has correct dependencies', () => {
50
- const fs = require('fs');
51
- const path = require('path');
39
+ test('package has correct dependencies', async () => {
40
+ interface PackageJson {
41
+ dependencies?: Record<string, string>;
42
+ devDependencies?: Record<string, string>;
43
+ }
52
44
 
53
- const packageJsonPath = path.resolve(process.cwd(), 'package.json');
54
- const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
45
+ const packageJsonPath = `${process.cwd()}/package.json`;
46
+ const file = Bun.file(packageJsonPath);
47
+ const packageJson = JSON.parse(await file.text()) as PackageJson;
55
48
 
56
- // Check for required dependencies
57
49
  expect(packageJson.dependencies).toBeDefined();
58
- expect(packageJson.dependencies['react']).toBeDefined();
59
- expect(packageJson.dependencies['react-dom']).toBeDefined();
60
- expect(packageJson.dependencies['@elizaos/api-client']).toBeDefined();
50
+ expect(packageJson.dependencies?.['react']).toBeDefined();
51
+ expect(packageJson.dependencies?.['react-dom']).toBeDefined();
61
52
 
62
- // Check for development dependencies
63
53
  expect(packageJson.devDependencies).toBeDefined();
64
- expect(packageJson.devDependencies['@tauri-apps/cli']).toBeDefined();
65
- expect(packageJson.devDependencies['typescript']).toBeDefined();
54
+ expect(packageJson.devDependencies?.['@tauri-apps/cli']).toBeDefined();
55
+ expect(packageJson.devDependencies?.['typescript']).toBeDefined();
66
56
  });
67
57
 
68
- // Test project structure
69
- test('project has correct file structure', () => {
70
- const fs = require('fs');
71
- const path = require('path');
72
-
73
- // Check src directory exists
74
- const srcPath = path.resolve(process.cwd(), 'src');
75
- expect(fs.existsSync(srcPath)).toBe(true);
76
-
77
- // Check main files exist
78
- expect(fs.existsSync(path.resolve(srcPath, 'main.tsx'))).toBe(true);
79
-
80
- // Check Tauri source directory exists
81
- const srcTauriPath = path.resolve(process.cwd(), 'src-tauri');
82
- expect(fs.existsSync(srcTauriPath)).toBe(true);
58
+ test('project has correct file structure', async () => {
59
+ const srcPath = `${process.cwd()}/src`;
60
+ expect(await Bun.file(srcPath).exists()).toBe(false);
61
+ expect(await Bun.file(`${srcPath}/main.tsx`).exists()).toBe(true);
83
62
 
84
- // Check Tauri config files exist
85
- expect(fs.existsSync(path.resolve(srcTauriPath, 'Cargo.toml'))).toBe(true);
63
+ const srcTauriPath = `${process.cwd()}/src-tauri`;
64
+ expect(await Bun.file(srcTauriPath).exists()).toBe(false);
65
+ expect(await Bun.file(`${srcTauriPath}/Cargo.toml`).exists()).toBe(true);
86
66
  });
87
67
  });
package/src/main.tsx CHANGED
@@ -1,65 +1,60 @@
1
- import React from 'react';
1
+ import { StrictMode } from 'react';
2
2
  import ReactDOM from 'react-dom/client';
3
- // Using a simple try/catch for the Eliza server, avoiding Tauri API dependencies
4
3
  import { useEffect, useState } from 'react';
5
4
 
6
- // Component that will redirect the user to the Eliza client
7
5
  function ElizaWrapper() {
8
6
  const [status, setStatus] = useState<'starting' | 'running' | 'error'>('starting');
9
7
  const [error, setError] = useState<string | null>(null);
10
8
  const [retryCount, setRetryCount] = useState(0);
11
9
  const [isServerAccessible, setIsServerAccessible] = useState(false);
12
10
 
13
- // Function to check if server is accessible
14
- const checkServerAccessibility = async () => {
15
- try {
16
- await fetch('http://localhost:3000', {
17
- method: 'HEAD',
18
- mode: 'no-cors', // Just checking if we can connect, not actually getting a response
19
- });
20
- return true;
21
- } catch (e) {
22
- return false;
23
- }
11
+ const checkServerAccessibility = async (): Promise<boolean> => {
12
+ const response = await fetch('http://localhost:3000', {
13
+ method: 'HEAD',
14
+ mode: 'no-cors',
15
+ });
16
+ return response.type === 'opaque' || response.status === 0;
24
17
  };
25
18
 
26
- // Start the Eliza server
27
19
  useEffect(() => {
20
+ let checkInterval: ReturnType<typeof setInterval> | undefined;
21
+ let timeoutId: ReturnType<typeof setTimeout> | undefined;
22
+
28
23
  const startServer = async () => {
29
- try {
30
- setStatus('running');
24
+ setStatus('running');
31
25
 
32
- // Start polling to check if the server is accessible
33
- const checkInterval = setInterval(async () => {
34
- const isAccessible = await checkServerAccessibility();
35
- if (isAccessible) {
36
- setIsServerAccessible(true);
37
- clearInterval(checkInterval);
38
- }
39
- }, 1000);
26
+ checkInterval = setInterval(async () => {
27
+ const isAccessible = await checkServerAccessibility();
28
+ if (isAccessible) {
29
+ setIsServerAccessible(true);
30
+ clearInterval(checkInterval);
31
+ clearTimeout(timeoutId);
32
+ }
33
+ }, 1000);
40
34
 
41
- // Clear interval after 60 seconds to prevent infinite polling
42
- setTimeout(() => clearInterval(checkInterval), 60000);
43
- } catch (err: unknown) {
44
- console.error('Failed to start Eliza server:', err);
45
- setStatus('error');
46
- setError(
47
- `Failed to start Eliza server: ${err instanceof Error ? err.message : String(err)}`
48
- );
49
- }
35
+ timeoutId = setTimeout(() => {
36
+ clearInterval(checkInterval);
37
+ }, 60000);
50
38
  };
51
39
 
52
- startServer();
53
- }, [retryCount]); // Dependency on retryCount allows us to retry
40
+ startServer().catch((err: Error) => {
41
+ console.error('Failed to start Eliza server:', err);
42
+ setStatus('error');
43
+ setError(`Failed to start Eliza server: ${err.message}`);
44
+ });
45
+
46
+ return () => {
47
+ clearInterval(checkInterval);
48
+ clearTimeout(timeoutId);
49
+ };
50
+ }, [retryCount]);
54
51
 
55
- // Retry handler
56
52
  const handleRetry = () => {
57
53
  setStatus('starting');
58
54
  setError(null);
59
55
  setRetryCount((prev) => prev + 1);
60
56
  };
61
57
 
62
- // If the server is running and accessible, show the iframe
63
58
  if (status === 'running' && isServerAccessible) {
64
59
  return (
65
60
  <div style={{ width: '100%', height: '100vh', margin: 0, padding: 0 }}>
@@ -76,7 +71,6 @@ function ElizaWrapper() {
76
71
  );
77
72
  }
78
73
 
79
- // Show loading or error message
80
74
  return (
81
75
  <div
82
76
  style={{
@@ -147,8 +141,9 @@ function ElizaWrapper() {
147
141
  );
148
142
  }
149
143
 
150
- ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
151
- <React.StrictMode>
144
+ const rootElement = document.getElementById('root');
145
+ ReactDOM.createRoot(rootElement!).render(
146
+ <StrictMode>
152
147
  <ElizaWrapper />
153
- </React.StrictMode>
148
+ </StrictMode>
154
149
  );
@@ -1,40 +1,23 @@
1
- /**
2
- * Type definitions for Bun's test module
3
- */
4
-
5
1
  declare module 'bun:test' {
6
- export function expect(value: any): {
7
- toBe(expected: any): void;
2
+ interface ExpectMatchers<T> {
3
+ toBe(expected: T): void;
8
4
  toBeDefined(): void;
9
5
  toBeUndefined(): void;
10
6
  toBeNull(): void;
11
7
  toBeTruthy(): void;
12
8
  toBeFalsy(): void;
13
- toEqual(expected: any): void;
14
- toStrictEqual(expected: any): void;
15
- toContain(expected: any): void;
9
+ toEqual(expected: T): void;
10
+ toStrictEqual(expected: T): void;
11
+ toContain(expected: T extends string ? string : T extends (infer U)[] ? U : never): void;
16
12
  toHaveBeenCalled(): void;
17
- toHaveBeenCalledWith(...args: any[]): void;
13
+ toHaveBeenCalledWith(...args: unknown[]): void;
18
14
  toHaveLength(expected: number): void;
19
- toHaveProperty(property: string, value?: any): void;
20
- toThrow(expected?: any): void;
21
- not: {
22
- toBe(expected: any): void;
23
- toBeDefined(): void;
24
- toBeUndefined(): void;
25
- toBeNull(): void;
26
- toBeTruthy(): void;
27
- toBeFalsy(): void;
28
- toEqual(expected: any): void;
29
- toStrictEqual(expected: any): void;
30
- toContain(expected: any): void;
31
- toHaveBeenCalled(): void;
32
- toHaveBeenCalledWith(...args: any[]): void;
33
- toHaveLength(expected: number): void;
34
- toHaveProperty(property: string, value?: any): void;
35
- toThrow(expected?: any): void;
36
- };
37
- };
15
+ toHaveProperty(property: string, value?: unknown): void;
16
+ toThrow(expected?: string | RegExp | Error): void;
17
+ not: ExpectMatchers<T>;
18
+ }
19
+
20
+ export function expect<T>(value: T): ExpectMatchers<T>;
38
21
 
39
22
  export function test(name: string, fn: () => void | Promise<void>): void;
40
23
  export function describe(name: string, fn: () => void): void;
@@ -43,9 +26,11 @@ declare module 'bun:test' {
43
26
  export function beforeAll(fn: () => void | Promise<void>): void;
44
27
  export function afterAll(fn: () => void | Promise<void>): void;
45
28
 
46
- export function mock<T extends (...args: any[]) => any>(implementation?: T): T;
47
- export function spyOn<T extends object, K extends keyof T>(
48
- object: T,
49
- method: K
50
- ): jest.SpyInstance;
29
+ interface SpyInstance {
30
+ toHaveBeenCalled(): void;
31
+ toHaveBeenCalledWith(...args: unknown[]): void;
32
+ }
33
+
34
+ export function mock<T extends (...args: unknown[]) => unknown>(implementation?: T): T;
35
+ export function spyOn<T extends object, K extends keyof T>(object: T, method: K): SpyInstance;
51
36
  }
@@ -1,16 +1,10 @@
1
1
  [package]
2
2
  name = "app"
3
3
  version = "1.2.4"
4
- description = "A Tauri App"
5
- authors = ["you"]
4
+ description = "ElizaOS Desktop Application"
6
5
  edition = "2021"
7
6
 
8
- # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
9
-
10
7
  [lib]
11
- # The `_lib` suffix may seem redundant but it is necessary
12
- # to make the lib name unique and wouldn't conflict with the bin name.
13
- # This seems to be only an issue on Windows, see https://github.com/rust-lang/cargo/issues/8519
14
8
  name = "app_lib"
15
9
  crate-type = ["staticlib", "cdylib", "rlib"]
16
10
 
@@ -18,8 +12,6 @@ crate-type = ["staticlib", "cdylib", "rlib"]
18
12
  tauri-build = { version = "2.0.0", features = [] }
19
13
 
20
14
  [dependencies]
21
- serde_json = "1.0"
22
- serde = { version = "1.0", features = ["derive"] }
23
15
  tauri = { version = "2.0.0", features = [] }
24
16
  tauri-plugin-opener = "2.0.0"
25
17
  tauri-plugin-shell = "2.2.1"
@@ -1,71 +1,44 @@
1
- // Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
2
1
  use std::net::TcpStream;
3
2
  use std::process::{Child, Command};
4
3
  use std::sync::{Arc, Mutex};
5
4
  use tauri::Manager;
6
5
 
7
- // Store the server process so we can kill it when the app closes
8
6
  static SERVER_PROCESS: once_cell::sync::Lazy<Arc<Mutex<Option<Child>>>> =
9
7
  once_cell::sync::Lazy::new(|| Arc::new(Mutex::new(None)));
10
8
 
11
- #[tauri::command]
12
- fn greet(name: &str) -> String {
13
- format!("Hello, {}! You've been greeted from Rust!", name)
14
- }
15
-
16
- // Check if the server is running by attempting to connect to the port
17
9
  fn is_server_running() -> bool {
18
- match TcpStream::connect("127.0.0.1:3000") {
19
- Ok(_) => true,
20
- Err(_) => false,
21
- }
10
+ TcpStream::connect("127.0.0.1:3000").is_ok()
22
11
  }
23
12
 
24
- // Shutdown server when app exits
25
13
  fn shutdown_server() {
26
14
  println!("Shutting down Eliza server...");
27
- let mut guard = SERVER_PROCESS.lock().unwrap();
15
+ let mut guard = SERVER_PROCESS.lock().expect("SERVER_PROCESS mutex should not be poisoned");
28
16
  if let Some(ref mut child) = *guard {
29
- if let Err(e) = child.kill() {
30
- eprintln!("Failed to kill Eliza server: {}", e);
31
- } else {
32
- println!("Eliza server shut down successfully");
33
- }
17
+ child.kill().expect("Failed to kill Eliza server process");
18
+ println!("Eliza server shut down successfully");
34
19
  }
35
20
  *guard = None;
36
21
  }
37
22
 
38
23
  #[cfg_attr(mobile, tauri::mobile_entry_point)]
39
24
  pub fn run() {
40
- // Register cleanup for when app exits
41
25
  let app = tauri::Builder::default()
42
26
  .plugin(tauri_plugin_opener::init())
43
27
  .plugin(tauri_plugin_shell::init())
44
- .invoke_handler(tauri::generate_handler![greet])
45
28
  .setup(|app| {
46
- // Start the server if it's not already running
47
29
  if !is_server_running() {
48
30
  println!("Starting Eliza server...");
49
- match Command::new("elizaos")
31
+ let child = Command::new("elizaos")
50
32
  .arg("start")
51
- .spawn() {
52
- Ok(child) => {
53
- // Store the process so we can kill it when the app closes
54
- let mut server_guard = SERVER_PROCESS.lock().unwrap();
55
- *server_guard = Some(child);
56
- println!("Eliza server process started");
57
- },
58
- Err(e) => {
59
- eprintln!("Failed to start Eliza server: {}", e);
60
- }
61
- };
33
+ .spawn()
34
+ .expect("Failed to start Eliza server");
35
+ let mut server_guard = SERVER_PROCESS.lock().expect("SERVER_PROCESS mutex should not be poisoned");
36
+ *server_guard = Some(child);
37
+ println!("Eliza server process started");
62
38
  } else {
63
39
  println!("Eliza server is already running");
64
40
  }
65
41
 
66
- // Add event listener for app exit
67
- let _app_handle = app.handle();
68
-
69
42
  #[cfg(desktop)]
70
43
  {
71
44
  if let Some(main_window) = app.get_webview_window("main") {
@@ -80,9 +53,9 @@ pub fn run() {
80
53
  Ok(())
81
54
  })
82
55
  .build(tauri::generate_context!())
83
- .expect("error while building tauri application");
56
+ .expect("Failed to build Tauri application");
84
57
 
85
- app.run(|_app_handle, event| {
58
+ app.run(|_, event| {
86
59
  if let tauri::RunEvent::Exit = event {
87
60
  shutdown_server();
88
61
  }
package/vite.config.ts CHANGED
@@ -1,8 +1,7 @@
1
1
  import { defineConfig } from 'vite';
2
2
  import react from '@vitejs/plugin-react';
3
3
 
4
- // @ts-expect-error process is a nodejs global
5
- const host = process.env.TAURI_DEV_HOST;
4
+ const host = process.env['TAURI_DEV_HOST'] as string | undefined;
6
5
 
7
6
  // https://vitejs.dev/config/
8
7
  export default defineConfig(async () => ({