@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 +2 -6
- package/eslint.config.js +10 -1
- package/index.html +1 -11
- package/package.json +4 -13
- package/src/__tests__/main.test.ts +39 -59
- package/src/main.tsx +37 -42
- package/src/types/bun-test.d.ts +19 -34
- package/src-tauri/Cargo.toml +1 -9
- package/src-tauri/src/lib.rs +12 -39
- package/vite.config.ts +1 -2
package/README.md
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
#
|
|
1
|
+
# ElizaOS Desktop Application
|
|
2
2
|
|
|
3
|
-
|
|
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
|
|
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
|
-
|
|
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.
|
|
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
|
|
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.
|
|
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": "
|
|
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
|
-
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
declare const Bun: {
|
|
5
|
+
file(path: string): {
|
|
6
|
+
exists(): Promise<boolean>;
|
|
7
|
+
text(): Promise<string>;
|
|
8
|
+
};
|
|
9
|
+
};
|
|
6
10
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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
|
-
|
|
21
|
-
|
|
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
|
-
|
|
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
|
-
|
|
30
|
-
|
|
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
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
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 =
|
|
54
|
-
const
|
|
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
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
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
|
-
|
|
85
|
-
expect(
|
|
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
|
|
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
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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
|
-
|
|
30
|
-
setStatus('running');
|
|
24
|
+
setStatus('running');
|
|
31
25
|
|
|
32
|
-
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
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
|
-
|
|
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
|
-
|
|
151
|
-
|
|
144
|
+
const rootElement = document.getElementById('root');
|
|
145
|
+
ReactDOM.createRoot(rootElement!).render(
|
|
146
|
+
<StrictMode>
|
|
152
147
|
<ElizaWrapper />
|
|
153
|
-
</
|
|
148
|
+
</StrictMode>
|
|
154
149
|
);
|
package/src/types/bun-test.d.ts
CHANGED
|
@@ -1,40 +1,23 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Type definitions for Bun's test module
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
1
|
declare module 'bun:test' {
|
|
6
|
-
|
|
7
|
-
toBe(expected:
|
|
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:
|
|
14
|
-
toStrictEqual(expected:
|
|
15
|
-
toContain(expected:
|
|
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:
|
|
13
|
+
toHaveBeenCalledWith(...args: unknown[]): void;
|
|
18
14
|
toHaveLength(expected: number): void;
|
|
19
|
-
toHaveProperty(property: string, value?:
|
|
20
|
-
toThrow(expected?:
|
|
21
|
-
not:
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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
|
}
|
package/src-tauri/Cargo.toml
CHANGED
|
@@ -1,16 +1,10 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "app"
|
|
3
3
|
version = "1.2.4"
|
|
4
|
-
description = "
|
|
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"
|
package/src-tauri/src/lib.rs
CHANGED
|
@@ -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
|
-
|
|
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().
|
|
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
|
-
|
|
30
|
-
|
|
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
|
-
|
|
31
|
+
let child = Command::new("elizaos")
|
|
50
32
|
.arg("start")
|
|
51
|
-
.spawn()
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
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("
|
|
56
|
+
.expect("Failed to build Tauri application");
|
|
84
57
|
|
|
85
|
-
app.run(|
|
|
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
|
-
|
|
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 () => ({
|