Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 0 additions & 26 deletions .claude/settings.local.json

This file was deleted.

2 changes: 0 additions & 2 deletions .github/workflows/tauri-build-win-official.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ jobs:
APP_SERVER_SECRET_KEY: ${{ secrets.APP_SERVER_SECRET_KEY }}
APP_UPDATER_CHECK_URL: ${{ secrets.APP_UPDATER_CHECK_URL }}
APP_UPDATER_LATEST_JSON_URL: ${{ secrets.APP_UPDATER_LATEST_JSON_URL }}
APP_RUNTIME_LATEST_JSON_URL: ${{ secrets.APP_RUNTIME_LATEST_JSON_URL }}
APP_UPDATER_TEMP_DIR: ${{ secrets.APP_UPDATER_TEMP_DIR }}
APP_WEBVIEW_DOWNLOAD_URL: ${{ secrets.APP_WEBVIEW_DOWNLOAD_URL }}

Expand Down Expand Up @@ -136,7 +135,6 @@ jobs:
Set-ConfigValue '^(secret_key\s*=\s*)".*"$' "${{ env.APP_SERVER_SECRET_KEY }}"
Set-ConfigValue '^(check_url\s*=\s*)".*"$' "${{ env.APP_UPDATER_CHECK_URL }}"
Set-ConfigValue '^(latest_json_url\s*=\s*)".*"$' "${{ env.APP_UPDATER_LATEST_JSON_URL }}"
Set-ConfigValue '^(runtime_latest_json_url\s*=\s*)".*"$' "${{ env.APP_RUNTIME_LATEST_JSON_URL }}"
Set-ConfigValue '^(updater_temp_dir\s*=\s*)".*"$' "${{ env.APP_UPDATER_TEMP_DIR }}"
Set-ConfigValue '^(downlaod_url\s*=\s*)".*"$' "${{ env.APP_WEBVIEW_DOWNLOAD_URL }}"

Expand Down
2 changes: 0 additions & 2 deletions .github/workflows/tauri-release-win.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ jobs:
APP_SERVER_SECRET_KEY: ${{ secrets.APP_SERVER_SECRET_KEY }}
APP_UPDATER_CHECK_URL: ${{ secrets.APP_UPDATER_CHECK_URL }}
APP_UPDATER_LATEST_JSON_URL: ${{ secrets.APP_UPDATER_LATEST_JSON_URL }}
APP_RUNTIME_LATEST_JSON_URL: ${{ secrets.APP_RUNTIME_LATEST_JSON_URL }}
APP_UPDATER_TEMP_DIR: ${{ secrets.APP_UPDATER_TEMP_DIR }}
APP_WEBVIEW_DOWNLOAD_URL: ${{ secrets.APP_WEBVIEW_DOWNLOAD_URL }}
run: |
Expand Down Expand Up @@ -82,7 +81,6 @@ jobs:
Set-ConfigValue '^(secret_key\s*=\s*)".*"$' "${{ env.APP_SERVER_SECRET_KEY }}"
Set-ConfigValue '^(check_url\s*=\s*)".*"$' "${{ env.APP_UPDATER_CHECK_URL }}"
Set-ConfigValue '^(latest_json_url\s*=\s*)".*"$' "${{ env.APP_UPDATER_LATEST_JSON_URL }}"
Set-ConfigValue '^(runtime_latest_json_url\s*=\s*)".*"$' "${{ env.APP_RUNTIME_LATEST_JSON_URL }}"
Set-ConfigValue '^(updater_temp_dir\s*=\s*)".*"$' "${{ env.APP_UPDATER_TEMP_DIR }}"
Set-ConfigValue '^(downlaod_url\s*=\s*)".*"$' "${{ env.APP_WEBVIEW_DOWNLOAD_URL }}"

Expand Down
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ dist-ssr
src/core/plugin/loader/plugin-imports.generated.ts

# tauri generated files
src-tauri/target
src-tauri/target
src-tauri/crates/*/target/
src-tauri/crates/*/Cargo.lock

# packages
packages
Expand Down
3 changes: 0 additions & 3 deletions CLAUDE.md

This file was deleted.

2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ Current high-value contribution areas include:
- Frontend UX polish and workflow consistency
- Tests, regression coverage, and release verification

Broader collaboration around additional core components is planned over time, including the runtime process (`simprint-runtime`) and the browser-kernel layer (`simprint-browser-kernel`). For now, contributions to this public repository are still highly valuable and help make the overall ecosystem easier to maintain.
The environment runtime is maintained in this repository under `src-tauri/crates/runtime`; the browser-kernel layer (`simprint-browser-kernel`) remains a separate component. Changes to environment lifecycle behavior should include tests in the embedded runtime crate whenever possible.

## Communication

Expand Down
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,6 @@ Current high-value contribution areas include:

Issues and pull requests are welcome. If you are interested in contributing on a longer horizon, please open an issue or discussion to introduce yourself and mention the areas you want to help maintain.

Additional core components are also being prepared for broader collaboration over time, including the runtime process (`simprint-runtime`) and the browser-kernel layer (`simprint-browser-kernel`). The long-term goal is to build a maintainable open ecosystem around Simprint rather than keep contribution limited to the client surface.

## Friend Links

- [LINUX DO - 新的理想型社区](https://linux.do/)
Expand Down
2 changes: 0 additions & 2 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,6 @@ Simprint 目前正处于持续推进的开源迁移阶段,我们希望逐步

欢迎提交 Issue 和 Pull Request。如果你希望长期参与维护,也欢迎通过 Issue 或 Discussion 简单介绍自己,并说明你希望参与的方向。

包括运行时进程(`simprint-runtime`)和浏览器内核层(`simprint-browser-kernel`)在内的更多核心组件,后续也会逐步为更广泛的协作做准备。我们的长期目标不是只开放客户端表层代码,而是逐步建设一个可持续维护的 Simprint 开源生态。

## Friend Links

- [LINUX DO - 新的理想型社区](https://linux.do/)
Expand Down
18 changes: 18 additions & 0 deletions src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ directories = "6.0.0"
rmp-serde = "1.3" # MessagePack 序列化
serde_bytes = "0.11" # 字节数组序列化
indexmap = { version = "2.12.0", features = ["serde"] }
runtime = { path = "crates/runtime" }

hkdf = "0.12"

Expand Down
153 changes: 5 additions & 148 deletions src-tauri/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,19 @@ mod crypto;
// =============================================================================

fn main() {
// 1. 准备 simprint-runtime 资源
runtime_assets::ensure_simprint_runtime_downloaded();

// 2. 仅在生产环境下下载 / 准备 webview-fixed 目录中的资源
// 1. 仅在生产环境下下载 / 准备 webview-fixed 目录中的资源
#[cfg(feature = "production")]
{
webview_assets::ensure_webview_fixed_downloaded();
}

// 3. 构建 Tauri 应用(处理 Windows manifest / 权限等)
// 2. 构建 Tauri 应用(处理 Windows manifest / 权限等)
tauri_build_pipeline::build_tauri();

// 4. 为前端构建写入环境标记文件(.build-env)
// 3. 为前端构建写入环境标记文件(.build-env)
frontend_env::prepare_frontend_build_env();

// 5. 读取明文配置并生成加密后的二进制配置文件
// 4. 读取明文配置并生成加密后的二进制配置文件
config_encrypt::generate_encrypted_config();
}

Expand Down Expand Up @@ -71,147 +68,7 @@ pub(crate) fn current_config_file_name() -> &'static str {
}

// =============================================================================
// 模块一:Runtime 资源下载
// =============================================================================

mod runtime_assets {
use super::*;
use sha2::{Digest, Sha256};

const RUNTIME_RESOURCE_PATH: &str = "resources/simprint-runtime.exe";

#[derive(Deserialize)]
struct UpdaterConfig {
runtime_latest_json_url: String,
}

#[derive(Deserialize)]
struct RuntimeLatestRelease {
platforms: std::collections::HashMap<String, RuntimeLatestReleasePlatform>,
}

#[derive(Deserialize)]
struct RuntimeLatestReleasePlatform {
url: String,
sha256: String,
}

pub fn ensure_simprint_runtime_downloaded() {
println!("cargo:rerun-if-changed={}", RUNTIME_RESOURCE_PATH);

let target_path = Path::new(RUNTIME_RESOURCE_PATH);
if target_path.exists() {
return;
}

if let Some(parent) = target_path.parent() {
fs::create_dir_all(parent).unwrap_or_else(|error| {
panic!(
"[BUILD ERROR] Failed to create runtime resources directory '{}': {}",
parent.display(),
error
);
});
}

let latest_json_url = detect_runtime_latest_json_url().unwrap_or_else(|| {
panic!(
"[BUILD ERROR] Failed to detect runtime latest.json URL from config file '{}'.",
super::current_config_file_name()
);
});

if let Err(error) = download_runtime_artifact(&latest_json_url, target_path) {
panic!("failed to download simprint-runtime: {error}");
}
}

fn detect_runtime_latest_json_url() -> Option<String> {
let config_file_name = super::current_config_file_name();

let config = Config::builder()
.add_source(config::File::with_name(config_file_name))
.build()
.map_err(|e| {
eprintln!(
"[BUILD ERROR] Failed to load config file '{}': {}",
config_file_name, e
);
e
})
.ok()?;

let updater_config: UpdaterConfig = config
.get("updater")
.map_err(|e| {
eprintln!(
"[BUILD ERROR] Failed to parse [updater] section in '{}': {}",
config_file_name, e
);
e
})
.ok()?;

Some(updater_config.runtime_latest_json_url)
}

fn download_runtime_artifact(
latest_json_url: &str,
target_path: &Path,
) -> Result<(), Box<dyn std::error::Error>> {
println!(
"cargo:warning=Downloading simprint-runtime metadata from {}",
latest_json_url
);

let client = reqwest::blocking::Client::builder().build()?;
let manifest = client
.get(latest_json_url)
.send()?
.error_for_status()?
.json::<RuntimeLatestRelease>()?;

let target_triple = env::var("TARGET")?;
let platform = manifest.platforms.get(&target_triple).ok_or_else(|| {
format!(
"runtime latest.json does not contain target platform '{}'",
target_triple
)
})?;

if platform.url.trim().is_empty() {
return Err("runtime latest.json url is empty".into());
}

println!(
"cargo:warning=Downloading simprint-runtime binary from {}",
platform.url
);

let bytes = client.get(&platform.url).send()?.error_for_status()?.bytes()?;

let actual_sha256 = sha256_hex(&bytes);
if !actual_sha256.eq_ignore_ascii_case(&platform.sha256) {
return Err(format!(
"runtime sha256 mismatch: expected {}, actual {}",
platform.sha256, actual_sha256
)
.into());
}

fs::write(target_path, &bytes)?;
Ok(())
}

fn sha256_hex(bytes: &[u8]) -> String {
let mut hasher = Sha256::new();
hasher.update(bytes);
format!("{:x}", hasher.finalize())
}
}

// =============================================================================
// 模块二:Webview 资源下载与解压
// 模块一:Webview 资源下载与解压
// =============================================================================

mod webview_assets {
Expand Down
1 change: 0 additions & 1 deletion src-tauri/config.example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ secret_key = "Nuexz9Y2hRc5Z6HK7Atb"
[updater]
check_url = "https://update.simprint.app/api/v1/versions/check"
latest_json_url = "https://pub-39307a5e69c74324855a762027cbf9bf.r2.dev/latest.json"
runtime_latest_json_url = "https://pub-d9427ecc5980437ba1445fc79ea593bd.r2.dev/simprint-runtime/latest.json"
updater_temp_dir = "updates"

[webview]
Expand Down
31 changes: 31 additions & 0 deletions src-tauri/crates/runtime/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
[package]
name = "runtime"
version = "0.1.0"
edition = "2024"
publish = false
license = "AGPL-3.0-only"
autobins = false

[lib]
name = "runtime"
path = "src/lib.rs"

[dependencies]
async-trait = "0.1"
bytes = "1"
log = "0.4"
rand = "0.8"
rmp-serde = "1.3"
reqwest = { version = "0.12.22", features = ["json"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
thiserror = "2.0.12"
tokio = { version = "1", features = ["macros", "rt-multi-thread", "io-util", "sync", "time", "net", "process"] }

[target.'cfg(windows)'.dependencies]
windows = { version = "0.61.1", features = [
"Win32_Foundation",
"Win32_Security",
"Win32_System_JobObjects",
"Win32_System_Threading",
] }
12 changes: 12 additions & 0 deletions src-tauri/crates/runtime/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Embedded environment runtime

This crate owns browser process supervision, the browser EventBus, environment status, CDP
endpoints, authentication propagation, and synchronized-input routing.

It intentionally has no binary target. The Tauri application creates `RuntimeHost` in-process and
forwards runtime events to the existing frontend event names. Chrome remains a separate supervised
process and communicates with this crate through the per-environment EventBus transport.

A browser launch is successful only after the browser process connects and completes the EventBus
handshake. Process exit, transport failure, or the startup deadline transitions the environment to
`error` and emits `environment.launch_failed`.
Loading
Loading